核心是解决容器与宿主机子网冲突导致的路由混乱。通过检查宿主机网段和docker0子网判断是否重叠,再选择修改bip或创建自定义网络解决,并清理残留、验证连通性。

核心是让容器流量能正确进出,不被宿主机路由表误判或丢弃。子网冲突会让系统分不清“该发给docker0还是真实局域网”,结果就是ping不通、端口映射失败、DNS查不到——本质是路由决策混乱。
确认是否真存在子网重叠
先别急着改配置,用两条命令快速验证:
- 查宿主机所在网段:
ip route | grep -E '^[0-9]|^default' | awk '{print $1}' | grep '\.' | head -1(比如输出192.168.3.0/24) - 查 docker0 当前子网:
ip addr show docker0 | grep 'inet ' | awk '{print $2}'(比如输出172.17.0.1/16)
如果宿主机网段落在 172.17.0.0/16、172.18.0.0/16 或 10.0.0.0/8 等大范围私有网段内,就极可能重叠。例如宿主机在 172.17.100.0/24,而 docker0 是 172.17.0.1/16,后者完全包含前者,必然冲突。
两种可靠解决路径
根据你是否想保留默认 bridge 行为,选其一即可:
-
方案一:改默认桥接网段(推荐用于新部署或可停服环境)
编辑/etc/docker/daemon.json,写入明确避开的子网,例如:{"bip": "10.200.0.1/16"}
保存后执行sudo systemctl restart docker。重启后ip addr show docker0应显示新地址,且旧容器需重建才能生效。 -
方案二:用自定义网络隔离(适合线上不能中断、多项目并存场景)
创建专属子网,如:docker network create -d bridge --subnet=192.168.123.0/24 myapp-net
启动容器时显式指定:docker run --network=myapp-net …
或在docker-compose.yml的networks下声明子网,避免依赖 Docker 自动分配。
清理残留防止“看似改了实则没生效”
只改配置不清理,旧路由和网桥残留常导致问题反复:
- 删掉所有已停容器:
docker rm -f $(docker ps -aq) - 清空无用自定义网络:
docker network prune - 手动删旧 docker0(谨慎):
sudo ip link delete docker0(Docker 重启时会自动重建) - 检查最终路由:
ip route | grep docker0,应只有一条指向新子网的记录,无重复或172.17.x.x类残留。
验证转发是否真正恢复
改完别只看 docker0 IP 变了,要测通路:
- 进容器 ping 宿主机网关(比如
ping 192.168.3.1),通说明出向正常 - 从宿主机 ping 容器 IP(如
ping 10.200.1.5),通说明入向正常 - 在容器里
curl http://www.baidu.com,成功说明 DNS + 出网完整链路 OK - 若仍异常,检查 iptables 是否有拦截规则:
sudo iptables -L -t nat -n | grep POSTROUTING,确保 MASQUERADE 规则对应的是新 docker0 接口。



















