用户希望在一个 Docker 环境中,让 Nginx(或 Nginx Proxy Manager)代理另一个运行在 8083 端口的服务(例如 drawdb 或 vanblog)。核心难点在于:两个容器可能位于不同的网络,且需要解决容器间通信的网络配置问题。
Nginx 容器不能直接使用 localhost 或 127.0.0.1 访问其他容器,因为每个容器有独立的网络命名空间。
要让容器间通信,推荐将两个容器放入同一个自定义的 Docker bridge 网络。
在同一自定义网络中,可以通过容器名(或服务名) 作为主机名,配合容器内部端口进行访问。
nginxproxy_pass http://backend-app:8083;
其中 backend-app 是后端服务的容器名,8083 是容器内部监听的端口(不是宿主机映射端口)。
Docker 安装后会创建一个名为 bridge(或称 docker0)的默认网络。但它有致命缺点:
| 特性 | 默认 bridge | 自定义 bridge |
|---|---|---|
| 容器名自动 DNS 解析 | ❌ 不支持 | ✅ 支持 |
需要使用已废弃的 --link | 是 | 否 |
| 容器重启后 IP 变化 | 需要手动更新配置 | 容器名不变,不受影响 |
| 生产环境推荐程度 | ⭐ | ⭐⭐⭐⭐⭐ |
结论:必须创建自定义 bridge 网络,而不是使用默认的 bridge。
bashdocker network create app-network
bash# 后端服务
docker run -d --name backend-app --network app-network your-backend-image
# Nginx 容器
docker run -d --name nginx --network app-network -p 80:80 nginx
bashdocker network connect app-network nginx
实际部署中推荐使用 docker-compose.yml,Compose 会自动为项目创建一个默认的自定义网络,并且服务之间可以直接用服务名通信。
yamlversion: '3.9'
services:
backend:
image: xinsodev/drawdb
container_name: drawdb
ports:
- "8083:80" # 可选,如通过 Nginx 代理可不映射宿主机端口
restart: unless-stopped
nginx:
image: nginx
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
restart: unless-stopped
在此 Compose 文件中,不显式定义网络,Compose 会创建默认网络(名称格式:目录名_default)。服务 nginx 可以通过 http://backend:80 访问 backend。
如果已经有了一个由其他项目创建的网络(如 nginx-proxy-manager_default 或 1panel-network),需要让新服务加入该网络,并声明该网络为 external。
正确配置示例(针对 drawdb)
yamlversion: '3.9'
services:
drawdb:
image: xinsodev/drawdb
ports:
- '8083:80' # 可选,若通过 NPM 代理可删除
restart: unless-stopped
container_name: drawdb
networks:
- 1panel-network
networks:
1panel-network:
external: true # 关键:表示该网络已存在,不要尝试创建
另一示例:让 Nginx Proxy Manager 自己也加入外部网络
原用户提供的 NPM 配置中存在 YAML 缩进错误,修正后如下:
yamlservices:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
environment:
TZ: "Asia/Shanghai"
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- 1panel-network # ✅ 必须与 volumes 平级
networks:
1panel-network:
external: true
不能直接重命名。Docker 不允许修改已有网络的名称。若需要改名,只能:
docker network create new-name)docker network rm old-name)不能。Docker 的不同 bridge 网络默认隔离,即使知道另一个网络的网关 IP 也无法路由。必须将容器加入同一网络,或通过端口映射到宿主机(-p)后使用宿主机 IP 访问。
该 DNS 名称仅在 Docker Desktop (Mac/Windows) 中有效,用于从容器访问宿主机。Linux 下默认不可用,除非使用 --add-host=host.docker.internal:host-gateway 参数。
-p 8083:80):将容器端口暴露给宿主机,外部或其他网段的容器可以通过 宿主机IP:8083 访问。容器名:内部端口):性能更高、更安全,且不需要暴露端口到宿主机。用户有一个 vanblog 服务(含 MongoDB),需要加入 1panel-network 以便 Nginx Proxy Manager 代理。
yamlversion: "3"
services:
vanblog:
image: mereith/van-blog:latest
restart: always
depends_on:
mongo:
condition: service_healthy
environment:
TZ: "Asia/Shanghai"
EMAIL: ""
volumes:
- /var/vanblog/data/static:/app/static
- /var/vanblog/log:/var/log
- /var/vanblog/caddy/config:/root/.config/caddy
- /var/vanblog/caddy/data:/root/.local/share/caddy
ports:
- 8080:80
- 4433:443
networks:
- 1panel-network
mongo:
image: mongo:4.4.16
restart: always
environment:
TZ: "Asia/Shanghai"
volumes:
- /var/vanblog/data/mongo:/data/db
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongo localhost:27017/test --quiet
interval: 10s
timeout: 5s
retries: 5
networks:
- 1panel-network
networks:
1panel-network:
external: true
vanblog(容器名)80(vanblog 内部监听端口)proxy-network、app-network、1panel-network、nginx-proxy-manager_defaultbridge、network1 等过于通用的名称如果用户已经有一个由 Nginx Proxy Manager 或 1Panel 创建的网络,强烈建议直接复用该网络,而不是另建新网络,这样可以减少网络碎片。
容器名:内部端口,不要使用宿主机 IP 或映射端口(除非不得已)。docker-compose.yml 中,若需引用已存在的网络,必须添加 external: true。networks 字段应位于服务定义下的顶层,与 volumes、ports 平级。docker exec -it nginx-container /bin/sh 进入容器,执行 ping backend-container 或 curl http://backend-container:port。bash# 查看所有网络
docker network ls
# 查看某个网络的详细信息(包括连接的容器)
docker network inspect my-network
# 创建自定义 bridge 网络
docker network create my-network
# 将运行中的容器连接到网络
docker network connect my-network container-name
# 断开容器与网络
docker network disconnect my-network container-name
# 删除网络(需先断开所有容器)
docker network rm my-network
本文作者:Weee
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!