本质是宿主机路由表被Docker误加default via 172.17.0.1 dev docker0干扰,导致外网流量被导向网桥;需三步解决:立即删除冲突路由、修改daemon.json中bip为不重叠网段(如192.168.200.1/24)、配置SNAT并启用ip_forward。

容器在多网卡宿主机下默认网关选错,本质不是容器配置问题,而是宿主机路由表被干扰——Docker启动时悄悄加了一条 default via 172.17.0.1 dev docker0,和你业务网卡的默认路由并存,内核按模糊匹配把外网流量全导进网桥里,结果就是“容器能 ping 宿主机,但 curl google.com 超时”。解决要分三步:清路由、避冲突、定出口。
立刻恢复连通性:删掉那条错误的默认路由
这是最急的一步,5秒就能让现有容器恢复上网:
- 运行
ip route,确认是否同时存在两条default via,比如一条走ens33(你的业务网卡),另一条走docker0 - 直接删掉 Docker 擅自加的那条:
sudo ip route del default via 172.17.0.1 dev docker0 - 再跑一次
ip route,确保只剩一条业务默认路由,例如default via 192.168.5.1 dev ens33
永久避免冲突:改掉 docker0 的默认网段
Docker 默认用 172.17.0.0/16,万一你业务网段是 172.17.10.0/24 或 172.16.0.0/12,内核会优先匹配更长前缀,流量就卡在 docker0 里出不去:
- 编辑
/etc/docker/daemon.json,写入不重叠的子网,例如:{"bip": "192.168.200.1/24"} - 停服务:
sudo systemctl stop docker containerd - 删旧网桥:
sudo ip link delete docker0 - 重启 Docker:
sudo systemctl start docker - 验证:
ip addr show docker0应显示新 IP,且ip route | grep 192.168.200只有一条直连路由
强制流量走指定网卡:配 SNAT + 开转发
光有默认路由还不够。当宿主机有 eth0(内网)和 eth1(公网)时,得告诉系统:“所有容器的包,必须从 eth1 出去”:
- 确认容器网桥的宿主机侧 IP(比如
192.168.200.1),这个地址最好属于eth1所在子网,或能被其网关转发 - 加 SNAT 规则(假设
eth1的 IP 是203.0.113.10):sudo iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -o eth1 -j SNAT --to-source 203.0.113.10 - 开启内核转发:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward,并写入/etc/sysctl.conf持久化:net.ipv4.ip_forward = 1
检查网络模式与 DNS 继承逻辑
不同模式对宿主机路由依赖程度不同,别踩坑:
- bridge 模式(默认):完全靠宿主机默认路由 + iptables NAT,上面三步必须做完
-
host 模式:容器直接复用宿主机网络栈,
ip route和宿主机一模一样,多网卡路由问题会原样暴露,慎用 - DNS 建议显式配置,避免继承宿主机可能混乱的
resolv.conf,在docker run加--dns 8.8.8.8,或在docker-compose.yml中写dns: ["114.114.114.114"]


















