bridge 模式工作原理
面试题
Docker bridge 网络模式的工作原理是什么?容器之间是如何通过 bridge 通信的?
标准答案
bridge 模式是 Docker 默认的网络模式,它基于 Linux 网桥(Bridge)和 iptables 规则实现容器隔离与通信。理解其工作原理是掌握 Docker 网络的核心。
网络拓扑
宿主机
┌────────────────────────────────────────────────────┐
│ │
│ 容器 A 容器 B 容器 C │
│ ┌──────────┐ ┌──────────┐ ┌────────┐│
│ │ eth0 │ │ eth0 │ │ eth0 ││
│ │ 172.17.0.2│ │ 172.17.0.3│ │ 172.17.0.4│
│ └────┬─────┘ └────┬─────┘ └───┬────┘│
│ │ │ │ │
│ ┌────┴───────────────────┴────────────────────┴──┐ │
│ │ docker0 网桥 │ │
│ │ IP: 172.17.0.1 │ │
│ │ MAC: 02:42:xx:xx:xx:xx │ │
│ └───────────────────────┬────────────────────────┘ │
│ │ │
│ ┌───────────────────────┴────────────────────────┐ │
│ │ 宿主机 eth0 (物理网卡) │ │
│ │ 192.168.1.100 │ │
│ └───────────────────────┬────────────────────────┘ │
│ │ │
└──────────────────────────┼──────────────────────────┘
│
互联网/外网
四步理解 bridge 工作流程
第一步:创建网桥
# Docker daemon 启动时自动创建 docker0 网桥
ip link show docker0
brctl show docker0
# 查看网桥的 IP(默认 172.17.0.1/16)
ip addr show docker0
第二步:创建 veth pair
当启动容器时,Docker 创建一对 veth 虚拟网卡:
# 在宿主机上看到新出现 veth 开头的接口
ip link show | grep veth
# veth pair 的两端:
# - 一端在宿主机:vethXXX(连接到 docker0 网桥)
# - 一端在容器内:eth0(容器内看到的网卡)
# 查看容器的 veth 对应关系
docker inspect --format='{{.NetworkSettings.SandboxKey}}' myapp
第三步:分配 IP
# Docker 内嵌 DHCP 服务器自动分配 IP
# 默认 bridge 网络子网:172.17.0.0/16
# 容器获取 172.17.0.2、172.17.0.3...
# 宿主机(docker0)的 IP 是容器的默认网关
docker exec myapp ip route
# default via 172.17.0.1 dev eth0
# 172.17.0.0/16 dev eth0 scope link
第四步:配置 iptables NAT
# 容器访问外网:通过 iptables MASQUERADE(源地址转换)
iptables -t nat -L POSTROUTING -n
# Chain POSTROUTING (policy ACCEPT)
# target prot opt source destination
# MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16
# 外网访问容器:通过 iptables DNAT(目的地址转换)
iptables -t nat -L DOCKER -n
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80
容器间通信
# 场景:两个容器在 bridge 下通信
docker run -d --name web1 nginx
docker run -d --name web2 nginx
# web1 ping web2 的 IP(可以通)
docker exec web1 ping 172.17.0.3
# web1 ping web2 的容器名(❌ 默认 bridge 不支持)
docker exec web1 ping web2
# ping: bad address 'web2'
通信过程:
web1 (172.17.0.2) → 发送 ARP 请求 "who has 172.17.0.3?"
↓
docker0 网桥转发 ARP 广播到所有端口
↓
web2 (172.17.0.3) 回复 "I am, MAC: 02:42:ac:11:00:03"
↓
web1 将数据包通过 veth pair 发送到 docker0
↓
docker0 根据 MAC 地址转发到 web2 的 veth 端口
↓
web2 收到数据包
端口映射原理
# 启动容器映射端口
docker run -d -p 8080:80 nginx
# Docker 做的三件事:
1. 在 docker0 网桥上添加 DNAT 规则:
# 访问宿主机 8080 → 转发到容器 172.17.0.2:80
iptables -t nat -A DOCKER ! -i docker0 \
-p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80
2. 在 FORWARD 链添加允许转发的规则:
iptables -A DOCKER -o docker0 -d 172.17.0.2 -j ACCEPT
iptables -A DOCKER -i docker0 ! -o docker0 -j ACCEPT
3. 配置 IP 转发:
sysctl net.ipv4.ip_forward # 必须为 1
关键配置点
# 修改默认 bridge 的子网
# /etc/docker/daemon.json
{
"bip": "172.20.0.1/16",
"default-address-pools": [
{"base": "172.20.0.0/16", "size": 24}
]
}
性能特点
| 方面 | 说明 |
|---|---|
| 延迟 | 略有额外延迟(veth + 网桥转发) |
| 吞吐量 | 接近原生(约 95%+) |
| NAT 开销 | 主要开销在 masquerade |
| 可扩展性 | 默认 single bridge 有性能瓶颈 |
常见问题
Q:为什么默认 bridge 不支持通过容器名通信?
默认 bridge 不提供内置 DNS 解析。Docker 的嵌入式 DNS 功能只在用户自定义网络中启用。这是驱动层面的限制,而非技术不可行。
Q:docker0 网桥的 MAC 地址学习是如何工作的?
和普通网桥一样,docker0 会学习到达各个端口的 MAC 地址,建立转发表。当所有 veth 端口都注册了对应的 MAC 地址后,网桥就能高效地转发二层数据帧。
Q:iptables FORWARD 链默认策略是 DROP 会怎样?
容器无法访问外网。需要添加明确的 ACCEPT 规则:
iptables -A FORWARD -i docker0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o docker0 -j ACCEPT
Docker 会自动维护这些规则。
总结
bridge 模式的核心:Linux 网桥提供容器间二层通信,veth pair 连接容器到网桥,iptables 实现 NAT 和端口映射。自定义 bridge 比默认 bridge 多一个 DNS 解析功能,实际工作中建议使用自定义 bridge。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容