默认 bridge 和自己创建的 bridge 网络有什么区别?为什么有的容器能按名字互访、有的不能?跨网络为什么不通?这篇用 ping 逐项验证,并进入虚拟机看网桥和 veth 设备。
docker network ls 里的内置网络:bridge/bridge host/host kind/bridge none/null bridge 网络的 Subnet / Gateway:172.17.0.0/16 172.17.0.1 两个默认 bridge 上的容器 IP:a=172.17.0.2 b=172.17.0.3 a ping b 的 IP:退出码 0 a ping b 的名字 bwlab-c46b:退出码 1;ping: bad address 'bwlab-c46b' 容器里的默认路由:default via 172.17.0.1 dev eth0 ; 172.17.0.0/16 dev eth0 scope link src 172.17.0.2
默认 bridge 的子网是 172.17.0.0/16,网关 172.17.0.1(虚拟机里 docker0 的地址)。同一个网络里的容器按 IP 互通,但容器名解析不了(bad address)。
docker network create 之后新网络的 Subnet / Gateway:172.19.0.0/16 172.19.0.1 自定义网络里 c ping d 的名字 bwlab-c46d:退出码 0;解析到 PING bwlab-c46d (172.19.0.3): 56 data bytes
docker network create 出来的网络按顺序分配新的 /16 子网(这里是 172.19,因为 172.18 已被另一个网络占用);容器按名字互访可以。名字解析的细节见后面的内置 DNS 一篇。
自定义网络里的 c ping 默认 bridge 上的 a(172.17.0.2):退出码 1 默认 bridge 上的 a ping c(172.19.0.2):退出码 1 docker network connect bwlab-c46net bwlab-c46a 之后,a 有 2 个 IP:['172.17.0.2', '172.19.0.4'] a ping c 的名字:退出码 0
不同 bridge 网络之间不通;docker network connect 把容器接入第二个网络,它就有了两个 IP,可以访问新网络里的容器。我没有查隔离是靠哪条 iptables 规则实现的。
虚拟机里的网桥设备:docker0 br-c76c209e2a7a br-ae1a41b9fb47 虚拟机里 veth 设备个数:起容器前 10 个,起 4 个容器(其中 a 连了两个网络)之后 15 个,增加 5 个——每个容器每连一个网络就多一个 veth docker0 的地址:172.17.0.1/16
每个自定义网络对应虚拟机里一个 br-<网络ID前缀> 网桥,默认 bridge 是 docker0;每个容器的每个网卡对应虚拟机里一个 veth 设备(另一端在容器的网络命名空间里,见后面的 veth 一篇)。