Docker自定义桥接网络下容器内域名解析失败及外部网络访问问题如何排查解决?
摘要:前言 在 Ubuntu 20.04 上的一台曾作为 Kubernetes 节点的服务器,退役后直接用于运行 docker-compose 部署的业务容器。核心症状是:使用自定义桥接网络的容器无法解析外部域名,且无法访问外部网络(ping 外
前言
在 Ubuntu 20.04 上的一台曾作为 Kubernetes 节点的服务器,退役后直接用于运行 docker-compose 部署的业务容器。核心症状是:使用自定义桥接网络的容器无法解析外部域名,且无法访问外部网络(ping 外部 IP 100% 丢包),而使用 --network host 模式的容器一切正常。
整个排查过程历经多个层面:DNS 配置、systemd-resolved、Kubernetes 残留、Docker 版本、daemon.json 解析、iptables NAT 规则缺失,最终通过手动补充 MASQUERADE 规则彻底解决。
问题现象
容器内 cat /etc/resolv.conf 显示:nameserver 127.0.0.11
search openstacklocal
options ndots:0
并注释显示 ExtServers: [8.8.8.8 114.114.114.114 223.5.5.5](证明 daemon.json 中的 dns 配置被读取),但 nslookup baidu.com 超时。
容器内 ping 8.8.8.8 100% 丢包 → 说明不是单纯 DNS 问题,而是整个外部出站网络不通。
宿主机网络正常,host 网络模式容器正常。
iptables NAT 表为空,没有任何 MASQUERADE 规则。
问题根本原因(多重叠加)
Kubernetes 节点退役后残留:
kubelet、CNI 插件清理不彻底,导致 Docker daemon 在初始化用户自定义桥接网络时行为异常。
部分 sysctl 参数和 iptables 链残留,干扰 Docker 自动创建 NAT 规则。
Docker 自动 NAT 规则未创建:
正常情况下,Docker 会为每个桥接网络(包括用户自定义网络)在 iptables NAT 表的 POSTROUTING 链自动添加 MASQUERADE 规则,实现容器出站地址伪装。
本案例中,该规则始终缺失,导致容器发出的包(源 IP 为 172.18.x.x)无法得到回复。
daemon.json 配置部分失效:
虽然新版 Docker 能读取 dns 配置(容器内注释显示 ExtServers),但由于网络初始化异常,内置 DNS 代理(127.0.0.11)无法实际向外部上游 DNS 发送查询(出站不通)。
早期 daemon.json 曾因复制错误带有 < > 尖括号导致整个文件被忽略,后已修复,但 NAT 问题仍存。
旧版 Docker (19.03.15) 的历史影响:
即使升级到新版,旧状态可能部分继承,导致 NAT 规则不自动生成。
完整排查命令与过程
以下命令按实际排查顺序整理,便于复现。
