强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Docker Compose 完全指南 / 第 4 章 · 网络:默认网络、自定义网络与外部网络

第 4 章 · 网络管理

4.1 Docker 网络基础

Docker 网络是容器间通信的基石。Compose 自动为每个项目创建独立网络,实现服务隔离与互联。

网络驱动类型

驱动 说明 适用场景
bridge 默认驱动,单主机桥接网络 大多数 Compose 场景
host 容器直接使用宿主机网络栈 需要极致网络性能
overlay 跨主机网络(Swarm) 多节点集群
macvlan 分配独立 MAC 地址 容器需直接接入物理网络
none 无网络 完全隔离的容器

网络生命周期

docker compose up
    │
    ▼
┌─────────────────────────────┐
│  创建项目默认网络              │
│  <project>_default           │
│  (bridge 驱动)               │
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│  所有服务自动加入默认网络       │
│  服务名 = 内部 DNS 主机名      │
└─────────────┬───────────────┘
              │
docker compose down
              │
              ▼
┌─────────────────────────────┐
│  删除容器 + 项目网络           │
│  (数据卷保留)                 │
└─────────────────────────────┘

4.2 默认网络行为

当你不配置任何网络时,Compose 自动创建一个以项目名为前缀的 bridge 网络。

验证默认网络

# compose.yaml
services:
  web:
    image: nginx:alpine
  app:
    image: alpine:3.20
    command: sleep infinity
# 启动
docker compose up -d

# 查看网络
docker network ls | grep myproject
# <project>_default   bridge   local

# 查看网络详情
docker network inspect <project>_default

# 测试服务间连通性
docker compose exec app ping web
# PING web (172.18.0.x): 56 data bytes
# 64 bytes from 172.18.0.x: seq=0 ttl=64 time=0.068 ms

默认 DNS 解析

在同一 Compose 网络中,每个服务都有以下 DNS 记录:

DNS 名称 解析到
web 服务 web 的容器 IP
<service> 对应服务的所有容器 IP(负载均衡)
<container_name> 指定容器的 IP

💡 关键特性:服务名就是主机名。容器内通过 http://web:80 即可访问 web 服务,无需硬编码 IP。


4.3 自定义网络

4.3.1 创建自定义 bridge 网络

# compose.yaml
services:
  frontend:
    image: nginx:alpine
    networks:
      - frontend-net

  backend:
    image: node:20-alpine
    networks:
      - frontend-net
      - backend-net

  db:
    image: postgres:16-alpine
    networks:
      - backend-net

networks:
  frontend-net:
    driver: bridge
  backend-net:
    driver: bridge

网络隔离示意

┌─────────── frontend-net ──────────┐
│                                   │
│  ┌──────────┐   ┌──────────┐    │
│  │ frontend │   │ backend  │    │
│  │ (Nginx)  │   │ (Node.js)│    │
│  └──────────┘   └────┬─────┘    │
│                      │           │
└──────────────────────┼───────────┘
                       │
┌──────────────────────┼───────────┐
│        backend-net   │           │
│                      │           │
│               ┌──────┴─────┐    │
│               │   backend  │    │
│               │  (Node.js) │    │
│               └──────┬─────┘    │
│                      │           │
│               ┌──────┴─────┐    │
│               │     db     │    │
│               │ (PostgreSQL)│    │
│               └────────────┘    │
│                                  │
└──────────────────────────────────┘

通信规则:

源 → 目标 能否通信 原因
frontend → backend 同一 frontend-net
backend → db 同一 backend-net
frontend → db 不在同一网络

💡 这就是网络隔离的价值:前端无法直接访问数据库,所有数据请求必须通过后端,符合安全最佳实践。

4.3.2 网络配置选项

networks:
  frontend-net:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-frontend   # Linux 桥接接口名
      com.docker.network.bridge.enable_icc: "true"   # 容器间通信
    ipam:
      driver: default
      config:
        - subnet: 172.20.0.0/16
          ip_range: 172.20.240.0/20
          gateway: 172.20.0.1
    labels:
      - "com.example.project=myapp"
      - "com.example.environment=production"

4.3.3 服务级别的网络配置

services:
  app:
    image: myapp:latest
    networks:
      frontend-net:
        ipv4_address: 172.20.0.100     # 固定 IP
        ipv6_address: "2001:db8::100"  # IPv6
        priority: 1000                  # 出口流量优先级
        aliases:
          - myapp.local                # 网络别名(其他容器可通过此名访问)
          - api.local
配置项 说明
ipv4_address 固定 IPv4 地址
ipv6_address 固定 IPv6 地址
priority 网络优先级(值越大优先级越高)
aliases 网络别名列表,其他容器可通过别名访问

4.4 外部网络

外部网络(External Network)是在 Compose 之外预先创建的网络,常用于:

  • 多个 Compose 项目共享同一网络
  • 连接已有的 Docker 基础设施
  • 与手动创建的容器通信

创建外部网络

# 手动创建
docker network create shared-net

# 或由另一个 Compose 项目创建
cd project-a && docker compose up -d
# project-a_default 网络被创建

在 Compose 中使用外部网络

# project-b/compose.yaml
services:
  api:
    image: myapi:latest
    networks:
      - shared
      - internal

networks:
  shared:
    external: true           # 声明为外部网络
    name: shared-net         # 指定外部网络名称
  internal:
    # 非外部,Compose 自动创建

跨项目通信示例

# project-a/compose.yaml — 前端应用
services:
  frontend:
    image: nginx:alpine
    networks:
      - project-a-net
      - shared-net

networks:
  project-a-net:
  shared-net:
    external: true
    name: cross-project-net
# project-b/compose.yaml — 后端 API
services:
  api:
    image: node:20-alpine
    networks:
      - project-b-net
      - shared-net

networks:
  project-b-net:
  shared-net:
    external: true
    name: cross-project-net
# 创建共享网络
docker network create cross-project-net

# 分别启动两个项目
cd project-a && docker compose up -d
cd project-b && docker compose up -d

# frontend 现在可以通过 http://api:3000 访问 project-b 的 API

4.5 host 和 none 网络模式

host 模式

容器直接使用宿主机的网络栈,没有网络隔离。

services:
  proxy:
    image: nginx:alpine
    network_mode: host
    # 不需要 ports 映射,直接监听宿主机端口
优点 缺点
性能最佳,无 NAT 开销 端口冲突风险
可访问宿主机所有端口 无网络隔离
适合高性能代理 仅 Linux 支持(macOS/Windows 不支持)

⚠️ 注意host 模式下,ports 指令将被忽略。在 macOS/Windows 上使用 Docker Desktop 时,host 模式行为与 Linux 不同。

none 模式

services:
  batch-job:
    image: alpine:3.20
    network_mode: none
    command: ["sh", "-c", "echo 'No network access' && sleep 5"]

适用于不需要网络的批处理任务。


4.6 网络别名与服务发现

服务名解析

services:
  api:
    image: myapi:latest
    # 其他容器可通过以下方式访问:
    # - http://api:3000        (服务名)
    # - http://myapp-api:3000  (项目前缀 + 服务名,取决于配置)

网络别名

services:
  database:
    image: postgres:16
    networks:
      default:
        aliases:
          - db
          - postgres
          - pg.local
# 其他服务可通过任意别名连接
services:
  app:
    image: myapp:latest
    environment:
      # 以下三种写法都能解析到同一个容器
      DATABASE_URL: postgresql://user:pass@database:5432/mydb
      DATABASE_URL: postgresql://user:pass@db:5432/mydb
      DATABASE_URL: postgresql://user:[email protected]:5432/mydb

links(遗留方式,不推荐)

services:
  web:
    image: nginx:alpine
    links:
      - app    # 旧方式,仅保留向后兼容
  app:
    image: myapp:latest

⚠️ links 是 V1 时代的遗留功能,在现代 Compose 中完全可以用自定义网络 + 服务名替代。不推荐使用。


4.7 端口映射与网络安全

安全端口绑定

services:
  db:
    image: postgres:16
    ports:
      # ❌ 危险:所有网络接口都可访问
      - "5432:5432"

      # ✅ 安全:仅本地访问
      - "127.0.0.1:5432:5432"

      # ✅ 安全:仅允许特定网段
      - "10.0.0.0/8:5432:5432"  # 注意:不支持 CIDR,仅单 IP

仅内部通信(不暴露端口)

services:
  db:
    image: postgres:16
    # 不配置 ports,容器仅在 Docker 网络内可达
    # 外部无法访问

  api:
    image: myapi:latest
    ports:
      - "8080:3000"   # 仅 API 暴露到宿主机

💡 最佳实践:数据库、缓存等内部服务不要暴露端口到宿主机,仅通过 Docker 网络内部访问。


4.8 高级网络场景

4.8.1 连接已有容器

services:
  app:
    image: myapp:latest
    network_mode: "container:existing-container-name"
    # 共享指定容器的网络栈

4.8.2 多网络服务(网关模式)

services:
  gateway:
    image: nginx:alpine
    networks:
      public-net:
      internal-net:
    ports:
      - "443:443"

  auth:
    image: myauth:latest
    networks:
      internal-net:
      auth-net:

  db:
    image: postgres:16
    networks:
      auth-net:
      data-net:

  cache:
    image: redis:7
    networks:
      data-net:

networks:
  public-net:
  internal-net:
  auth-net:
  data-net:

4.8.3 启用 IPv6

networks:
  dual-stack:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 172.28.0.0/16
        - subnet: "2001:db8:abcd::/64"

4.9 调试网络问题

常用诊断命令

# 查看所有网络
docker network ls

# 查看网络详情(含连接的容器)
docker network inspect <project>_default

# 在容器内测试连通性
docker compose exec app ping db
docker compose exec app nslookup db
docker compose exec app curl -v http://web:80

# 查看容器 IP
docker compose exec app ip addr show
docker compose inspect --format '{{.NetworkSettings.Networks}}' <service>

常见问题排查

问题 可能原因 解决方案
ping: bad address 'db' 服务不在同一网络 检查 networks 配置
Connection refused 目标服务未启动或端口错误 docker compose logs 查看日志
No route to host 网络模式不匹配 确认 network_mode 配置
端口被占用 宿主机端口冲突 更换宿主机端口或停止占用进程
DNS 解析慢 默认 DNS 配置问题 在 daemon.json 中配置 DNS

4.10 小结

概念 说明
默认网络 Compose 自动创建 <project>_default bridge 网络
服务发现 服务名即主机名,同一网络内自动 DNS 解析
自定义网络 按职责划分网络,实现安全隔离
外部网络 external: true,用于跨项目通信
host/none 特殊网络模式,按需使用
安全原则 内部服务不暴露端口,通过网络隔离保护

扩展阅读


上一章:第 3 章 · 基础语法 ← | 下一章:第 5 章 · 数据卷 →