3. Bridge网络深度解析:默认桥接网络原理、端口映射机制、容器间通信
Bridge网络是Docker默认的网络驱动,也是单机容器通信的基础。理解其底层原理、端口映射机制以及容器间通信方式,是排查网络故障的核心前提。本章将深入剖析Docker默认桥接网络的工作模型。
3.1 默认桥接网络原理
Docker守护进程启动时,会在宿主机上创建一个名为docker0的虚拟网桥。所有未指定网络的容器,默认都会连接到这个docker0网桥上。其核心架构如下:
核心组件:
- docker0 网桥: 宿主机上的虚拟二层交换机,默认IP段为
172.17.0.0/16。 - veth pair: 每创建一个容器,Docker会创建一对虚拟以太网卡(veth pair)。一端连接到容器内的
eth0,另一端连接到docker0网桥。 - 网络命名空间: 每个容器拥有独立的网络栈(网卡、路由表、iptables规则),通过veth pair与宿主机网络桥接。
关键点: 同一宿主机上,连接到
docker0 网桥的容器处于同一个二层网络中,可以直接通过IP地址通信。容器与外部网络通信时,需要通过宿主机的iptables进行网络地址转换(NAT)。
3.2 端口映射机制
默认情况下,容器可以访问外部网络,但外部网络无法直接访问容器。端口映射机制通过-p或--publish参数,将宿主机端口流量转发到容器端口,实现外部访问。
| 映射模式 | 命令示例 | 说明 |
|---|---|---|
| 指定端口映射 | -p 8080:80 |
宿主机 8080 端口 → 容器 80 端口 |
| 随机端口映射 | -p 80 |
宿主机随机端口(32768-60999)→ 容器 80 端口 |
| 指定IP映射 | -p 192.168.1.100:8080:80 |
绑定到特定宿主机IP的 8080 端口 |
| UDP端口映射 | -p 8080:80/udp |
映射 UDP 协议端口 |
端口映射的底层实现依赖iptables的DNAT规则。当外部请求到达宿主机映射端口时,iptables将目标地址和端口改写为容器IP和端口,然后通过docker0网桥转发给容器。
故障排查提示: 如果端口映射不生效,请检查:
- 宿主机防火墙是否放行了映射端口。
- 容器内服务是否监听在
0.0.0.0而非127.0.0.1。 - 使用
iptables -t nat -L -n查看DNAT规则是否生成。
3.3 容器间通信
在默认桥接网络下,容器间通信主要通过两种方式:IP地址通信和--link机制(已废弃,推荐使用自定义网络)。
3.3.1 通过IP地址通信
连接到同一docker0网桥的容器,可以直接使用对方的IP地址进行通信。Docker内置的DNS服务默认不解析容器名称,因此无法通过容器名直接访问。
# 启动两个容器
docker run -d --name web1 nginx
docker run -d --name web2 nginx
# 进入 web2 容器,ping web1 的 IP
docker exec -it web2 sh
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.123 ms
3.3.2 通过容器名通信(自定义网络)
使用自定义Bridge网络时,Docker内置的DNS服务会自动解析容器名称,实现容器名通信,这是推荐的生产实践。
# 创建自定义桥接网络
docker network create my-bridge
# 启动容器并连接到自定义网络
docker run -d --name app1 --network my-bridge nginx
docker run -d --name app2 --network my-bridge nginx
# 进入 app2,通过容器名访问 app1
docker exec -it app2 sh
/ # ping app1
PING app1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.089 ms
3.4 常见故障与排查
| 故障现象 | 可能原因 | 排查命令 |
|---|---|---|
| 容器间无法ping通 | 不在同一网络;iptables规则阻断 | docker network inspect bridge |
| 端口映射外部无法访问 | 宿主机防火墙;容器服务未启动 | ss -tlnp | grep 8080 |
| 容器无法访问外网 | 宿主机IP转发未开启;DNS配置错误 | sysctl net.ipv4.ip_forward |
| DNS解析失败 | 容器DNS配置错误;宿主机resolv.conf问题 | docker exec <容器> cat /etc/resolv.conf |
最佳实践:
- 生产环境始终使用自定义Bridge网络,利用内置DNS实现容器名通信。
- 避免使用
--link参数,该机制已废弃且功能有限。 - 端口映射时优先指定宿主机端口,避免随机端口带来的管理复杂性。
- 定期使用
docker network inspect检查网络连接状态。