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