核心是让nginx通过服务名而非localhost或ip访问后端容器,推荐使用自定义bridge网络+docker内置dns解析;宿主机nginx需用host-gateway或网关ip;跨网络需多网卡接入;避免localhost、--network=host及依赖depends_on。

核心是让 Nginx 能正确访问到后端容器,而不是靠“localhost”硬连或写死 IP。关键在理解 Docker 网络命名空间隔离,并选择匹配部署场景的通信方式。
用自定义 bridge 网络 + 服务名解析(推荐生产环境)
这是最稳定、可维护性最强的方式。Nginx 容器和后端容器加入同一个自定义 bridge 网络,Docker 内置 DNS(127.0.0.11)会自动将服务名解析为当前网络中的容器 IP。
- 创建网络:
docker network create app-net - 启动后端容器时指定网络:
docker run --name api --network app-net -d my-api:latest - 启动 Nginx 容器也加入该网络:
docker run --name nginx --network app-net -p 80:80 -v $(pwd)/conf:/etc/nginx/conf.d -d nginx - Nginx 配置中直接写服务名:
upstream backend { server api:3000; },无需关心 IP 变化
宿主机上的 Nginx 代理容器服务(适合轻量部署或混合架构)
当 Nginx 运行在宿主机而非容器中,而你的后端服务运行在容器里时,不能写 localhost:3000,因为那是宿主机自己的回环地址,不是容器的。
- 确保后端容器正确映射端口:
docker run -p 3000:3000 my-app - 确认应用监听的是
0.0.0.0:3000,而非仅127.0.0.1:3000 - 检查防火墙是否放行该端口(如
ufw allow 3000) - Nginx 配置中使用宿主机网关地址(Docker 20.10+ 更推荐):
server host-gateway:3000;,或手动写server 172.17.0.1:3000;
跨多个 Docker 网络代理(如前后端分离部署)
当 Nginx 和后端不在同一网络(例如前端在 frontend-net,API 在 backend-net),需让 Nginx 容器同时接入两个网络。
- 先启动 Nginx 并接入主网络:
docker run --name nginx --net frontend-net -p 80:80 -d nginx - 再将其连接到后端网络:
docker network connect backend-net nginx - 此时 Nginx 容器拥有两个网络接口,可在配置中用后端容器名(如
api:3000)直连,前提是 API 容器也在backend-net中
避免踩坑的关键细节
很多 502 错误其实不是网络不通,而是配置疏漏。
-
容器内 Nginx 写 localhost = 自己的回环:永远不要在容器里配
server localhost:3000去访问另一个容器 -
不依赖
depends_on判断服务就绪:它只控制启动顺序,不保证应用已监听端口;建议加健康检查或启动脚本重试 -
别在生产用
--network=host:虽然能解决连通性,但绕过 Docker 网络管理,带来端口冲突和安全风险 -
DNS 缓存可能延迟:若容器重启后 Nginx 仍解析旧 IP,可加
resolver 127.0.0.11 valid=5s;并在proxy_pass中用变量避免缓存











