排查 Docker 容器网络丢包需定位丢包发生的具体环节:先确认 veth-pair 两端状态与 MAC 匹配,再比对容器 eth0 与宿主机 veth 的 /proc/net/dev 收发包计数,若容器 tx_packets > 宿主机 rx_packets 则丢包在容器 egress 路径,若宿主机 tx_packets > 容器 rx_packets 则丢包在宿主机 ingress 路径。

排查 Docker 容器网络丢包,核心不是看“容器有没有丢包”,而是定位“包在哪个环节被丢”——veth-pair 本身不丢包,真正丢包发生在它连接的两端:容器内命名空间、宿主机网桥(如 docker0)、内核 netfilter 队列,或物理网卡驱动层。必须分层验证、逐段比对收发与丢弃计数。
确认 veth-pair 两端状态与配对关系
veth 是容器通信的底层通道,一端在容器内(如 eth0),另一端在宿主机(如 vethabc123)。两者必须成对、UP、MAC 匹配。
- 查容器 PID:docker inspect -f '{{.State.Pid}}' <container_id>
- 进容器命名空间查 eth0:nsenter -n -t <pid> -- ip link show eth0,确认状态为 UP,无 NO-CARRIER
- 在宿主机查对应 veth:ip link | grep "link-netnsid <N>"(N 来自上一步 eth0 的 link-netnsid),再执行 ip -d link show <veth_name>,核对 peer_ifindex 或 MAC 是否与容器内 eth0 一致
- 任一端 DOWN 或配对失败,说明网络初始化异常,需检查 dockerd 日志或重启容器
比对容器侧与宿主机侧 /proc/net/dev 统计
直接读取帧级统计比 ping/iperf 更可靠,能定位丢包发生的具体路径方向。
- 容器内收发:nsenter -n -t <pid> -- cat /proc/net/dev | grep eth0,重点关注 rx_packets、tx_packets、rx_dropped
- 宿主机 veth 接口:cat /proc/net/dev | grep vethabc123,同样看 rx/tx 各项
- 若容器 tx_packets > 宿主机 rx_packets → 丢包在容器 egress 路径(如 iptables OUTPUT DROP、tc qdisc 限速丢包)
- 若宿主机 tx_packets > 容器 rx_packets → 丢包在宿主机 ingress 路径(如 docker0 转发失败、rp_filter 拒绝、netfilter INPUT DROP)
检查网桥、iptables 与内核关键参数
流量经过 docker0 或 CNI 网桥时,常见瓶颈来自 conntrack 溢出、iptables 规则复杂、或反向路径过滤启用。
- 确认 veth 已挂载到网桥:brctl show docker0 或 ip link show master docker0
- 查 conntrack 使用率:cat /proc/sys/net/netfilter/nf_conntrack_count 和 /proc/sys/net/netfilter/nf_conntrack_max,比值超 90% 易触发丢包
- 检查是否启用 netfilter 桥接:sysctl net.bridge.bridge-nf-call-iptables,若为 1,所有桥接包都会走 iptables,规则过多会延迟甚至丢包
先确认是不是真丢包,排除“假抖动”干扰
微服务高并发下,“丢包”常是心跳超时、状态不同步引发的误判,并非真实网络层问题。
- 进容器执行:ping -M do -s 1472 8.8.8.8(1472 + 28 = 1500),能通说明路径支持标准 MTU;不通就逐步减小 -s 值,找到最大可用载荷,加 28 得出实际路径 MTU
- 查内核日志:dmesg | grep "too long",出现 “dropped packet, size 1514 > 1450” 就是 MTU 错配的铁证
- 对比容器状态:docker inspect <container> 查 State.Status,再和 Swarm Manager 或 Kubernetes 的任务状态比对。若容器内进程正常但平台标记为 failed,大概率是控制面误判


















