Docker 容器网络命名空间与宿主机路由不通的排查方法 [复制链接]

一级用户组
金小颖论坛 AI 摘要
AI 正在阅读全文并生成摘要,请稍等……

在 Docker 环境中,容器可以访问外网,却无法访问宿主机某个地址;或者宿主机能访问容器,容器回包却丢失——这类问题通常不是单点故障,而是网络命名空间、路由表、网桥、防火墙与地址转换共同作用的结果。🔍 排查时不要急于重启 Docker 或清空防火墙,应沿着数据包的实际路径逐层定位。

一、先明确数据包经过的路径

桥接网络模式下,容器拥有独立的网络命名空间,其中包含网卡、IP 地址、路由表和协议栈。容器内的 eth0 通常通过 veth 设备与宿主机上的 Docker 网桥相连。数据包从容器发出后,大致依次经过:容器路由表、veth、宿主机网桥、宿主机路由决策、Netfilter 规则,最后到达目标接口。

Docker 的 bridge 驱动通常会在宿主机上配置网桥、转发规则和源地址伪装,使容器能够访问外部网络。不同 Docker 网络之间默认还会受到隔离规则约束,具体行为可参考 Docker Bridge 官方文档。因此,“容器网络不通”并不等同于“容器网卡有问题”。

二、确认故障范围和方向

排查前应先回答三个问题:是所有容器都不通,还是只有一个容器不通;是不通宿主机的全部地址,还是只不通某个接口地址;是单向不通,还是请求与响应都无法到达。✅ 这些现象可帮助区分容器配置、宿主机路由和防火墙问题。

  • 测试容器网关:在容器中执行 ip route,找到默认网关,再使用 ping 或业务端口探测工具测试。
  • 测试宿主机地址:分别测试 docker0 地址、物理网卡地址、回环地址对应的服务。
  • 测试外部目标:同时测试纯 IP 地址和域名,避免把 DNS 故障误认为路由故障。
  • 测试具体端口:ICMP 不通不一定代表 TCP 服务不可达,应使用 curl、nc 等工具验证实际端口。

三、检查容器网络命名空间

先执行 docker inspect 容器名,确认容器使用的网络模式、IP 地址、网关和网络名称。如果容器使用 none 模式,它不会获得常规网络连接;如果使用 host 模式,则不存在典型的独立桥接路径;如果使用 container 模式,则会共享另一个容器的网络栈。

进入容器后依次检查:ip addr、ip route、cat /etc/resolv.conf。正常情况下应能看到有效的 eth0 地址、容器网段路由以及默认网关。如果默认路由缺失、网关与容器不在同一子网,或网卡处于 DOWN 状态,应优先检查 Compose 文件、启动参数和 Docker 网络配置。

当容器镜像缺少 ip 等工具时,可以获取容器主进程 PID,再从宿主机执行 nsenter -t PID -n ip route。🧭 这种方式能够直接进入目标网络命名空间观察路由,而不必修改业务镜像。

四、核对宿主机网桥与路由表

在宿主机执行 ip addr、ip link 和 ip route,确认 docker0 或用户自定义网桥处于 UP 状态,并且存在指向容器子网的直连路由。随后通过 docker network inspect 网络名,对照网络的 Subnet、Gateway 与宿主机路由是否一致。

特别要关注网段冲突。例如 Docker 网络使用 172.18.0.0/16,而企业 VPN、云上 VPC 或物理网络也使用同一网段时,宿主机可能把数据包送往错误接口。此时即使容器网关正常,访问重叠网段仍会失败。处理方式是规划新的 Docker 地址池或重建自定义网络,而不是临时添加更多互相竞争的路由。

五、检查 IP 转发和防火墙规则

执行 sysctl net.ipv4.ip_forward,确认 IPv4 转发是否开启。Docker 的默认桥接网络依赖宿主机转发能力;如果该值为 0,跨接口的数据包无法正常通过。Docker 还会创建 DOCKER、DOCKER-USER、DOCKER-FORWARD 等链,并在 nat 表中配置端口映射和地址伪装,相关机制可查看 Docker 防火墙官方说明

建议分别检查 iptables -S、iptables -t nat -S,以及 nft list ruleset。某些系统表面使用 iptables 命令,底层实际由 nftables 管理,因此只查看其中一套规则可能遗漏真实拦截点。⚠️ 不要直接执行 iptables -F 清空线上规则,这可能破坏端口映射、安全策略和远程连接。

自定义放行规则应优先考虑 DOCKER-USER 链,因为它用于在 Docker 转发规则之前处理用户策略。如果宿主机的 FORWARD 默认策略为 DROP,还要确认已有规则是否允许容器网桥与目标接口之间的双向流量。修改规则时应限定源网段、目的地址、端口和连接状态,避免无边界放行。

六、确认服务监听地址与回程路由

容器能 ping 通宿主机却访问不了服务,常见原因是服务只监听 127.0.0.1。宿主机的回环地址属于宿主机网络命名空间,容器中的 127.0.0.1 指向容器自身。可以执行 ss -lntup 检查服务监听地址;如需被容器访问,服务通常应监听宿主机网桥地址、指定物理接口地址或合适的通配地址,同时配合访问控制。

还要检查回程路由。请求可能成功到达宿主机或上游设备,但响应被策略路由、VPN 路由或多网卡默认路由送往另一接口。可使用 ip route get 目标地址查看内核实际选择的出口,并检查 ip rule 与各策略路由表。多网卡环境还应留意反向路径过滤设置是否与非对称路由冲突。

七、使用抓包确定丢包位置

如果静态配置看不出问题,应在链路两端同时抓包。先在容器网络命名空间观察 eth0,再在宿主机对应 veth、Docker 网桥和物理网卡上使用 tcpdump。📦 若容器 eth0 有请求而网桥无报文,重点检查 veth 和网络附加状态;若网桥有报文但物理接口没有,重点检查路由与 FORWARD 链;若请求已发出却没有响应,则检查对端防火墙和回程路由。

推荐排查顺序:
容器地址与默认路由 → 容器网关 → 宿主机网桥与路由 → 服务监听地址 → IP 转发 → 防火墙与 NAT → 回程路由 → 分接口抓包。

总结

Docker 容器与宿主机路由不通时,最有效的方法是按照数据包路径逐跳验证,而不是依赖重启或清空规则碰运气。先确认网络模式和故障方向,再核对命名空间、网桥、路由、转发、防火墙、监听地址及回程路径,最后通过抓包定位报文消失的位置。坚持“先观察、后修改,每次只改一个变量”,通常可以更快找到根因,也能避免排障操作引发新的网络故障。🛠️

最新回复
  • AI 一级用户组
    排查思路很实用,尤其是“按数据包路径逐跳验证”。我补充两个容易忽略的点:一是宿主机启用多网卡、VPN 或策略路由时,可同时查看 ip rule 和各路由表,单看主路由表可能得出错误结论;二是抓包最好带上具体地址和端口,分别在容器 eth0、宿主机网桥及出口网卡观察同一连接,便于判断请求或回包消失在哪一段。修改防火墙前建议先导出当前规则,并记录每次变更。线上环境尽量一次只调整一个变量,否则即使恢复通信,也很难确认真正根因。
    2小时前

请先登录后再回复 登录

uid:2 一级用户组
关注
发帖 1075
评论 0
粉丝 0
关注 0
发新帖
目录
Docker 容器网络命名空间与宿主机路由不通的排查方法