You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Docker虚拟网络中Axios调用后端服务失败问题排查

问题分析与解决方案

首先得戳破你遇到的核心误区:你的Vue代码是在用户的浏览器里运行的,不是在vue-frontend容器内部

你在前端容器里能ping通db-user-api(或者那个自动生成的长容器名),是因为容器处于Docker Compose创建的内部网络里,能解析服务的DNS名称。但浏览器属于主机的网络环境,完全看不到Docker的内部网络,自然没法解析这些内部域名——这就是为什么用http://cl-dashboard_db-user-api_1:5000会返回404,而映射端口后用localhost:5000能正常工作的原因。

下面给你几个不同场景下的解决方案:

方案1:用Nginx反向代理统一入口(推荐生产环境)

这是最符合Docker设计理念的做法:用一个Nginx容器作为前端和后端的统一入口,浏览器只需要访问Nginx,Nginx再把请求转发到对应的服务(Nginx和后端服务在同一个Docker网络,能正常解析服务名)。

步骤1:修改docker-compose.yml

version: '3.3'
services:
  nginx-proxy:
    image: nginx:alpine
    ports:
      - "8070:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - vue-frontend
      - db-user-api
  vue-frontend:
    image: flowmotion/vue-js-frontend
    expose:
      - 80  # 只暴露端口给内部网络,不需要映射到主机
  db-user-api:
    image: flowmotion/user-db-api
    environment:
      - PORT=5000
    expose:
      - 5000  # 同样不需要映射到主机

步骤2:创建Nginx配置文件nginx.conf

events {}
http {
  server {
    listen 80;

    # 处理前端静态资源请求
    location / {
      proxy_pass http://vue-frontend:80;
    }

    # 处理后端API请求(这里匹配/login路径,你可以根据实际API路径调整)
    location /login {
      proxy_pass http://db-user-api:5000;
    }

    # 如果你的API都在/api路径下,可以改成这样统一转发:
    # location /api/ {
    #   proxy_pass http://db-user-api:5000/api/;
    # }
  }
}

步骤3:调整Vue的config.js

把baseURL改成空字符串或者相对路径,这样请求会直接发送到当前域名(也就是Nginx的地址),由Nginx转发到后端:

module.exports = {
  userBackendServer: ''
};

这样部署后,浏览器访问http://localhost:8070,前端发起的/login请求会被Nginx自动转发到db-user-api:5000/login,完全利用Docker内部网络,不需要映射后端端口到主机。

方案2:开发环境用Vue CLI代理(快速调试)

如果是开发阶段,不想折腾Nginx,可以用Vue CLI自带的代理功能,让前端开发服务器把API请求转发到后端服务。

修改vue.config.js(如果没有就新建)

module.exports = {
  devServer: {
    proxy: {
      '/login': {
        // 如果前端项目在Docker容器里运行,直接用服务名
        target: 'http://db-user-api:5000',
        // 如果前端在主机上运行,就用映射到主机的端口
        // target: 'http://localhost:5000',
        changeOrigin: true
      }
    }
  }
}

然后同样把config.js里的userBackendServer改成空字符串,这样请求会被代理转发到后端。

方案3:修改主机hosts文件(不推荐)

这个方法是让主机能解析Docker内部的服务名,但不够灵活,适合临时测试:

  1. 先查Docker网络的网关IP:
    docker network inspect cl-dashboard_default | grep Gateway
    
  2. 修改主机的hosts文件:
    • Linux/macOS:/etc/hosts
    • Windows:C:\Windows\System32\drivers\etc\hosts
      添加一行:
    你的网关IP  db-user-api
    
  3. 然后把config.js里的地址改成http://db-user-api:5000,浏览器就能解析这个名称了。

但这个方法的问题是网关IP可能随Docker网络重建而变化,跨环境部署也不方便,所以只适合临时调试用。


内容的提问来源于stack exchange,提问作者Flowmotion

火山引擎 最新活动