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

Docker化Nginx反向代理对接React与Express应用时出现502 Bad Gateway错误的排查求助

排查Docker Compose + Nginx 502 Bad Gateway问题

让我们一步步拆解你遇到的问题,核心原因主要集中在服务依赖顺序、应用监听端口配置以及Nginx代理目标端口匹配这几个点上:

一、最关键的问题:服务启动顺序搞反了

你的docker-compose.yml里让client和server依赖reverse-proxy,这意味着Nginx会先启动,而此时React和Express服务还没就绪。Nginx启动时会尝试解析http://client和http://server,但这两个容器可能还没完全启动,导致Nginx无法建立连接,直接返回502。

修复方案:把依赖关系反过来,让reverse-proxy依赖client和server,确保Nginx在后端服务就绪后再启动:

version: "3"
services:
  reverse-proxy:
    image: mern-reverse-proxy
    build: ./reverse-proxy
    container_name: mern-app-reverse-proxy
    ports:
      - "80:80"
    depends_on: # 这里修改为依赖client和server
      - client
      - server
  client:
    image: mern-react
    build: ./client
    volumes:
      - ./client/:/usr/src/app
      - /usr/src/app/node_modules
    container_name: mern-app-client
    environment:
      CHOKIDAR_USEPOLLING: "true"
      PORT: 3000 # 新增:指定React监听端口
      HOST: 0.0.0.0 # 新增:让React监听所有网卡(容器内必须配置)
  server:
    image: mern-express
    build: ./server
    volumes:
      - ./server/:/usr/src/app
      - /usr/src/app/node_modules
    container_name: mern-app-server
    environment:
      CHOKIDAR_USEPOLLING: "true"

二、应用实际监听端口与配置不匹配

你在Dockerfile里EXPOSE 80,但默认情况下:

  • React的yarn start默认监听3000端口,且只监听localhost(容器内无法被其他容器访问)
  • Express默认监听3000端口(如果你的代码没改的话)

这就导致Nginx尝试代理到服务的80端口时,根本没有服务在监听,直接连接失败。

针对React的修复:

修改React的Dockerfile,把EXPOSE改成实际监听的3000端口:

FROM node:16-alpine3.11
WORKDIR /usr/src/app
COPY ./package.json ./
COPY ./yarn.lock ./
RUN yarn install
COPY . .
EXPOSE 3000 # 从80改成3000
CMD ["yarn", "start"]

针对Express的修复:

  1. 修改Dockerfile的EXPOSE为3000:
FROM node:16-alpine3.11
WORKDIR /usr/src/app
COPY ./package.json ./
COPY ./yarn.lock ./
RUN yarn install
COPY . .
EXPOSE 3000 # 从80改成3000
CMD ["yarn", "start"]
  1. 确保Express代码监听0.0.0.0(容器内必须配置,否则只能本地访问):
// Express入口文件示例
app.listen(3000, '0.0.0.0', () => {
  console.log('Server running on port 3000');
});

三、Nginx代理目标端口需要明确指定

现在你的nginx.conf里proxy_pass http://client和http://server没有指定端口,Nginx会默认用80端口,但我们的服务实际在3000端口运行,所以必须补上端口:

worker_processes 1;
events {
    worker_connections 1024;
}
http {
    sendfile on;
    server {
        listen 80;
        location /api {
            proxy_pass http://server:3000; # 加上3000端口
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $server_name;
        }
        location / {
            proxy_pass http://client:3000; # 加上3000端口
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $server_name;
        }
    }
}

额外排查技巧

如果修改后还是有问题,可以通过以下命令定位:

  1. 进入Nginx容器测试网络连通性:
    docker exec -it mern-app-reverse-proxy ping client
    docker exec -it mern-app-reverse-proxy ping server
    
    能ping通说明Docker网络没问题。
  2. 在Nginx容器内测试服务端口是否可达:
    docker exec -it mern-app-reverse-proxy curl http://client:3000
    docker exec -it mern-app-reverse-proxy curl http://server:3000/api/xxx # 替换成你的API路径
    
    能返回内容说明服务正常,否则检查服务是否启动。
  3. 查看Nginx错误日志:
    docker logs mern-app-reverse-proxy
    
    日志里会明确显示是连接超时还是拒绝连接,帮助快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:22:45