Docker Compose 无法直接配置容器级网络镜像,需通过 macvlan+混杂模式(真旁路)、自定义 bridge+iptables TEE(兼容云环境)或 nsenter 临时切入命名空间三种方案实现无感抓包。

在 Docker Compose 中无法直接配置“容器级网络镜像”——因为 Compose 本身不提供流量镜像(SPAN/Port Mirroring)能力,它只是编排工具,底层依赖 Docker 网络驱动和宿主机网络设施。所谓“多服务无感抓包”,本质是让抓包容器**被动旁路监听**其他服务间的双向通信,而非修改业务容器配置或侵入其网络栈。
用 macvlan + 物理网卡混杂实现真正旁路镜像
这是最接近“无感”的方案:抓包容器与被测服务处于同一二层域,无需改动任何服务定义,也不依赖 iptables 或 docker0 转发。
- 宿主机物理网卡(如 eth0)需支持混杂模式:
sudo ip link set eth0 promisc on - 在 docker-compose.yml 中声明 macvlan 网络(注意指定
parent和子网):
mirror-net:
driver: macvlan
driver_opts:
parent: eth0
ipam:
config:
- subnet: 192.168.1.0/24
gateway: 192.168.1.1
- 所有服务(包括 sniffer)都加入该网络,并为 sniffer 容器添加必要权限:
app-a:
image: nginx:alpine
networks: [mirror-net]
app-b:
image: curlimages/curl
command: sleep infinity
networks: [mirror-net]
sniffer:
image: nicolaka/netshoot
cap_add: [NET_ADMIN]
networks: [mirror-net]
command: sh -c "ip link set eth0 promisc on && tcpdump -i eth0 -w /tmp/capture.pcap -s 0 host 192.168.1.10 and host 192.168.1.11"
启动后,sniffer 容器能捕获 app-a ↔ app-b 的完整以太网帧(含双向 MAC 层),业务容器完全无感知、零配置变更。
用自定义 bridge + iptables tee 实现兼容性抓包
适用于云主机、虚拟机等无法直连物理网卡的环境。核心是将进出 docker0 的双向流量复制一份到本地回环接口,再由抓包容器监听 lo。
- 先启用 docker0 混杂:
sudo ip link set docker0 promisc on - 创建自定义 bridge 网络(避免干扰默认网络):
mirror-br:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
- 在 sniffer 容器启动时注入 iptables 规则(需挂载宿主机
/proc/sys/net/ipv4/ip_forward并开启转发):
image: nicolaka/netshoot
cap_add: [NET_ADMIN, NET_RAW]
volumes:
- /proc/sys/net/ipv4/ip_forward:/proc/sys/net/ipv4/ip_forward:ro
command: sh -c "
echo 1 > /proc/sys/net/ipv4/ip_forward &&
iptables -t mangle -A PREROUTING -s 172.20.0.0/16 -d 172.20.0.0/16 -j TEE --gateway 127.0.0.1 &&
iptables -t mangle -A POSTROUTING -s 172.20.0.0/16 -d 172.20.0.0/16 -j TEE --gateway 127.0.0.1 &&
tcpdump -i lo -w /tmp/mirror.pcap -s 0"
该方式下,app-a 与 app-b 仍使用标准 bridge 配置,无需修改;sniffer 通过 lo 接口捕获被复制的双向 IP 包(不含 MAC 层),对业务透明。
用 nsenter 临时切入命名空间抓取逻辑流
适合调试阶段快速验证,不需提前规划网络,但非持久化方案。
- 保持服务使用默认网络(如
myproject_default) - 启动一个带 netns 权限的调试容器(可复用):
image: nicolaka/netshoot
cap_add: [NET_ADMIN]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: tail -f /dev/null
- 执行命令切入目标容器网络命名空间并抓包(例如抓 app-a 与 app-b 通信):
docker-compose exec debug nsenter -t $(pidof -s app-a) -n tcpdump -i any -w /tmp/a-to-b.pcap host $(dig +short app-b | head -1)
此方法不改写 compose 配置,也不影响运行中服务,但每次需手动触发,不适合长期监控。


















