Adding a new NIC to a Docker container in a specific order

I’m trying to have a CentOS container with two network interfaces.
After going through the Docker docs and “googleing” a bit, I found this GitHub issue comment that specifies how to achieve this.

Following it, I created a new network (default type: bridge)

docker network create my-network

Inspecting the new network, I can see that Docker assigned it to the subnetwork 172.18.0.0/16 and the gateway 172.18.0.1/16.

Then, when creating the container, I specifically attach the new network:

docker create -ti --privileged --net=my-network --mac-address 08:00:AA:AA:AA:FF <imageName>

Inside the container, I can check with ifconfig that indeed the interface is present with that IP and mac address:

    eth0      Link encap:Ethernet  HWaddr 08:00:AA:AA:AA:FF  
              inet addr:172.18.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
              inet6 addr: fe80::a00:aaff:feaa:aaff/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:3 errors:0 dropped:0 overruns:0 frame:0
              TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:258 (258.0 b)  TX bytes:258 (258.0 b)
    
    lo        Link encap:Local Loopback  
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

The problem comes when I connect the container to the default Docker network (bridge0 a.k.a bridge):

docker network connect bridge <my-container>

Checking now the interfaces in the container:

    eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
              inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
              inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:17 errors:0 dropped:0 overruns:0 frame:0
              TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:2941 (2.8 KiB)  TX bytes:508 (508.0 b)
    
    eth1      Link encap:Ethernet  HWaddr 08:00:AA:AA:AA:FF  
              inet addr:172.18.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
              inet6 addr: fe80::a00:aaff:feaa:aaff/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:17 errors:0 dropped:0 overruns:0 frame:0
              TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:2941 (2.8 KiB)  TX bytes:508 (508.0 b)

The interface for my new network gets moved onto eth1, meanwhile the interface for the default networks gets eth0.

Also, when checking the configuration file for the interface (/etc/sysconfig/network-scripts/ifcfg-eth0), I can see that the MAC address specified there differs from the one I manually set up when running the container (08:00:AA:AA:AA:FF):

    DEVICE="eth0"
    BOOTPROTO="dhcp"
    HWADDR="52:54:00:85:11:33"
    IPV6INIT="yes"
    IPV6_AUTOCONF="yes"
    MTU="1500"
    NM_CONTROLLED="yes"
    ONBOOT="yes"
    TYPE="Ethernet"
    UUID="25016937-1ff9-40d7-b4c3-18e08af0f98d"

In /etc/sysconfig/network-scripts there is only the configuration file for eth0. The file for eth1 (the newly added interface) is missing.

Due to the requirements of the work I’m involved, I need that the first interface has to be always disabled and its MAC address has to be specifically set.

Any other network-related work must go through the new attached NIC.

My question is:

How can I attach a new NIC to the container so eth0 will have the desired MAC address.
(Doing this at image level is also fine.)

1 Like

So… any ideas? :confused:

Thanks!

Dead adrics,

First of all, thank you for your detailed instructions, it helped me a lot when I was playing with multiple interfaces in docker.
Secondly, I don’t know whether you still wait for any response on this thread, but I summarized below what I ended up after some workarounds.

Solution 1:
Just right after your solution, if you only need a different MAC address, just change the corresponding device’s MAC address in the container by some basic tools, say, ifconfig. If you don’t have it in your container, just install net-tools package.
To change the mac use this: ifconfig eth1 hw ether 08:00:AA:AA:AA:FF

Solution 2:
Since docker is also using linux’s networking namespaces you can do this in the rock-bottom layer as well. Unfortunately, Docker tries to hide this from the user, but the namespaces are still existing under the hood. In order to get them to be managed by ip netns tool, do the following:

  1. get the process id (pid) of your running container:
    $ sudo docker inspect -f '{{.State.Pid}}' <container name>
    is not your label:tag name, it is the name that docker automatically assign to it once a container is fired up - get yours viadocker ps command and look for the last column (NAME).
  2. create a symlink from the /proc/ filesystem to /var/run/
    2.1. First, create a netns directory in /var/run/
    $ sudo mkdir -p /var/run/netns
    2.2. Using the PID you have just obtained, create the symlink
    $ sudo ln -sf /proc/<PID>/ns/net /var/run/netns/<YOUR DESIRED NETNS NAME FOR YOU CONTAINER>
    Now, if you execute ip netns list, you will see the networking namespace of your container.
  3. From now on, there is no docker specific stuffs, just create a veth pair, bring them up, and attach one end of it to the container and you are fine:
    $ sudo ip link add veth1_container type veth peer name veth1_root
    $ sudo ifconfig veth1_container up
    $ sudo ifconfig veth1_root up
    $ sudo ip link set veth1_container netns <YOUR NETNS NAME>
    $ sudo ip netns exec <YOUR NETNS NAME> ifconfig veth1_container up

The last command might be a bit overcomplicated, but it seemed that bringing up this interface natively in the container is not possible due to missing permissions :face_with_raised_eyebrow:

Note that the MAC address could also be changed in the same way I have shown in solution 1, before attaching it to the container, or after - does not really matter, just different commands need to be used (recall the permission issue just mentioned above).

I hope it helps.
Cheers,
cs.lev