当前端和后端位于虚拟 Docker 网络中时,如何使用 axios 寻址后端主机

Posted

技术标签:

【中文标题】当前端和后端位于虚拟 Docker 网络中时,如何使用 axios 寻址后端主机【英文标题】:How to address backend host with axios, when frontend and backend are in virtual docker network 【发布时间】:2019-10-15 21:55:05 【问题描述】:

我正在构建一个简单的登录网站,我的 vue-frontend 需要从连接到 sql 数据库的 nodejs-backend 检索用户数据。 我决定为此使用 docker-compose,据我了解,docker-compose 会自动为我的 docker-compose.yml 中提到的服务设置网络。

似乎不起作用的是我在代码中处理后端的方式。 我怀疑这可能是因为我使用 axios 向我的后端发送请求的方式。

我已经检查了默认的 docker-network 并且能够使用我在网络配置中找到的 dns 名称从我的前端 ping 到我的后端。 但是在我的代码中使用相同的名称不起作用。

有效的方法是将主机端口映射到我公开的 api 端口并使用http://localhost:5000 作为地址,但这违背了 docker 网络的目的。

我的 docker-compose.yml:

version: '3.3'

services:
    vue-frontend:
        image: flowmotion/vue-js-frontend
        ports:
            - 8070:80
        depends_on:
            - db-user-api

    db-user-api:
        image: flowmotion/user-db-api
        environment:
            - PORT=5000
        ports:
            - 5000:5000 #only needed if docker network connection can't be established 

有问题的 Vue-fontend 文件:

登录.vue

methods: 
    async login() 
      try 
        const response = await authenticationService.login(
          email: this.email,
          password: this.password
        );
        this.$store.dispatch("setToken", response.data.token);
        this.$store.dispatch("setUser", response.data.user);
        this.$router.push( path: "/" );
       catch (error) 
        this.showError = true;
        this.error = error.response.data.error;
      
    
  
;
</script>

authenticationService.js

import api from "@/services/api";

export default 
  login(credentials) 
    return api().post("login", credentials);
  
;

api.js

import axios from 'axios';
import config from '../config/config';
export default () => 
    return axios.create(
        baseURL: config.userBackendServer
    );
;

config.js()

module.exports = 
    userBackendServer: 'http://cl-dashboard_db-user-api_1:5000' //this doesn't seem to work
;

//using 'http://localhost:5000' works if ports are mapped to host machine.

预期结果将是我的后端进行 sql 查找。

实际结果是,我的前端没有连接到我的后端,而是给了我一个 404 状态并且我的后端永远无法到达

【问题讨论】:

【参考方案1】:

你是正确的假设 docker 网络中的容器可以在不向外部世界开放任何端口的情况下相互通信。

要点是-您的 vue 应用程序不在任何容器中-它作为 js 脚本文件从容器提供给您的浏览器,它是将请求发送到您的节点后端的那个。因为您的浏览器无论如何都不在 docker 网络内 - 您必须使用外部端口映射(在您的情况下为 localhost:5000)才能到达后端。

如果您对此还有任何疑问,请告诉我。

【讨论】:

好的,这是有道理的。因此,对于部署,我是否需要使用 docker-compose.yml 中指定的端口指定服务 ip 地址/URI?像这样: userBackendServer: 'URItoMyApp:5000' 把它作为环境变量放在你的.env文件中,在vue应用根目录下。现在它将是VUE_APP_API_ROOT=http://localhost:500/,并在生产中将其更改为您的服务器主机名。您的后端生产容器应该映射到主机默认端口(80 和 443),因此您不需要指定任何端口号。 @hudac 正确,CORS 标头不应在生产中使用。通常的架构会放置一个代理服务器(比如 nginx)来为前端文件提供服务,并将/api/* 请求重定向到后端服务器。例如:cli.vuejs.org/guide/deployment.html#docker-nginx 好的,我找到了这个例子 github.com/wkrzywiec/kanban-board/blob/master/kanban-ui/… - nginx 反向代理,它在内部重定向 /api/* 的调用。谢谢! @Vivere 在生产中,您通常会使用代理来实现前端和后端的相同域名(否则您将面临 CORS),因此您可以从请求的 URL 中删除主机名,默认情况下浏览器将使用前端域名作为主机名(例如,您将 AJAX 发送到“/api/image1.png”),不带主机名。

以上是关于当前端和后端位于虚拟 Docker 网络中时,如何使用 axios 寻址后端主机的主要内容,如果未能解决你的问题,请参考以下文章

【JSON】JSON在前端和后端传递

docker部署前端和后端打包程序

如何在 docker env 中使用 nginx 反向代理通信 UI 和后端应用程序

npm 并发错误?当同时运行前端和后端时?

前端渲染和后端渲染

ProxyPassReverseCookieDomain动态变量