编辑
2026-05-10
学习记录
00

目录

Docker网络配置实战:Nginx代理跨容器服务与网络最佳实践
背景与需求
一、Nginx 代理其他 Docker 服务的基本原理
1.1 核心要点
1.2 示例:Nginx 配置中的代理地址
二、为什么不用默认的 bridge 网络?
三、创建自定义网络并连接容器
3.1 创建网络
3.2 启动容器时加入网络
3.3 如果容器已经运行,可以动态连接网络
四、使用 Docker Compose 管理网络
4.1 基础示例
4.2 连接已存在的外部网络(例如 Nginx Proxy Manager 的网络)
五、常见问题与解答
5.1 网络创建后能否改名?
5.2 不同 bridge 网络之间能否通过网关 IP 访问?
5.3 如何使用 host.docker.internal?
5.4 端口映射与内部通信的区别
六、一个完整的实战案例:VanBlog + Nginx Proxy Manager
6.1 修改后的 docker-compose.yml
6.2 在 Nginx Proxy Manager 中添加代理
七、网络名称命名建议
八、总结与最佳实践
附录:常用命令

Docker网络配置实战:Nginx代理跨容器服务与网络最佳实践

背景与需求

用户希望在一个 Docker 环境中,让 Nginx(或 Nginx Proxy Manager)代理另一个运行在 8083 端口的服务(例如 drawdb 或 vanblog)。核心难点在于:两个容器可能位于不同的网络,且需要解决容器间通信的网络配置问题。

一、Nginx 代理其他 Docker 服务的基本原理

1.1 核心要点

Nginx 容器不能直接使用 localhost127.0.0.1 访问其他容器,因为每个容器有独立的网络命名空间。

要让容器间通信,推荐将两个容器放入同一个自定义的 Docker bridge 网络

在同一自定义网络中,可以通过容器名(或服务名) 作为主机名,配合容器内部端口进行访问。

1.2 示例:Nginx 配置中的代理地址

nginx
proxy_pass http://backend-app:8083;

其中 backend-app 是后端服务的容器名,8083 是容器内部监听的端口(不是宿主机映射端口)。

二、为什么不用默认的 bridge 网络?

Docker 安装后会创建一个名为 bridge(或称 docker0)的默认网络。但它有致命缺点:

特性默认 bridge自定义 bridge
容器名自动 DNS 解析❌ 不支持✅ 支持
需要使用已废弃的 --link
容器重启后 IP 变化需要手动更新配置容器名不变,不受影响
生产环境推荐程度⭐⭐⭐⭐⭐

结论:必须创建自定义 bridge 网络,而不是使用默认的 bridge。

三、创建自定义网络并连接容器

3.1 创建网络

bash
docker network create app-network

3.2 启动容器时加入网络

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

3.3 如果容器已经运行,可以动态连接网络

bash
docker network connect app-network nginx

四、使用 Docker Compose 管理网络

实际部署中推荐使用 docker-compose.yml,Compose 会自动为项目创建一个默认的自定义网络,并且服务之间可以直接用服务名通信。

4.1 基础示例

yaml
version: '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

4.2 连接已存在的外部网络(例如 Nginx Proxy Manager 的网络)

如果已经有了一个由其他项目创建的网络(如 nginx-proxy-manager_default1panel-network),需要让新服务加入该网络,并声明该网络为 external

正确配置示例(针对 drawdb)

yaml
version: '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 缩进错误,修正后如下:

yaml
services: 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

五、常见问题与解答

5.1 网络创建后能否改名?

不能直接重命名。Docker 不允许修改已有网络的名称。若需要改名,只能:

  1. 创建新网络(docker network create new-name
  2. 迁移所有容器到新网络
  3. 删除旧网络(docker network rm old-name

5.2 不同 bridge 网络之间能否通过网关 IP 访问?

不能。Docker 的不同 bridge 网络默认隔离,即使知道另一个网络的网关 IP 也无法路由。必须将容器加入同一网络,或通过端口映射到宿主机(-p)后使用宿主机 IP 访问。

5.3 如何使用 host.docker.internal?

该 DNS 名称仅在 Docker Desktop (Mac/Windows) 中有效,用于从容器访问宿主机。Linux 下默认不可用,除非使用 --add-host=host.docker.internal:host-gateway 参数。

5.4 端口映射与内部通信的区别

  • 端口映射-p 8083:80):将容器端口暴露给宿主机,外部或其他网段的容器可以通过 宿主机IP:8083 访问。
  • 直接内部通信(通过自定义网络 + 容器名:内部端口):性能更高、更安全,且不需要暴露端口到宿主机。

六、一个完整的实战案例:VanBlog + Nginx Proxy Manager

用户有一个 vanblog 服务(含 MongoDB),需要加入 1panel-network 以便 Nginx Proxy Manager 代理。

6.1 修改后的 docker-compose.yml

yaml
version: "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

6.2 在 Nginx Proxy Manager 中添加代理

  • Scheme: http
  • Forward Hostname / IP: vanblog(容器名)
  • Forward Port: 80(vanblog 内部监听端口)

七、网络名称命名建议

  • ✅ 语义化:如 proxy-networkapp-network1panel-networknginx-proxy-manager_default
  • ✅ 只使用字母、数字、下划线、连字符
  • ❌ 避免使用 bridgenetwork1 等过于通用的名称
  • ❌ 避免使用特殊字符或空格
  • ❌ 名称不宜过长,但也要清晰

如果用户已经有一个由 Nginx Proxy Manager 或 1Panel 创建的网络,强烈建议直接复用该网络,而不是另建新网络,这样可以减少网络碎片。

八、总结与最佳实践

  • 始终使用自定义 bridge 网络,不要依赖默认的 bridge。
  • 容器间通信使用 容器名:内部端口,不要使用宿主机 IP 或映射端口(除非不得已)。
  • docker-compose.yml 中,若需引用已存在的网络,必须添加 external: true
  • 注意 YAML 缩进:networks 字段应位于服务定义下的顶层,与 volumesports 平级。
  • 验证连通性:使用 docker exec -it nginx-container /bin/sh 进入容器,执行 ping backend-containercurl 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 许可协议。转载请注明出处!