docker: how to get veth bridge interface pair easily?

i have 2 containers by docker, and bridge like this:

root@venus-166:~# docker ps
CONTAINER ID        IMAGE                                         COMMAND                CREATED             STATUS              PORTS                      NAMES
ef99087167cb        images.docker.sae.sina.com.cn/ubuntu:latest   /bin/bash -c /home/c   2 days ago          Up 21 minutes       0.0.0.0:49240->22223/tcp   night_leve3         
c8a7b18ec20d        images.docker.sae.sina.com.cn/ubuntu:latest   /bin/bash -c /home/c   2 days ago          Up 54 minutes       0.0.0.0:49239->22223/tcp   night_leve2 

bridge name bridge id       STP enabled interfaces
docker0     8000.72b675c52895   no      vethRQOy1I
                            vethjKYWka

How can i get which container match veth* ?

  • php-fpm Connection reset by peer
  • Docker : Persisting build argument in container during run?
  • Slow codeception coverage in docker
  • Docker : Could not resolve host: github.com - for go get ./
  • Root PID of Docker container
  • Exposing Elastic Beanstalk environment variables to Laravel's artisan using Docker
  • ef99 => vethRQOy1I or ef99 => vethjKYWka
    

    //———————————————————-

    I know it works by ethtool, but is there any better way?

  • how do developers add new function on a massive online Saas application although it is running?
  • Database with starttime and endtime [closed]
  • docker container does not start with json unmarshal error
  • Copy all files with given extension from docker container
  • PyCharm docker debugging error
  • Using sudo inside a docker container
  • 6 Solutions collect form web for “docker: how to get veth bridge interface pair easily?”

    Here’s a variation on the ethtool trick mentioned above, without actually using ethtool:

    function veth_interface_for_container() {
      # Get the process ID for the container named ${1}:
      local pid=$(docker inspect -f '{{.State.Pid}}' "${1}")
    
      # Make the container's network namespace available to the ip-netns command:
      mkdir -p /var/run/netns
      ln -sf /proc/$pid/ns/net "/var/run/netns/${1}"
    
      # Get the interface index of the container's eth0:
      local index=$(ip netns exec "${1}" ip link show eth0 | head -n1 | sed s/:.*//)
      # Increment the index to determine the veth index, which we assume is
      # always one greater than the container's index:
      let index=index+1
    
      # Write the name of the veth interface to stdout:
      ip link show | grep "^${index}:" | sed "s/${index}: \(.*\):.*/\1/"
    
      # Clean up the netns symlink, since we don't need it anymore
      rm -f "/var/run/netns/${1}"
    }
    

    There are multiple “hackish” ways to do it:

    • scan kernel logs, as mentioned by Jiri (but you have to do it right after starting the container, otherwise it gets messy);
    • check the interface counters (sent/received packets/bytes) in the container, then compare with the interfaces in the host, and find the pair that matches exactly (but with sent and receive directions flipped);
    • use an iptables LOG rule.

    The last option is, IMHO, the more reliable one (and the easiest to use), but it’s still very hackish. The idea is very simple:

    1. Add an iptables rule to log e.g. ICMP traffic arriving on the Docker bridge:

      sudo iptables -I INPUT -i docker0 -p icmp -j LOG

    2. Send a ping to the container you want to identify:

      IPADDR=$(docker inspect -format='{{.NetworkSettings.IPAddress}}' 0c33)

      ping -c 1 $IPADDR

    3. Check kernel logs:

      dmesg | grep $IPADDR

      You will see a line looking like this:

      […] IN=docker0 OUT= PHYSIN=vethv94jPK MAC=fe:2c:7f:2c:ab:3f:42:83:95:74:0b:8f:08:00 SRC=172.17.0.79 …

      If you want to be fancy, just extract PHYSIN=… with awk or sed.

    4. Remove the iptables logging rule (unless you want to leave it there because you will regularly ping containers to identify them).

    If you need a bullet-proof version, you can install ulogd and use the ULOG target. Instead of just writing packet headers to the kernel log, it will send them through a netlink socket, and a userland program can then process them properly.

    If anyone is still interested in this. I found this on the docker mailing list: http://permalink.gmane.org/gmane.comp.sysutils.docker.user/3182

    You can define the name of the veth yourself by passing the lxc-conf parameter “lxc.network.veth.pair”. E.g.:

    docker run -rm -i -t –lxc-conf=”lxc.network.veth.pair=foobar” ubuntu /bin/bash

    Creates a container with a veth interface named “foobar”.

    See this page for more handy lxc-conf parameters: http://manpages.ubuntu.com/manpages/precise/man5/lxc.conf.5.html

    I don’t know how to get it properly, but you use a hack: you can scan the syslog for added interfaces after you run your container:

    #!/bin/sh
    
    JOB=$(sudo docker run -d ...)
    sleep 1s
    INTERFACE=$(grep "docker0: port" /var/log/syslog | tail -n 1 |  sed -r s/^.*\(veth[^\)]+\).*$/\\1/)
    echo "job: $JOB interface: $INTERFACE"
    
    dmesg --clear
    for i in $(docker inspect $(docker ps -a -q) | grep IPAddress | cut -d\" -f4); do ping -c 1 -w 1 $i >/dev/null; done
    while read line
    do
    IPADDRESS=$(docker inspect $line | grep IPAddress | cut -d\" -f4)
    NAME=$(docker inspect $line | grep Name | cut -d/ -f2 | cut -d\" -f1)
    FOUND=$(dmesg | grep $IPADDRESS | grep -Po 'vet[A-Za-z0-9]+' | sort -u)
    echo "GEVONDEN $IPADDRESS MET NAAM : $NAME en INTERFACE: $FOUND" | grep NAAM
    done < <(docker ps -a -q)
    

    Try this script:

    get_network_mode() {
        docker inspect --format='{{.HostConfig.NetworkMode}}' "$1"
    }
    
    
    for container_id in $(docker ps -q); do
        network_mode=$(get_network_mode "${container_id}")
        # skip the containers whose network_mode is 'host' or 'none'.
        if [[ "${network_mode}" = "host" || "${network_mode}" = "none" ]]; then
            continue
        fi
    
        # if one container's network_mode is 'other container',
        # then get its root parent container's network_mode.
        while grep container <<< "${network_mode}" -q; do
            network_mode=$(get_network_mode "${network_mode/container:/}")
            # if one of its parent container's network_mode is 'host' or 'none'
            # then skip the current container.
            if [[ "${network_mode}" = "host" || "${network_mode}" = "none" ]]; then
                 continue 2
            fi
        done
    
        # get current container's 'container_id'.
        pid=$(docker inspect --format='{{.State.Pid}}' "${container_id}")
        # get the 'id' of veth device in the container.
        veth_id=$(nsenter -t "${pid}" -n ip link show eth0 |sed -nr 's/.*eth0@if([0-9]+).*/\1/p')
        # get the 'name' of veth device in the 'docker0' bridge,
        # which is the peer of veth device in the container.
        veth_name=$(ip link show |sed -nr "/^${veth_id}/s/.*(veth.*)@if.*/\1/p")
    
        echo "${container_id} => ${veth_name}"
    done
    

    Explains:

    • avoid to execute commands in container.
    • avoid to create temporary folders and files.
    • MOST importantly, avoid to get incorrect answers for containers whose NetworkMode is host, none, or container:<name|id> (share network stack with another container’s. For example: user's containers in one pod in kubernetes share the network stack with the pause pod container’s network stack)
    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.