Docker 中 Nginx 网络配置
Docker 中 Nginx 网络配置完全指南
在使用 Docker 部署 Nginx 时,网络几乎是最容易出问题、也最容易被误解的一层。本文将系统性讲解:
- Docker 中 Nginx 的网络视角
- Nginx 如何访问 其他容器
- Nginx 如何访问 宿主机上的服务
- 常见错误模式与排错方法
- 用 Mermaid 画清楚网络结构
如果你曾遇到:
502 Bad Gatewayconnect() failed (111: Connection refused)- 容器里
curl 127.0.0.1不通
这篇文章就是为你写的。
一、最重要的心智模型(一切问题的根源)
Nginx 运行在容器里,它看到的网络世界,只属于这个容器。
也就是说:
- ❌ 不是宿主机的网络视角
- ❌ 不是你 SSH 登录后的视角
- ❌ 不是浏览器的视角
而是:
[ nginx 容器 ] 的网络命名空间
这条规则一旦记住,80% 的 Docker + Nginx 问题都会自动消失。
二、Docker 网络的三种常见场景
场景 A:Nginx 反代 同一个 docker-compose 中的其他容器
网络结构
graph LR N[Nginx 容器] -->|HTTP| A[App 容器]
Docker Compose 默认会:
- 创建一个 私有 bridge 网络
- 为每个 service 提供 内建 DNS
正确配置方式
docker-compose.yml
services:
nginx:
image: nginx
app:
image: my-app
expose:
- "8080"
nginx.conf
proxy_pass http://app:8080;
关键点
app是 service 名,不是容器 IP- Docker DNS 会自动解析
- 不需要
ports
✅ 这是生产环境最推荐的方式
场景 B:Nginx 访问 宿主机上的服务
这是最经典的翻车点。
网络结构
graph TD N[Nginx 容器] H[宿主机] S[宿主机服务 :8080] N -->|host.docker.internal| H H --> S
为什么 127.0.0.1 一定是错的?
proxy_pass http://127.0.0.1:8080; # ❌
因为:
127.0.0.1在容器里 = 容器自己- 宿主机的服务根本不在这个地址
正确三步走(Linux)
1️⃣ 宿主机服务必须监听在 0.0.0.0
server --host 0.0.0.0 --port 8080
验证:
ss -lntp | grep 8080
# 应看到 0.0.0.0:8080
2️⃣ docker-compose 添加 host 映射
extra_hosts:
- "host.docker.internal:host-gateway"
3️⃣ Nginx 使用 host.docker.internal
proxy_pass http://host.docker.internal:8080;
场景 C:Nginx 访问 其他 docker-compose / 独立容器
网络结构
graph LR N[Nginx] -->|shared network| API[API 容器]
解决方案:共享 Docker Network
docker network create shared-net
services:
nginx:
networks: [shared-net]
api:
networks: [shared-net]
networks:
shared-net:
external: true
proxy_pass http://api:9000;
三、地址选择速查表(实战必备)
| 目标服务 | proxy_pass 写法 |
|---|---|
| 同 compose 容器 | http://service_name:port |
| 宿主机服务 | http://host.docker.internal:port |
| 其他 compose | http://container_name:port |
| nginx 自己 | http://127.0.0.1:port |
| 外网服务 | http://domain:port |
四、WebSocket / RPC 场景的标准模板
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
location / {
proxy_pass http://host.docker.internal:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
五、排错三板斧(永远先做这三步)
1️⃣ 进入 Nginx 容器
docker exec -it nginx sh
2️⃣ 在容器内直接 curl upstream
curl http://app:8080
curl http://host.docker.internal:8080
curl 不通,nginx 一定不通
3️⃣ 看 error.log 对应含义
| 错误信息 | 含义 |
|---|---|
| connect() failed (111) | 地址 / 监听问题 |
| no route to host | network 未加入 |
| upstream prematurely closed | 协议 / header |
六、总结(一句话版本)
Docker 中配置 Nginx,不是在写配置文件,而是在选“网络视角”。
只要你始终记住:
- Nginx 在哪个容器
- upstream 在哪个网络命名空间
- 服务监听在哪个地址
Docker + Nginx 就会变得非常可控、非常稳定。