在 Docker 环境中,容器“无法联网”“能访问网关却访问不了外部”“宿主机找不到对应网卡”等问题,往往与网络命名空间、veth 设备、网桥或转发规则有关。理解数据包如何从容器进入宿主机,是快速定位故障的关键。本文从工作原理出发,整理一套可直接执行的排查流程。🔍
一、网络命名空间如何实现隔离
Linux 网络命名空间简称 netns,它可以隔离网卡、IP 地址、路由表、ARP 邻居表、防火墙规则和端口等网络资源。Docker 创建容器时,通常会为容器准备独立的网络命名空间,因此容器内执行 ip addr 或 ip route,看到的是该容器自己的网络配置,而不是宿主机的配置。
这种隔离并不代表容器与宿主机完全断开。Docker 会根据所选网络驱动建立通信通道。以默认 bridge 网络为例,容器拥有自己的 eth0,宿主机上则存在一块与之配对的 veth 网卡,两者共同组成一条虚拟链路。
二、veth 链路与 Docker 网桥
veth 可以理解为一根虚拟网线的两个端点:数据包从一端进入,就会从另一端出现。Docker 通常将其中一端放入容器网络命名空间并命名为 eth0,另一端保留在宿主机中,再连接到 docker0 或用户自定义的 Linux bridge。
容器访问外部网络时,典型路径为:容器 eth0 → 宿主机 veth → Docker 网桥 → 宿主机路由与转发规则 → 物理网卡。返回流量沿相反路径进入容器。若其中任一环节出现接口未启用、网桥脱离、路由缺失、转发关闭或防火墙拦截,通信都可能失败。🔗
快速确认网络拓扑
- 使用 docker inspect 容器名 查看容器所属网络、IP 地址、网关和网络 ID。
- 在容器内执行 ip addr、ip route,确认 eth0、地址和默认路由是否存在。
- 在宿主机执行 ip link,检查相关 veth 接口是否处于 UP 状态。
- 执行 bridge link,确认 veth 是否已加入正确的 Docker 网桥。
- 执行 docker network inspect 网络名,核对网段、网关及已连接容器。
三、按网络层次定位故障
排查时不要一开始就修改防火墙或重启 Docker。更稳妥的方法是从容器内部向外逐层测试,这样可以迅速缩小问题范围。🧭
- 检查本地接口:确认容器 eth0 处于 UP 状态,IP 地址属于 Docker 网络配置的子网。若没有地址,重点检查容器网络连接和 Docker 网络数据库。
- 测试默认网关:从容器访问默认网关。如果失败,应检查 veth 配对关系、网桥端口状态、子网掩码以及邻居表。
- 测试宿主机外网:若网关可达但外部 IP 不可达,检查宿主机是否启用了 IPv4 转发。可执行 sysctl net.ipv4.ip_forward,正常情况下其值应为 1。
- 区分 DNS 故障:先测试外部 IP,再测试域名。IP 可达而域名失败,通常说明容器的 DNS 配置、宿主机解析服务或上游 DNS 存在问题。
- 检查端口映射:外部无法访问容器服务时,确认应用是否监听在 0.0.0.0,而不是仅监听 127.0.0.1,同时核对 Docker 发布端口和宿主机监听状态。
四、veth 异常的重点检查方法
宿主机上的 veth 名称通常是随机生成的,不能只凭名称判断它属于哪个容器。可以先获取容器主进程 PID,再进入其网络命名空间观察接口索引。常用思路是执行 docker inspect -f 获取 PID,随后通过 nsenter -t PID -n ip link 查看容器网卡信息,并与宿主机 ip link 显示的 peer 索引进行对应。
如果容器内 eth0 存在,但宿主机对应 veth 消失,可能是网络命名空间与宿主机链路状态不一致。此时优先尝试将容器断开并重新连接网络,而不是手工创建同名接口。可使用 docker network disconnect 和 docker network connect 重建网络附件;对无状态容器,也可以重新创建容器。
注意:不要在未记录现场信息前直接删除 docker0、清空防火墙规则或重启宿主机。这些操作会破坏证据,还可能影响其他正常容器。
五、抓包判断数据包停在哪里
当接口、地址和路由看起来都正常时,抓包是最直观的手段。可以分别在容器 eth0、宿主机 veth、Docker 网桥和物理网卡上使用 tcpdump -ni 接口名 观察流量。
若容器 eth0 能看到请求,而宿主机 veth 看不到,说明 veth 链路或命名空间关联异常;若网桥上有包、物理网卡上没有,重点检查路由、IP 转发及防火墙 FORWARD 链;若请求能够发出但没有返回包,则应继续检查上游网络、安全策略和目标服务。📡
六、常见故障与修复方向
- veth 状态为 DOWN:检查配对端是否存在,并确认接口和网桥均已启用。
- 容器没有默认路由:重新连接 Docker 网络,检查自定义网络的网关参数。
- 容器之间无法通信:确认它们是否处于同一网络,并检查网络隔离及防火墙规则。
- 外网访问失败:检查 IP 转发、NAT 规则、FORWARD 策略以及宿主机出口路由。
- 重启后网络异常:排查防火墙管理工具、系统网络服务是否覆盖了 Docker 自动生成的规则。
总结
Docker bridge 网络的核心链路是“容器网络命名空间+veth 配对+Linux 网桥+宿主机转发与 NAT”。故障排查应遵循从内到外的顺序:先看容器接口和路由,再测网关,随后检查 veth、网桥、转发、防火墙与出口网络,最后通过多点抓包确认数据包中断位置。掌握这条链路后,大多数容器网络问题都能被拆解为明确、可验证的小问题。✅