Docker networking bridge to host NIC

This post is part of a series about Docker, including:

Today we’ll see Docker networking with a very specific target in mind: bridge container to the host network.

This isn’t supposed to be the way of work of containers: a container should be created to run a single application so container networking, from the point of view of a Network Engineer, is essentialy a Port Address Translation with a firewall exception.

I know that’s a strong simplification, you cand find lot of good explanation about Docker networking on Slideshare.

Different methods to connect a Docker container to the network can be found HERE.

Docker Networking

When you install Docker on a Linux host in creates a new interface called docker0.

Every container’s eth0 interface is connected to an internal “host-only” interface that could be accessed via the PAT/Firewall exception mentioned before.

root@1d622f185fe4:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:03  
      inet addr:172.17.0.3  Bcast:0.0.0.0  Mask:255.255.0.0
      inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link
      UP BROADCAST RUNNING  MTU:1500  Metric:1
      RX packets:31567 errors:0 dropped:0 overruns:0 frame:0
      TX packets:19482 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0 
      RX bytes:49245829 (49.2 MB)  TX bytes:1366148 (1.3 MB)

Note: the Ubuntu image hasn’t ifconfig installed, install it executing:

apt-get install net-tools

Bridging

On the Docker documentation about bridging the suggested method is to use Linux bridge.

A better method is show below.

Open vSwitch and Pipework

Open vSwitch (shortened OVS) is an open source multilayer software switch that support many well-known features, including bridging.

Let’s see how it can be used with Docker to bridge a container to the local network.

Install Open vSwitch on host:

apt-get install openvswitch-switch openvswitch-common

Verify OVS is correctly installed:

root@ubuntusrv:~# ovs-vsctl show
f9018860-275f-49e5-a6a8-5d9baf2df7b7
ovs_version: "2.3.1"

Create a bridge interface and add host’s eth0 to the bridge:

ovs-vsctl add-br ovsbr0; ovs-vsctl add-port ovsbr0 eth0; dhclient ovsbr0; service networking restart

Note: network connection to the host may be lost. In my case I was connected remotely via SSH to the host and executing all the commands in a single line the connection wasn’t lost.

Note2: to delete the previous configuration run

ovs-vsctl del-port eth0; ovs-vsctl del-br ovsbr0; service networking restart

This is the final configuration of the Open vSwitch:

ovs-vsctl show

Bridge "ovsbr0"
    Port "eth0"
        Interface "eth0"
    Port "ovsbr0"
        Interface "ovsbr0"
            type: internal
ovs_version: "2.3.1"

The OVS named ovsbr0 now has just two ports, one external eth0 and one internal ovsbr0.

Now we just need to create the Docker containers with an interface bridged to the internal vSwitch interface ovsbr0. To do that Pipework helps a lot.

Install pipework

Pipework is a script that can automate many Docker and OVS configurations, check documentation for details.

To install Pipework on the host machine run:

git clone https://github.com/jpetazzo/pipework.git

In our case we want to start a container with a bridged interface and assign it an IP address from a DHCP server in the same subnet of the host.

This is the command to run:

./pipework/pipework ovsbr0 $(docker run -i -t --net="none" -d ubuntuplus /bin/bash) dhcp

Now attach to the container and verify the network interface configuration:

root@b30fcf44858f:/# ifconfig
eth1  Link encap:Ethernet  HWaddr 3a:05:56:81:f4:eb  
      inet addr:10.1.0.18  Bcast:10.1.0.255  Mask:255.255.255.0
      inet6 addr: fe80::3805:56ff:fe81:f4eb/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:221 errors:0 dropped:0 overruns:0 frame:0
      TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000 
      RX bytes:19161 (19.1 KB)  TX bytes:1674 (1.6 KB)

Great! 10.1.0.0/24 is my network. Verify on the DHCP server (a Cisco router)

sh ip dhcp binding 10.1.0.18
IP address          Client-ID/              Lease expiration        Type
                Hardware address/
                User name
10.1.0.18           3a05.5681.f4eb          May 13 2015 02:26 PM    Automatic

Notice in the DHCP output the real MAC address of the container.

This is the configuration of the OVS

ovs-vsctl show

Bridge "ovsbr0"
    Port "eth0"
        Interface "eth0"
    Port "veth1pl13142"
        Interface "veth1pl13142"
    Port "ovsbr0"
        Interface "ovsbr0"
            type: internal
ovs_version: "2.3.1"

Notice the new port veth1pl13142 associtated to the running container.

Stay tuned for the next post of the Docker series where I’ll join the dots to show you my final goal, the actual reason I’ve started to use Docker.

A few notes.

Cleaning OVS

When the container is killed the OVS port isn’t removed. After some time the OVS could have many unused ports. To clean the ports I wrote this simple scripts:

ovs-vsctl show | grep Interface.*veth | sed 's/"//g' | awk '{ cmd= "ovs-vsctl del-port "$2 ; system(cmd) }'

Container to OVS port map

I still haven’t found a working script to map an OVS port to a container but THIS looks like a good start. Any help would be appreciated.

That’s it

 
comments powered by Disqus