Docker 五种网络模式对比与踩坑记录
五种网络模式的能力边界
Docker 通过 --network 指定容器网络模式,默认是 bridge。五种模式的核心差异在于网络命名空间的复用方式和地址分配方式。
bridge:容器拥有独立网络命名空间,接入 docker0 网桥,由内置 IPAM 分配 172.17.0.0/16 网段地址,可发布端口。host:容器与宿主共享网络命名空间,不分配独立 IP,端口直接占用宿主端口。none:只有 lo 回环口,无外部网络,适合纯计算型任务。container:与指定容器共享网络命名空间,共用 IP 和端口空间,Kubernetes 的 pause 容器就是这种用法。自定义 bridge:用户自行创建,自带 DNS 解析,这是与默认 bridge 最关键的区别。
docker network create --subnet 10.10.0.0/24 appnet docker run -d --name api --network appnet --network-alias api nginx docker run --rm --network appnet curlimages/curl curl -s http://api:80/
默认 bridge 网络下容器之间只能用 IP 互访,且每个新容器创建时 IP 可能变化,这也是官方推荐改用自定义网络的直接理由。
host 模式的端口冲突与性能取舍
host 模式跳过 NAT,减少一层转发,短连接场景下延迟收益明显。实测同一台 4 核 8G 机器上用 wrk 压测,host 模式约 42000 req/s,bridge 模式约 35000 req/s,差距约 20%。代价是端口独占,宿主上 8080 被占用时容器直接启动失败:
docker: Error response from daemon: driver failed programming external connectivity on endpoint web: Bind for 0.0.0.0:8080 failed: port is already allocated.
解决办法是先确认占用方:ss -lntp | grep 8080。若确实需要共存,只能改端口或退回 bridge 模式并用 -p 8081:8080 映射。
container 模式与生命周期绑定
共享网络命名空间的容器,其网络生命周期与目标容器完全一致。目标容器停止,共享者会失去网络。常用于 sidecar 场景,例如日志采集器与业务容器共享 IP,采集器直接访问 127.0.0.1 上的业务端口:
docker run -d --name app myapp:1.2 docker run -d --name logside --network container:app fluent/fluent-bit
注意 --network container:xxx 与 -p 互斥,同时使用会报错,端口发布必须写在目标容器上。
坑一:默认 bridge 下 DNS 解析失败
用 docker-compose 起过服务后,改成 docker run 手动起容器,发现代码里写 http://db:5432 一直报 getaddrinfo ENOTFOUND db。原因是容器接在默认 bridge 上,内置 DNS 不做容器名解析。检查方式:
docker exec -it web cat /etc/resolv.conf # nameserver 127.0.0.11 才对;若为 8.8.8.8 说明未启用内置 DNS
解决:创建自定义网络,并用 --network-alias 指定与代码一致的别名,或者把所有容器迁到同一个自定义网络。迁移时要注意容器必须先断开旧网络再接入新网络,否则 IP 会变成两个网段并存的状态。
坑二:自定义子网与办公网段冲突
某次在客户内网部署,自定义网络选了 172.17.0.0/16,结果容器完全无法访问宿主所在的内网服务,但容器之间正常。用 ip route 查看,172.17.0.0/16 同时出现在 docker0 和客户内网网关上,流量被误导。诊断:
docker network inspect appnet | grep Subnet ip route | grep 172.17
解决:避开 172.16.0.0/12、10.0.0.0/8 等常被内网占用的段,改用 100.64.0.0/10 这类 CGNAT 段,并在 /etc/docker/daemon.json 中固定默认地址池:
{
"default-address-pools": [
{"base": "100.64.0.0/12", "size": 24}
]
}改完执行 systemctl restart docker。已有容器不会自动换网段,需要重建。
选型建议与小结
需要容器名互访、需要隔离网段的多容器应用,用自定义 bridge;对延迟极度敏感且端口可控的网关类服务,用 host;纯离线批处理用 none 再显式接入所需网络;sidecar 与服务网格边车用 container 模式共享命名空间。
小结:默认 bridge 没有 DNS 解析能力,所以生产环境更推荐自定义 bridge 网络;host 模式换 20% 吞吐但失去端口隔离;container 模式的网络生命周期跟随目标容器;自定义子网必须先排查与内网路由的冲突,否则容器内部互访正常而对外访问全断。落地前用 docker network inspect 和 ip route 各核对一次即可。
- 点赞
- 收藏
- 关注作者
评论(0)