You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Docker Compose环境变量配置Vite React应用的后端服务名以解决跨服务通信的域名解析问题?

如何通过Docker Compose环境变量配置Vite React应用的后端服务名以解决跨服务通信的域名解析问题?

我来帮你理清这个问题的核心,以及给出几个实用的解决方案:

问题根源:你搞错了前端代码的运行环境!

你以为前端代码是在Docker容器里运行的,所以能直接用Docker服务名backend来访问后端,但实际上React代码最终是在用户的浏览器里执行的,浏览器不在你的Docker网络skystack_net里,自然没法解析Docker内部的服务名,这就是net::ERR_NAME_NOT_RESOLVED报错的原因。而你用宿主机内部IP(比如172.25.176.1)能行,是因为这个IP是浏览器能访问到的宿主机地址,后端容器的5000端口已经映射到了宿主机上。

解决方案一:本地开发时用Vite代理转发请求(最推荐)

既然本地开发时前端跑在浏览器,后端跑在Docker里,我们可以让Vite帮我们把API请求转发到后端容器,这样前端代码不用改,还能避开跨域问题。

  1. 在你的前端项目根目录下修改vite.config.js,添加代理配置:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      // 匹配所有以/api开头的请求
      '/api': {
        target: 'http://localhost:5000', // 后端容器映射到宿主机的地址
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '') // 去掉/api前缀再转发给后端
      }
    }
  }
})
  1. 修改你的前端API请求代码,用相对路径代替硬编码的地址:
// 原来的写法
// const BACKEND_HOST_URL = import.meta.env.VITE_BACKEND_HOST_URL || 'http://localhost:5000';

// 现在的写法,直接用相对路径
const fetchData = async () => {
  const response = await fetch('/api/my-endpoint');
  // ...处理响应
};

这样本地开发时,Vite会把/api/my-endpoint的请求转发到http://localhost:5000/my-endpoint,完全适配你的Docker后端。

解决方案二:Docker部署前端时用反向代理(适合生产环境)

如果要把前端也部署到Docker容器里对外提供服务,推荐用Nginx作为反向代理,把前端和后端的请求都统一处理,这样Nginx在Docker网络里能直接解析backend服务名。

  1. 创建一个Nginx配置文件nginx.conf:
server {
  listen 80;
  server_name localhost;

  # 处理前端静态文件请求
  location / {
    root /usr/share/nginx/html;
    try_files $uri $uri/ /index.html;
  }

  # 处理API请求,转发到后端服务
  location /api {
    proxy_pass http://backend:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}
  1. 修改你的docker-compose.yml,添加Nginx服务,调整前端和后端的端口配置:
version: '3'

services:
  frontend:
    build:
      context: ../frontend
    # 去掉端口映射,让Nginx访问
    environment:
      # 前端打包时用相对路径指向代理地址
      - VITE_BACKEND_HOST_URL=/api
    networks:
      - skystack_net
    depends_on:
      - nginx

  backend:
    build:
      context: ../backend
    # 不需要对外暴露端口,只让Nginx访问
    # ports:
    #   - "5000:5000"
    depends_on:
      - mongodb
    environment:
      - PORT=5000
      - DOCKER_ENV=true
    networks:
      - skystack_net

  mongodb:
    image: mongo:latest
    ports:
      - "27017:27017"
    networks:
      - skystack_net
    volumes:
      - mongo-data:/data/db

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      # 挂载Nginx配置文件
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      # 挂载前端打包后的静态文件
      - ../frontend/dist:/usr/share/nginx/html
    networks:
      - skystack_net
    depends_on:
      - backend

volumes:
  mongo-data:

networks:
  skystack_net:
  1. 前端打包时确保用相对路径,修改vite.config.js添加base: './':
export default defineConfig({
  plugins: [react()],
  base: './'
})

这样用户访问Nginx的80端口时,前端静态文件由Nginx提供,API请求会被转发到Docker网络里的backend:5000,完美解决服务名解析问题。

额外小技巧:兼容本地和Docker两种开发模式

如果你想让前端代码同时支持本地跑(不用Docker)和Docker跑,可以保留环境变量的逻辑,但调整一下:

// 本地开发时用Vite代理的/api,Docker部署时用Nginx代理的/api
const BACKEND_HOST_URL = import.meta.env.VITE_BACKEND_HOST_URL || '/api';

const fetchData = async () => {
  const response = await fetch(`${BACKEND_HOST_URL}/my-endpoint`);
  // ...处理响应
};

这样不管是本地开发还是Docker部署,代码都能正常工作。

备注:内容来源于stack exchange,提问作者Casper Karlsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 15:53:01