Docker 网络详解:从 docker0 网桥到网络命名空间
Docker 是一种广泛使用的容器化技术,其网络功能的实现依赖于 Linux 的网络命名空间和虚拟网桥。本文将深入探讨 Docker 的默认桥接网络(bridge network),重点分析 docker0 网桥的作用、容器网络与主机网络的关系,以及网络命名空间级别的工作原理,并结合实际示例(如 ifconfig
和 route
命令输出)进行说明。
一、什么是 docker0 网桥?
docker0 是一个虚拟网桥(bridge),由 Docker 在安装时自动创建。它存在于主机的网络命名空间中,充当容器网络与主机网络之间的“中间人”。docker0 的主要功能包括:
- 网络连接:将容器的网络流量转发到主机网络接口(如 eth0),实现容器与外部网络的通信。
- IP 分配:docker0 关联一个默认子网(通常为 172.17.0.0/16),Docker 会从该子网为容器分配 IP 地址。
- NAT 转发:通过网络地址转换(NAT),将容器的私有 IP 转换为主机公网 IP,从而访问外部网络。
可以通过以下命令查看 docker0 的信息:
ip addr show docker0
docker network inspect bridge
二、Docker 网络与网络命名空间
1. 网络命名空间的基本概念
网络命名空间(Network Namespace)是 Linux 内核提供的隔离机制,每个网络命名空间拥有独立的网络栈,包括网络设备、路由表、iptables 规则和协议栈。Docker 利用网络命名空间为每个容器创建独立的网络环境,确保容器之间的网络隔离。
2. docker0 在主机网络命名空间中的角色
- 位置:docker0 位于主机的网络命名空间,IP 通常为 172.17.0.1/16。
- 功能:docker0 就像一个虚拟交换机,连接所有容器和主机网络。
- 连接方式:通过虚拟以太网设备(veth pair),docker0 将容器的网络接口(eth0)与主机网络连接起来。
3. 容器的网络命名空间
- 独立性:每个容器有自己的网络命名空间,包含独立的网络接口(如 eth0)。
- veth 设备:
- Docker 创建一对 veth 设备,一端放入容器(命名为 eth0),另一端绑定到主机网络命名空间的 docker0 网桥。
- 容器内的 eth0 会分配一个 IP(如 172.17.0.2),默认网关指向 docker0 的 IP(172.17.0.1)。
- 通信路径:容器内的流量通过 eth0 和 veth 对到达 docker0,docker0 再决定如何转发。
三、容器与主机网络的通信
1. 容器访问外部网络
- 流量路径:
- 容器(IP: 172.17.0.2)发出数据包,目标为外部地址(如 8.8.8.8)。
- 数据包通过 eth0 和 veth 对到达 docker0 网桥(默认网关 172.17.0.1)。
- docker0 将流量转发到主机的物理网卡(如 eth0)。
- 主机通过 iptables NAT 转换(MASQUERADE),将容器私有 IP 转换为公网 IP,流量最终到达外部网络。
- 路由表:可以通过
ip route
或route -n
查看容器的路由表。例如:Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 172.17.0.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 * 255.255.0.0 U 0 0 0 eth0
default via 172.17.0.1
表示默认网关为 172.17.0.1,外部流量会通过它转发。
2. 主机访问容器
主机可以直接通过 docker0 的子网(172.17.0.0/16)访问容器。例如,主机运行 ping 172.17.0.2
,流量通过 docker0 网桥转发到容器的 eth0。
3. 外部网络访问容器
外部网络访问容器通常通过端口映射实现。例如,使用 docker run -p 8080:80
将主机的 8080 端口映射到容器的 80 端口。Docker 会设置 DNAT 规则,流量通过 docker0 到达容器。
四、同一网段内的容器通信
1. 示例:容器内的网络配置
以下是容器内执行 ifconfig
的输出:
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0UP LOOPBACK RUNNING MTU:65536 Metric:1
- 容器 IP 为 172.17.0.2,子网掩码为 255.255.0.0(/16),属于 172.17.0.0/16 网段。
路由表(route -n
输出)如下:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 * 255.255.0.0 U 0 0 0 eth0
- 默认网关为 172.17.0.1。
- 172.17.0.0/16 网段的流量直接通过 eth0,无需网关。
2. 同一网段通信的含义
假设另一个容器 IP 为 172.17.0.3(也在 172.17.0.0/16 网段),容器之间的通信不需要额外的网关:
- 路由表匹配:目标 IP 172.17.0.3 匹配
172.17.0.0/16
规则,路由表显示无需网关(Gateway: *
)。 - docker0 的作用:docker0 网桥直接将流量从容器 A(172.17.0.2)的 veth 接口转发到容器 B(172.17.0.3)的 veth 接口。
- 无需额外的网关:这里的“额外的网关”指的是主机的默认网关(比如路由器 IP)。同一网段内的通信仅依赖 docker0 网桥的二层转发功能,类似于局域网中的交换机。
流量路径:
- 容器 A(172.17.0.2)发出数据包,目标为 172.17.0.3。
- 数据包通过 eth0 和 veth 对到达 docker0 网桥。
- docker0 识别目标 IP 172.17.0.3,将数据包直接转发到容器 B 的 veth 接口。
- 数据包到达容器 B 的 eth0,通信完成。
五、总结
Docker 的默认桥接网络通过 docker0 网桥和网络命名空间实现了容器网络的隔离与通信:
- docker0 网桥:位于主机网络命名空间,连接容器和主机网络,IP 通常为 172.17.0.1。
- 网络命名空间:每个容器有独立的网络命名空间,通过 veth 对与 docker0 相连。
- 通信模式:
- 容器访问外部网络:通过默认网关 172.17.0.1 和 NAT 转发。
- 同一网段容器通信:直接通过 docker0 网桥,无需额外的网关。
- 外部访问容器:通过端口映射和 DNAT 规则。