bigywater.tech
Docker · 52

host 网络:和 bridge 相比少了什么、快了多少

--network host 在 macOS 上到底是谁的网络?这篇读网络命名空间的编号、网卡列表和 hostname,验证 -p 为什么没用、从 Mac 能不能访问到,以及端口冲突。

net:[4026531833]
host 模式容器和虚拟机 PID 1 共用的网络命名空间编号
Connection refused
Mac 上访问 host 模式容器监听的端口的结果
Address in use
两个 host 模式容器绑定同一端口的第二个得到的错误

host 是谁

实测 · 本机执行输出
  默认容器的网卡:bonding_masters erspan0 eth0 gre0 gretap0 ip6_vti0 ip6gre0 ip6tnl0 ip_vti0 lo sit0 tunl0;hostname = 1184e6a1e4ac
  --network host 的容器的网卡:bond0 bonding_masters br-c76c209e2a7a docker0 dummy0 erspan0 eth0 gre0 gretap0 ip6_vti0 ip6gre0 ip6tnl0 ip_vti0 lo services1 sit0 teql0 tunl0 veth03fa606 veth604ef23 veth65f4fc2 veth8139bab vethbad205;hostname = docker-desktop
  虚拟机自己的网卡:bond0 bonding_masters br-c76c209e2a7a docker0 dummy0 erspan0 eth0 gre0 gretap0 ip6_vti0 ip6gre0 ip6tnl0 ip_vti0 lo services1 sit0 teql0 tunl0 veth03fa606 veth604ef23 veth65f4fc2 veth753b7c6 veth8139ba;hostname = docker-desktop
  网络命名空间:默认容器 net:[4026534595];--network host 的容器 net:[4026531833];虚拟机 PID 1 的 net:[4026531833]

在 Docker Desktop 上,--network host 的“host”是运行 Docker 的 Linux 虚拟机。容器的网络命名空间编号和虚拟机的 PID 1 完全相同,网卡里有 docker0、br-…、veth…,hostname 是虚拟机的 docker-desktop。Linux 宿主机上的情形不同,我没有测。

-p 无效

实测 · 本机执行输出
  --network host -p 9711:80:退出码 0;输出:WARNING: Published ports are discarded when using host network mode

host 模式下 -p 被丢弃,docker 只打印一个 WARNING,退出码仍是 0。

Mac 够不着

实测 · 本机执行输出
  host 模式容器监听了 9755:docker logs = listening
  虚拟机里 ss 看到 9755 在监听吗?是
  Mac 宿主机 curl 127.0.0.1:9755:URLError:<urlopen error [Errno 61] Connection refused>
  另一个默认 bridge 容器访问 172.17.0.1:9755(虚拟机上 docker0 的地址):成功

host 模式容器监听 9755,虚拟机里 ss 能看到,虚拟机里的其它容器通过 docker0 的地址 172.17.0.1 能访问,Mac 上 curl 127.0.0.1:9755 被拒绝。Docker Desktop 有单独的「主机网络」功能开关,我没有改任何设置,所以没有测它打开后的表现。

端口冲突

实测 · 本机执行输出
  第二个 host 容器绑定同一个端口:退出码 1;OSError: [Errno 98] Address in use
  对比:两个默认 bridge 容器都监听容器内的 8000:listening / listening

host 模式的容器之间没有网络隔离,绑定同一端口会冲突;bridge 模式的容器各有各的命名空间,可以都监听 8000。

分步演示

host 网络
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。网络命名空间编号读自 /proc/self/ns/net;网卡列表读自 /sys/class/net;虚拟机侧信息用特权容器加 nsenter 读取(方法见 c19);HTTP 服务用 python:3.12-alpine 的 socketserver;端口从 9730 以后挑一个空闲的(中间有一次因为端口 9721 在虚拟机里绑定失败而换了端口,原因我没有查);实验后已删除容器
    • 没有验证:Docker Desktop 的「启用主机网络」设置打开后从 Mac 访问、Linux 宿主机上的 --network host、host 模式下的 iptables 与防火墙、IPv6、host 模式容器与 bridge 容器之间的 DNS
    京ICP备2026067502号-1京公网安备11010502063487号