强曰为道

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

第 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 章 · 数据卷 →