容器本地运行正常但在Google Cloud Run上无法工作
解决Cloud Run中Nginx代理Node.js服务出现502错误的问题
核心问题分析
GCP日志中的connect() failed (111: Connection refused)表明Nginx无法连接到本地的Node.js服务(127.0.0.1:3001)。本地运行正常但Cloud Run异常,大概率是服务启动顺序/时机问题,或容器环境下的服务监听配置问题。
解决方案
1. 调整服务启动顺序,等待后端就绪后再启动Nginx
你的Dockerfile中使用CMD npm run pm2:start:prod && nginx -g 'daemon off;',但PM2启动服务是后台进程,命令会立即返回并启动Nginx——此时Node.js服务可能还未完成启动,导致Nginx连接失败。
解决方法:编写启动脚本,等待后端端口就绪后再启动Nginx:
步骤1:创建entrypoint.sh启动脚本
#!/bin/bash # 启动Node.js后端服务 npm run pm2:start:prod # 循环等待3001端口就绪(依赖netcat,需提前安装) until nc -z 127.0.0.1 3001; do echo "等待后端服务启动..." sleep 2 done # 启动Nginx nginx -g 'daemon off;'
步骤2:修改Dockerfile
在Dockerfile中添加脚本复制、权限配置,并替换原CMD:
FROM node:20 # 安装nginx和netcat(用于端口检查) RUN apt-get update && apt-get install -y nginx netcat-traditional WORKDIR /usr/src/app COPY . . RUN npm ci --omit=dev RUN cd my-project && npm i && npm run build && cd .. RUN rm /etc/nginx/sites-enabled/default COPY nginx.conf /etc/nginx/nginx.conf RUN cp -r ./my-project/dist/my-project/browser/* /usr/share/nginx/html/ # 添加并配置启动脚本 COPY entrypoint.sh /usr/src/app/entrypoint.sh RUN chmod +x /usr/src/app/entrypoint.sh # 使用启动脚本替代原CMD CMD ["/usr/src/app/entrypoint.sh"]
2. 确保Node.js服务监听正确的地址
虽然本地运行正常,但容器环境下建议让Node.js服务监听0.0.0.0(而非仅127.0.0.1),确保服务能在容器内部被访问:
// Node.js服务启动代码示例 app.listen(3001, '0.0.0.0', () => { console.log('后端服务运行在http://0.0.0.0:3001'); });
3. 验证PM2配置与服务状态
- 检查PM2的启动配置,确保它确实启动了监听3001端口的服务
- 在本地容器中运行后,执行
curl http://127.0.0.1:3001/api/ping验证后端服务是否正常响应 - 查看Cloud Run日志中Node.js/PM2的输出,确认服务无启动错误
4. 检查依赖安装完整性
确保npm ci --omit=dev正确安装了后端服务所需的所有生产依赖,避免因依赖缺失导致服务启动失败。
额外排查点
- 确认Cloud Run的容器端口配置为
8080(Nginx监听的端口,Cloud Run默认配置即可) - 在Cloud Run日志中筛选Node.js相关输出,排查服务启动时的报错信息
内容的提问来源于stack exchange,提问作者Mike Borozdin
相关产品推荐
相关产品推荐

