简体   繁体   English

找出哪个网络接口属于docker容器

[英]Find out which network interface belongs to docker container

Docker creates these virtual ethernet interfaces veth[UNIQUE ID] listed in ifconfig . Docker 创建ifconfig列出的这些虚拟以太网接口veth[UNIQUE ID] How can I find out which interface belongs to a specific docker container?如何找出哪个接口属于特定的 docker 容器?

I want to listen to the tcp traffic.我想听 tcp 流量。

To locate interface定位接口
In my case getting value from container was like (check eth0 to):在我的情况下,从容器中获取价值就像(检查eth0到):

$ docker exec -it my-container cat /sys/class/net/eth1/iflink
123

And then:然后:

$ ip ad | grep 123
123: vethd3234u4@if122: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker_gwbridge state UP group default

Check with tcpdump -i vethd3234u4检查tcpdump -i vethd3234u4


Reference about mysterious iflink from http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-class-net :来自http://lxr.free-electrons.com/source/Documentation/ABI/testing/sysfs-class-net 的关于神秘iflink参考:

150 What:           /sys/class/net/<iface>/iflink
151 Date:           April 2005
152 KernelVersion:  2.6.12
153 Contact:        netdev@vger.kernel.org
154 Description:
155                 Indicates the system-wide interface unique index identifier a
156                 the interface is linked to. Format is decimal. This attribute is
157                 used to resolve interfaces chaining, linking and stacking.
158                 Physical interfaces have the same 'ifindex' and 'iflink' values.

Based on the provided answer (which worked for me), I made this simple bash script:根据提供的答案(对我有用),我制作了这个简单的 bash 脚本:

#!/bin/bash

export containers=$(sudo docker ps --format "{{.ID}}|{{.Names}}")
export interfaces=$(sudo ip ad);
for x in $containers
        do
                export name=$(echo "$x" |cut -d '|' -f 2);
                export id=$(echo "$x"|cut -d '|' -f 1)
                export ifaceNum="$(echo $(sudo docker exec -it "$id" cat /sys/class/net/eth0/iflink) | sed s/[^0-9]*//g):"
                export ifaceStr=$( echo "$interfaces" | grep $ifaceNum | cut -d ':' -f 2 | cut -d '@' -f 1);
                echo -e "$name: $ifaceStr";
done

My answer more like improvement on that important topic because it didn't help to " Find out which network interface belongs to docker container ", but, as author noticed, he " want to listen to the tcp traffic " inside docker container - I'll try to help on that one during your troubleshooting of network.我的回答更像是对这个重要主题的改进,因为它对“找出属于 docker 容器的网络接口”没有帮助,但是,正如作者所注意到的,他“想监听docker 容器内的 tcp 流量” - 我'在您对网络进行故障排除期间,我会尽力帮助解决这个问题。

Considering that veth network devices are about network namespaces, it is useful to know that we can execute program in another namespace via nsenter tool as follow (remember - you need a privileged permission (sudo/root) for doing that):考虑到veth网络设备是关于网络命名空间的,知道我们可以通过nsenter工具在另一个命名空间中执行程序如下(请记住 - 您需要特权权限(sudo / root)才能执行此操作)很有用:

Get ID of any container you are interested in capture the traffic, for example it will be 78334270b8f8获取您有兴趣捕获流量的任何容器的 ID,例如它将是78334270b8f8

Then we need to take PID of that containerized application (I assume you are running only 1 network-related process inside container and want to capture its traffic. Otherwise, that approach is hard to be suitable):然后我们需要获取该容器化应用程序的PID (我假设您在容器内仅运行 1 个与网络相关的进程并希望捕获其流量。否则,这种方法很难适用):

sudo docker inspect 78334270b8f8 | grep -i pid

For example, output for pid will be 111380 - that's ID of your containerized app, you can check also it via ps command: ps aux | grep 111380例如, pid输出将是111380 - 这是您的容器化应用程序的 ID,您也可以通过ps命令检查它: ps aux | grep 111380 ps aux | grep 111380 just in curiosity. ps aux | grep 111380只是出于好奇。

Next step is to check what network interfaces you have inside your container:下一步是检查您的容器内有哪些网络接口:

sudo nsenter -t 111380 -n ifconfig

This command will return you list of network devices in network namespace of the containerized app (you should not have ifconfig tool on board of your container, only on your node/machine)此命令将返回容器化应用程序网络命名空间中的网络设备列表(您的容器上不应有ifconfig工具,只能在您的节点/机器上)

For example, you need to capture traffic on interface eth2 and filter it to tcp destination port 80 (it may vary of course) with this command:例如,您需要使用以下命令捕获接口eth2上的流量并将其过滤到 tcp 目标端口 80(当然可能会有所不同):

sudo nsenter -t 111380 -n tcpdump -nni eth2 -w nginx_tcpdump_test.pcap 'tcp dst port 80'

Remember, that in this case you do not need tcpdump tool to be installed inside your container.请记住,在这种情况下,您不需要在容器内安装tcpdump工具。

Then, after capturing packets, .pcap file will be available on your machine/node and to read it use any tool you prefer tcpdump -r nginx_tcpdump_test.pcap然后,在捕获数据包后, .pcap文件将在您的机器/节点上可用并使用您喜欢的任何工具读取它tcpdump -r nginx_tcpdump_test.pcap

approach's pros:方法的优点:

  • no need to have network tools inside container, only on docker node容器内无需网络工具,仅在 docker 节点上
  • no need to search for map between network devices in container and node无需在容器和节点中搜索网络设备之间的映射

cons:缺点:

  • you need to have privileged user on node/machine to run nsenter tool您需要在节点/机器上拥有特权用户才能运行nsenter工具

One-liner of the solution from @pbaranski来自@pbaranski 的单行解决方案

num=$(docker exec -i my-container cat /sys/class/net/eth0/iflink | tr -d '\r'); ip ad | grep -oE "^${num}: veth[^@]+" | awk '{print $2}'

If you need to find out on a container that does not include cat then try this tool: https://github.com/micahculpepper/dockerveth如果您需要查找不包含cat的容器,请尝试使用此工具: https : //github.com/micahculpepper/dockerveth

You can also read the interface names via /proc/PID/net/igmp like (container name as argument 1):您还可以通过 /proc/PID/net/igmp 读取接口名称,例如(容器名称作为参数 1):

#!/bin/bash

NAME=$1
PID=$(docker inspect $NAME --format "{{.State.Pid}}")
while read iface id; do
    [[ "$iface" == lo ]] && continue
    veth=$(ip -br addr | sed -nre "s/(veth.*)@if$id.*/\1/p")
    echo -e "$NAME\t$iface\t$veth"
done < <(</proc/$PID/net/igmp awk '/^[0-9]+/{print $2 " " $1;}')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM