核心是分层构建、网络互通与配置解耦:Node.js用多阶段Dockerfile构建轻量镜像(<120MB),监听0.0.0.0:3000;Nginx通过自定义网络(如fullstack-net)以服务名node-app反向代理/api请求;docker-compose统一编排,Nginx映射宿主机端口对外提供服务。

用 Docker 容器化打包并部署 Node.js 服务,配合 Nginx 做反向代理,核心是“分层构建 + 网络互通 + 配置解耦”。不依赖宿主机环境,一次构建、随处运行。
Node.js 服务容器化打包
重点不是直接运行 node app.js,而是构建轻量、可复用的镜像:
- 推荐使用多阶段构建:第一阶段用
node:18-alpine安装依赖并构建,第二阶段仅复制node_modules和源码,基础镜像仍为 alpine,最终镜像体积通常控制在 120MB 以内 -
Dockerfile中必须指定监听地址为0.0.0.0:3000(不能写127.0.0.1),否则容器内无法被其他容器访问 - 避免在容器里用
npm start启动后端时依赖本地.env文件未挂载——建议把关键配置(如端口、数据库地址)通过environment字段或docker-compose.yml的env_file注入
Nginx 容器作为反向代理
Nginx 不托管前端就浪费了它的能力;它真正价值在于统一入口、路由分发和跨域屏蔽:
- 静态资源(如 Vue/React 构建产物、Unity WebGL)直接放在
/usr/share/nginx/html,由 Nginx 原生服务,不走 Node - 所有
/api/开头的请求,用proxy_pass http://node-app:3000;转发——注意这里写的是服务名node-app,不是localhost或 IP - 确保 Nginx 容器与 Node 容器在同一个自定义网络(如
fullstack-net),才能通过服务名通信;bridge默认网络不支持服务发现
用 docker-compose 统一编排
不用手动 docker run 启一堆参数,靠 YAML 文件声明依赖关系和网络策略:
- 在
docker-compose.yml中定义两个 service:nginx和node-app,都加入同一networks,例如- fullstack-net - Node 服务无需暴露宿主机端口给外部(如不写
ports),只要保证 Nginx 能访问它内部端口(如3000)即可,更安全 - Nginx 服务则必须映射宿主机端口(如
"80:80"或"8080:80"),这是用户实际访问的入口 - 可加
depends_on确保 Node 启动后再拉起 Nginx,但注意它只控制启动顺序,不等待 Node 服务就绪;需配合健康检查或启动脚本做真正就绪判断
常见问题直击
502 Bad Gateway、404、跨域报错,90% 出在这里:
-
502:Nginx 找不到后端——检查
upstream或proxy_pass地址是否拼错;确认 Node 容器日志里真有Server running at http://0.0.0.0:3000,而不是卡在连接数据库等阻塞步骤 -
404:静态文件路径不对——Nginx 的
root必须指向容器内路径(如/usr/share/nginx/html),且挂载卷时宿主机路径要对应(如./dist:/usr/share/nginx/html) -
CORS 报错:前端请求被浏览器拦截——这不是 Nginx 能解决的,得在 Node 层加
cors中间件,或让 Nginx 在响应头中补Access-Control-Allow-Origin: *(仅限调试,生产建议精确控制)


















