【问题标题】:How can I capture the network traffic of Docker Swarm containers using netshoot and network_mode?如何使用 netshoot 和 network_mode 捕获 Docker Swarm 容器的网络流量?
【发布时间】:2025-11-27 16:05:02
【问题描述】:

过去,我们已经成功使用nicolaka/netshoot 来捕获使用docker-compose 运行的Docker 容器的网络流量:

$ cat docker-compose.yml
version: "3.6"
services:
  tcpdump:
    image: nicolaka/netshoot
    depends_on:
      - nginx
    command: tcpdump -i any -w /data/nginx.pcap
    network_mode: service:nginx
    volumes:
      - $PWD/data:/data

  nginx:
    image: nginx:alpine
    ports:
      - 80:80
$ docker-compose up
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Creating network "netshoot_default" with the default driver
Creating netshoot_nginx_1 ... done
Creating netshoot_tcpdump_1 ... done
$ curl -s -o /dev/null http://localhost
$ docker-compose down
Stopping netshoot_tcpdump_1 ... done
Stopping netshoot_nginx_1   ... done
Removing netshoot_tcpdump_1 ... done
Removing netshoot_nginx_1   ... done
Removing network netshoot_default
$ tshark -2 -r data/nginx.pcap http
   13   4.760638   172.25.0.1 → 172.25.0.2   HTTP 145 GET / HTTP/1.1
   17   4.760866   172.25.0.2 → 172.25.0.1   HTTP 684 HTTP/1.1 200 OK  (text/html)
$

不幸的是,如果容器以docker stack create 启动,这似乎不起作用,因为不支持network_mode

$ docker stack deploy -c docker-compose.yml netshoot
Ignoring unsupported options: network_mode

Creating network netshoot_default
Creating service netshoot_tcpdump
Creating service netshoot_nginx
$ curl -s -o /dev/null http://localhost
$ docker stack rm netshoot
Removing service netshoot_nginx
Removing service netshoot_tcpdump
Removing network netshoot_default
$ tshark -2 -r data/nginx.pcap http
$ tshark -2 -r data/nginx.pcap tcp
      6   4.221820   172.18.0.1 → 172.18.0.2   TCP 80 63798 → 80 [SYN] Seq=0 Win=65495 Len=0 MSS=65495 SACK_PERM=1 TSval=191764735 TSecr=0 WS=128
$

我们如何在 docker-compose.yml 中配置我们的 netshoot 容器,以便它们共享其他容器的网络接口,即使它们是通过 docker stack create 启动的?

【问题讨论】:

  • 在 docker compose 中您指定:“network_mode: service:nginx” 是错字吗?好的,不。有用。我不知道那个表格。
  • 如果你能做到,请写一个可重现的例子,因为这看起来真的很有趣
  • 可以在每个服务上提供“network:xxx”来强制网络链接

标签: docker networking docker-compose docker-swarm


【解决方案1】:

从那里:https://forums.docker.com/t/how-to-tcpdump-inter-service-traffic/23463/4

swarm 中的覆盖网络流量不会通过 docker0 或 docker_gwbridge。 有2个选项: 选项1: 进入容器并执行 tcpdump: nicolaka/netshoot 是包含所有网络调试工具的容器。

docker run -ti --net container: <container name/id> nicolaka/netshoot
tcpdump -i <eth0>

选项 2: 进入覆盖网络的网络命名空间并执行 tcpdump: 首先使用 docker network inspect 找到覆盖网络 ID 开始调试容器挂载网络命名空间:

docker run -it --rm -v /var/run/docker/netns:/var/run/docker/netns --privileged=true nicolaka/netshoot

所有命名空间都列在: /var/run/docker/netns

找到与上一个命令的覆盖网络 ID 匹配的 swarm 覆盖网络命名空间。 然后进入网络命名空间:

nsenter --net=/var/run/docker/netns/ sh
tcpdump -i vxlan0

【讨论】:

    【解决方案2】:

    我不知道这是否适用于您正在尝试做的事情,但您仍然可以附加到服务容器的网络命名空间。

    假设您为 docker swarm 节点设置了无密码 ssh,这样: docker -H ssh://user@nodeN container ls 然后从您的 docker 节点之一检索容器列表:

    docker service ps --no-trunc service_of_interest
    

    将返回每个服务任务的 ID、名称和节点。选一个。然后只需在同一节点上运行 netshoot:

    docker -H ssh://user@$NODE run --rm -it --network container:$NAME.$ID nicolaka/netshoot

    您可以从例如 Makefile 中自动执行此操作。但是将它放在 docker-compose.yml 中是行不通的,因为您需要提供太多动态查找的详细信息并在特定节点上调用 docker。

    【讨论】:

      最近更新 更多