容器网络和应用网络不同,一个宿主机上可能运行几十个容器,每个容器有自己的网络命名空间,看到的是独立的网卡和路由表。如果容器之间突然无法通信,不要急着修改应用配置,应该先确认网络层是否正常。本文将介绍从宿主机和容器两个视角查看网络配置的方法。

一、先理解网络命名空间与veth接口
容器网络的隔离建立在Linux网络命名空间(netns)之上。每个容器启动时,Docker或Kubernetes会创建独立的网络命名空间,容器内部看到的lo回环接口和eth0虚拟网卡,与宿主机上的物理网卡并不在同一个网络栈中。宿主机上执行ip addr查不到容器内的IP地址,必须进入容器的网络命名空间才能看到。Docker默认不会把网络命名空间软链接到/var/run/netns,因此直接使用ip netns list可能看不到容器,需要借助容器主进程PID和nsenter命令。
每个容器网络通常由一对veth接口连接:一端在容器内作为eth0,另一端插在宿主机侧的Linux网桥上,例如默认的docker0网桥。可以通过宿主机上的ip link show type veth查看所有veth设备,再根据接口序号或对端索引确认对应关系。也可以使用ethtool -S命令查看veth接口的统计信息,辅助判断流量是否经过该接口。
# 查看宿主机上的虚拟网卡
ip link show type veth
# 查看容器主进程 PID
docker inspect -f '{{.State.Pid}}' mycontainer
# 进入容器网络命名空间查看接口
nsenter -t 12345 -n ip addr
# 或者直接通过 docker exec 查看
docker exec -it mycontainer ip addr
理解这一层后,排查问题时就知道容器网络不直接依赖物理网卡,而是通过veth和网桥转发。多容器之间通信异常时,首先确认它们是否连接在同一个网桥上,以及veth接口是否处于UP状态。如果veth接口被手动关闭或者网桥没有正确创建,容器内的应用会表现为无法获取IP或无法访问网关。
二、用Docker原生命令查看网络配置
Docker提供了几个直接查看网络的命令,适合快速定位bridge、overlay等场景下的配置问题。docker network ls会列出所有网络及其驱动类型,docker network inspect则能显示子网、网关、已接入容器以及IP地址分配情况。排查容器IP异常或网段冲突时,这些信息必不可少。
docker network ls
# 查看默认 bridge 网络详情
docker network inspect bridge
# 查看容器在所有网络中的 IP 地址
docker inspect -f '{{range $k, $v := .NetworkSettings.Networks}}{{$k}}: {{$v.IPAddress}}{{end}}' mycontainer
从输出中可以看到每个网络的Subnet和Gateway。如果两个容器处在不同子网,又没有正确配置路由,它们之间就无法直接通信。对使用bridge驱动的容器来说,跨网络通信需要经过宿主机防火墙转发,而overlay驱动则通常依赖VXLAN等隧道协议。检查容器具体有哪些网络、IP是否在预期网段内、网关是否指向正确的网桥地址,是排查容器网络配置的第一步。
如果容器通过映射端口提供服务,还需要检查宿主机上的NAT规则。docker port container可以查看端口映射是否创建成功,而iptables -t nat -L -n -v则能显示Docker自动添加的DNAT和SNAT规则。很多端口访问失败的问题并非容器内服务没启动,而是因为iptables规则没有生效或被后续操作覆盖。
docker port mycontainer iptables -t nat -L -n -v | grep DOCKER
三、进入容器检查路由、DNS与连通性
确认网络配置的外部视图正常后,还需要进入容器内部查看实际生效的路由表和DNS配置。容器中的应用只能看到容器命名空间里的网络状态,所以宿主机上测试通的IP不代表容器内也能通。docker exec -it mycontainer ip route可以查看容器默认网关和路由条目,cat /etc/resolv.conf则展示DNS服务器地址。很多容器无法解析域名但能ping通IP,原因就出在DNS配置错误或DNS服务器不可达。
docker exec -it mycontainer ip route docker exec -it mycontainer cat /etc/resolv.conf docker exec -it mycontainer nslookup ipipp.com
默认路由应该指向容器所在网段的网关,如果路由表里缺少默认路由,或者网关地址与docker network inspect中看到的Gateway不一致,容器就无法访问外部网络。DNS解析失败时,可以先测试nslookup或dig,再决定是修改resolv.conf还是检查DNS服务器连通性。需要注意的是,容器内不一定安装了这些工具,可以使用docker exec配合基础镜像自带的命令,或在宿主机上通过nsenter进入网络命名空间测试。
对于跨主机通信,还要确认Linux内核的IP转发是否开启。执行sysctl net.ipv4.ip_forward,如果返回0,宿主机不会转发容器间的数据包。此时可以使用sysctl -w net.ipv4.ip_forward=1临时开启,或写入/etc/sysctl.conf永久生效。当然,在Kubernetes等编排平台中,CNI插件通常会代为管理转发和路由,但手动修改过内核参数的环境容易忽略这一项。
sysctl net.ipv4.ip_forward # 临时开启 IP 转发 sysctl -w net.ipv4.ip_forward=1
四、使用抓包与日志定位复杂网络故障
当路由和配置看起来都正确,但通信仍然异常时,抓包是最直接的验证手段。可以进入容器的网络命名空间执行tcpdump,也可以在宿主机上对容器对应的veth接口抓包。通过观察TCP握手、DNS查询和重传情况,能够判断数据包是否从容器发出、是否到达宿主机网桥、响应是否正常返回。
# 进入容器网络命名空间抓包 nsenter -t 12345 -n tcpdump -i eth0 -nn # 在宿主机上抓取 veth 接口流量 tcpdump -i veth1a2b3c4 -nn
抓包结果中如果只看到SYN包而没有SYN-ACK返回,说明请求在中间被丢弃或被防火墙拦截。如果DNS查询反复超时,可以对比容器内配置的DNS服务器与宿主机使用的DNS服务器是否一致。还可以结合容器应用日志,查看是否因为网络连接超时导致服务启动失败。对于Kubernetes环境,可以使用kubectl exec进入Pod执行同样的命令,同时检查CNI插件的状态和节点上的iptables规则。
最后,建议把排查过程记录下来:先确认网络命名空间和veth接口状态,再查看网络模式、子网和IP分配,然后检查容器内路由与DNS,最后通过抓包验证数据流。这样的顺序可以避免盲目重启容器或修改配置,也方便团队协作时快速共享诊断信息。容器网络问题看似复杂,但底层原理并不神秘,熟悉这些查看命令后,多数故障都能在几分钟内定位到具体层面。