核心是选对抓包位置:容器内看原始报文,docker0看桥接流量,物理网卡或隧道接口看封装后出向流量,nsenter可直连容器网络命名空间;再精准过滤目标ip端口,最后用wireshark三步分析syn/syn-ack链路状态定位故障层。

在 Docker 容器环境下用 tcpdump 抓包,核心不是“能不能抓”,而是“在哪抓、抓什么、怎么看”。容器网络有隔离性,直接在宿主机上抓 docker0 或物理网卡,和进容器抓 eth0,看到的报文内容完全不同——前者能看到 NAT 后或桥接后的流量,后者只看到应用发出的原始请求。选错位置,问题就永远藏在黑盒里。
宿主机侧:快速定位跨容器或出向通信问题
适合排查容器间不通、访问外部服务失败、DNS 解析异常等场景。无需进入容器,对运行环境零侵入。
- 先查目标容器 IP:
docker inspect -f '{{.NetworkSettings.IPAddress}}' <container_id></container_id> - 在宿主机抓该容器所有进出流量:
sudo tcpdump -i docker0 host <container_ip> -w /tmp/bridge.pcap</container_ip>(若用自定义 bridge 网络,把docker0换成对应网桥名,如br-xxxx) - 想看是否发出了 SYN 包又没响应?加过滤:
sudo tcpdump -i docker0 'host <target_ip> and tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'</target_ip>
容器内部:确认应用层行为与本地栈状态
当你怀疑是容器内 DNS 配置错误、HTTP Client 超时设置不合理、或连接池耗尽时,必须进容器看原始报文。
- 先进容器:
docker exec -it <container_id> /bin/sh</container_id>(或/bin/bash) - 检查并安装 tcpdump:
• Alpine 镜像:apk add --no-cache tcpdump
• Debian/Ubuntu 镜像:apt-get update && apt-get install -y tcpdump - 抓本机对外流量:
tcpdump -i eth0 port 80 or port 443 -w /tmp/app.pcap - 注意:精简镜像可能无 shell,可用
docker run --rm -v $(pwd):/host alpine:latest sh -c "apk add --no-cache tcpdump && tcpdump -i eth0 -w /host/out.pcap port 80"临时抓包
网络命名空间直连:绕过容器工具限制,精准捕获真实流量
当容器没装 tcpdump、没 shell、甚至用了 host 网络模式或 CNI 插件(如 Calico、Cilium),nsenter 是最可靠的方式——它直接切入容器的 netns,效果等同于在容器内执行命令。
- 获取容器 PID:
docker inspect -f '{{.State.Pid}}' <container_id></container_id> - 进入其网络命名空间抓包:
sudo nsenter -t <pid> -n tcpdump -i any -w /tmp/ns.pcap port 5432</pid>
(-i any避免因不确定网卡名而漏包;-n表示 net namespace) - 若需抓 vxlan 封装流量(如 Flannel):
sudo nsenter -t <pid> -n tcpdump -i flannel.1 udp port 8472</pid>
抓完之后怎么判断问题在哪
把 .pcap 文件拖进 Wireshark,重点看三段链路:
- 容器内有 SYN 发出,但 docker0 上收不到 → veth 设备损坏、容器网络栈崩溃、或 iptables DROP 规则误匹配
- docker0 收到 SYN,物理网卡或隧道接口(如 flannel.1)没发出 → 宿主机路由缺失、SNAT 规则未生效、或防火墙(ufw/iptables/firewalld)拦截
- 目标端收到 SYN 却不回 SYN-ACK → 目标服务未监听该端口、端口被其他进程占用、或目标节点防火墙丢包
- SYN-ACK 正常收到,但应用无响应 → 问题不在网络层,大概率是业务代码阻塞、数据库连接池满、或 TLS 握手卡住











