Docker 网络
Docker 的网络子系统负责容器之间、容器与宿主机之间、容器与外部世界之间的通信。
网络驱动概览
| 驱动 | 默认 | 隔离性 | 适用场景 |
|---|---|---|---|
bridge |
✅ | 宿主机内部 | 单机容器间通信 |
host |
— | 无隔离 | 高性能网络需求 |
none |
— | 完全隔离 | 无需网络的容器 |
overlay |
— | 跨宿主机 | Swarm 多机通信 |
macvlan |
— | 物理网络级 | 容器直接接入物理网络 |
ipvlan |
— | 物理网络级 | 替代 macvlan(少 MAC 限制) |
bridge — 桥接模式
默认 bridge
# 不指定网络时,容器使用默认 bridge(docker0)
docker run -d --name c1 nginx
docker run -d --name c2 nginx┌──────────────────────────────────────┐
│ 宿主机 │
│ ┌─────────┐ ┌─────────┐ │
│ │ 容器 c1 │ │ 容器 c2 │ │
│ │172.17.0.2│ │172.17.0.3│ │
│ └────┬─────┘ └────┬─────┘ │
│ └───────┬───────┘ │
│ ┌─────▼──────┐ │
│ │ docker0 │ ← 虚拟网桥 │
│ │ 172.17.0.1 │ │
│ └─────┬──────┘ │
│ ┌─────▼──────┐ │
│ │ iptables │ ← NAT │
│ │ (DNAT/SNAT)│ │
│ └─────┬──────┘ │
│ ┌─────▼──────┐ │
│ │ eth0 │ ← 物理网卡 │
│ └────────────┘ │
└──────────────────────────────────────┘🚨 默认 bridge 的限制:容器之间只能通过 IP 通信,不能通过容器名 DNS 解析。需要 DNS 的服务发现应使用自定义 bridge 网络。
自定义 bridge(用户定义网络)
docker network create --driver bridge my_bridge
# 创建时指定子网
docker network create \
--driver bridge \
--subnet=192.168.100.0/24 \
--gateway=192.168.100.1 \
my_bridge
docker run -d --name web --network my_bridge nginx
docker run -d --name api --network my_bridge my_api🔬 深入原理:自定义 bridge 网络相比默认 bridge 的核心区别:
| 特性 | 默认 bridge | 自定义 bridge |
|---|---|---|
| DNS 解析(容器名) | ❌ 不支持 | ✅ 支持 |
| 容器互联(–link) | 需要手动 | 自动 |
| 网络配置 | 固定 | 可自定义子网/网关/IP |
| 隔离性 | 所有容器共享 | 按网络隔离 |
容器连接/断开网络
# 将运行中的容器连接到网络
docker network connect my_bridge web
# 连接时指定 IP
docker network connect --ip 192.168.100.10 my_bridge web
# 断开连接
docker network disconnect my_bridge web💡 一个容器可以连接到多个网络,实现不同网络间的隔离访问。
host — 主机模式
docker run -d --network host nginx不使用 namespace 隔离网络
容器直接使用宿主机的网络栈
宿主机 :80 → 容器的 80 端口(无需 -p 映射)| 优缺点 | 说明 |
|---|---|
| ✅ 性能最高 | 无 NAT 转发、无虚拟网桥开销 |
| ✅ 无需端口映射 | 容器端口直接暴露在宿主机上 |
| ❌ 端口冲突 | 容器端口占用宿主机端口 |
| ❌ 安全隔离差 | 容器网络和宿主机完全共享 |
| ❌ 仅 Linux | Windows/Mac 不支持真正 host 模式 |
⚡ 性能提示:对网络延迟敏感的数据库、消息队列等场景,可考虑 host 模式。如 Redis 官方镜像在基准测试时推荐
--network host。
none — 无网络
docker run -d --network none my_app容器没有网络接口,只有 lo 回环。适用于:
- 批量计算任务
- 安全隔离极高的场景
- 不需要任何网络通信的后台任务
端口映射详解
# 基本格式:-p [宿主机IP:][宿主机端口:]容器端口[/协议]
docker run -p 8080:80 nginx # 0.0.0.0:8080 → 容器:80
docker run -p 127.0.0.1:8080:80 nginx # 仅本地 8080 → 容器:80
docker run -p 53:53/udp dns_server # UDP 端口
docker run -p 8080:80 -p 443:443 nginx # 多个端口
# 随机端口映射(-P):将 EXPOSE 声明的端口随机映射
docker run -d -P nginx # EXPOSE 80 → 随机端口
docker port <container_id> # 查看映射结果🔬 深入原理:端口映射通过 iptables 的 DNAT(目标地址转换)实现:
外部请求 0.0.0.0:8080
│
▼
iptables DNAT: 0.0.0.0:8080 → 容器IP:80
│
▼
docker-proxy 或直接 iptables 转发
│
▼
容器 eth0:80overlay — 跨主机网络(Swarm)
# 创建 overlay 网络(需要 Swarm 模式)
docker swarm init
docker network create --driver overlay --attachable my_overlay
# 创建服务跨多节点通信
docker service create --name web --network my_overlay --replicas 3 nginxNode A: 容器 web.1 ──┐ Node B: 容器 web.2 ──┐
│ │
overlay 网络 (VXLAN 隧道加密) │
│ │
┌─────▼──────────────────────────────▼─────┐
│ 跨主机容器可直接通信 │
└──────────────────────────────────────────┘macvlan / ipvlan — 接入物理网络
macvlan
# 创建一个 macvlan 网络,容器获得独立 MAC 地址
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
my_macvlan
docker run -d --network my_macvlan --ip 192.168.1.100 nginx容器直接接入物理网络,获得独立的 MAC 地址和 IP,看起来像一台独立的物理机。
🚨 陷阱:macvlan 模式下,宿主机本身无法直接与同一网卡的 macvlan 容器通信(Linux 内核限制)。如需宿主机和容器互通,需要创建子接口或使用 ipvlan。
ipvlan(推荐)
docker network create -d ipvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
-o ipvlan_mode=l2 \
my_ipvlan| 模式 | 特点 |
|---|---|
l2 |
二层桥接,类似 macvlan,共享宿主机 MAC(适用于 DHCP/MAC 受限环境) |
l3 |
三层路由,需要手动添加路由(适用于大型网络、多子网) |
DNS 解析机制
# 查看容器的 DNS 配置
docker exec web cat /etc/resolv.conf
# 输出示例:
# nameserver 127.0.0.11 ← Docker 内置 DNS
# options ndots:0🔬 深入原理:Docker 内置 DNS 服务器监听 127.0.0.11:
- 自定义网络:自动 DNS 解析,容器名和 service 名均可解析
- 默认 bridge:不支持 DNS 解析,只能通过
--link添加/etc/hosts - 容器名解析:
ping web→127.0.0.11:53→ 返回容器 IP - TTL:默认由 Docker 守护进程管理,容器重建后 DNS 自动更新
# 自定义 DNS 服务器
docker run -d --dns 8.8.8.8 --dns 114.114.114.114 nginx
# 自定义搜索域
docker run -d --dns-search example.com nginx网络调试命令
# 查看容器 IP 地址
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_id>
# 查看容器 DNS 配置
docker exec <container_id> cat /etc/resolv.conf
# 查看 iptables 规则
iptables -t nat -L -n | grep DOCKER
# 查看网桥信息
brctl show docker0
# 或
ip link show docker0
# 查看网络连接的容器
docker network inspect my_bridge
# 容器间连通性测试
docker exec web ping api
docker exec web nslookup api网络模式总结对比
| 特性 | bridge | custom bridge | host | overlay | macvlan |
|---|---|---|---|---|---|
| 容器间 DNS | ❌ | ✅ | N/A | ✅ | ❌ |
| 端口映射 | 需 -p |
需 -p |
不需要 | 需 -p |
不需要 |
| 外部访问 | NAT | NAT | 直接 | NAT/LB | 直接 |
| 性能 | 中等 | 中等 | 最高 | 较低(VXLAN) | 高 |
| 跨主机 | ❌ | ❌ | ❌ | ✅ | ❌ |
| 容器名解析 | ❌ | ✅ | N/A | ✅ | ❌ |
常见陷阱
| 陷阱 | 说明 | 正确做法 |
|---|---|---|
| 默认 bridge 无法 DNS | 容器名无法解析 | 使用自定义 bridge 网络 |
| host 模式端口冲突 | 容器与宿主机端口冲突 | 注意端口规划 |
| macvlan 宿主机不通 | 宿主机无法访问 macvlan 容器 | 使用 ipvlan 或创建子接口 |
| 忘记创建网络 | 启动时 --network 指向不存在的网络 |
先 docker network create |
| Compose 网络名冲突 | 不同项目创建同名网络 | 默认自动加项目前缀隔离 |
internal: true 误解 |
内部网络容器无法访问外网 | 根据需求选择是否启用 |