Docker部署Node.js+PM2搭配Nginx反向代理出现502错误排查
问题根源分析
你遇到502错误的核心原因是Docker多阶段构建的逻辑错误:
你的Dockerfile最后阶段基于nginx:alpine镜像,这意味着第一个build阶段的Node应用启动指令(CMD ["pm2-runtime", ...])被完全覆盖了——最终运行的容器里只有Nginx在工作,Node应用根本没有启动。Nginx试图代理到localhost:3000,但这个端口上没有任何服务在监听,所以返回502 Bad Gateway。
解决方案
方案一:用Docker Compose分离Node应用和Nginx(推荐,符合容器单职责原则)
1. 调整Node应用的Dockerfile
删除多阶段构建的Nginx部分,只保留Node+PM2的构建逻辑:
FROM node:14.17.0 WORKDIR /usr/app RUN npm install --global pm2 ENV PM2_PUBLIC_KEY xxxxx ENV PM2_SECRET_KEY xxxxx COPY ./package*.json ./ RUN npm install COPY ./ ./ RUN npm run-script build EXPOSE 3000 CMD [ "pm2-runtime", "start", "npm", "--", "start" ]
2. 创建docker-compose.yml文件
通过Compose管理两个独立容器(Node应用和Nginx代理):
version: '3.8' services: node-app: build: . container_name: node-app expose: - 3000 nginx: image: nginx:alpine container_name: nginx-proxy ports: - "3000:80" volumes: - ./.nginx/nginx.conf:/etc/nginx/nginx.conf depends_on: - node-app
3. 修改Nginx配置的代理目标
把proxy_pass的localhost:3000改成Docker Compose服务名node-app:3000(Docker内部DNS会自动解析到Node容器):
location / { proxy_pass http://node-app:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
4. 启动服务
执行命令:
docker-compose up -d
方案二:将Node和Nginx放在同一个容器(不推荐,仅用于快速验证)
如果你想临时在一个容器里运行两个服务,可以修改Dockerfile,用启动脚本同时启动Node和Nginx:
FROM node:14.17.0 AS build WORKDIR /usr/app RUN npm install --global pm2 ENV PM2_PUBLIC_KEY xxxxx ENV PM2_SECRET_KEY xxxxx COPY ./package*.json ./ RUN npm install COPY ./ ./ RUN npm run-script build FROM nginx:alpine # 安装Node.js(与构建阶段版本匹配) RUN apk add --no-cache nodejs npm # 复制Node应用文件 COPY --from=build /usr/app /usr/app WORKDIR /usr/app # 安装PM2 RUN npm install --global pm2 # 复制Nginx配置 COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf # 创建启动脚本,同时启动PM2和Nginx RUN echo '#!/bin/sh' > /start.sh && \ echo 'pm2-runtime start npm -- start &' >> /start.sh && \ echo 'nginx -g "daemon off;"' >> /start.sh && \ chmod +x /start.sh EXPOSE 3000 80 ENTRYPOINT ["/start.sh"]
启动命令
注意将主机端口映射到容器的80端口(Nginx监听端口):
docker run -d -p 3000:80 test/test
验证方法
可以通过以下命令确认问题:
- 查看容器日志:
docker logs <容器ID>,会看到Nginx报错connect() failed (111: Connection refused) while connecting to upstream - 进入容器检查端口:
docker exec -it <容器ID> sh,安装net-tools后执行netstat -tulpn,会发现3000端口没有任何进程监听
内容的提问来源于stack exchange,提问作者iraklikairakliirakli
相关产品推荐
相关产品推荐

