Understanding Docker Networking – Part-I

Estimated Reading Time: 6 minutes

This is a tutorial series for understanding how Docker Networking really works. I have tried to put it in very simple language so that laymen can understand how Docker networking is different from traditional bare metal OR virtual networking. I have put it through Q&A which are usually been asked or raised during the various meetups, seminars , webinars and presentations. Hope it is helpful for all Docker beginners. Here we go –

Que: How does Docker networking look like?

Dock_Net1

Que: Where does the 172.17.42.x come from?

It randomly chooses an address and subnet from the private range defined by RFC 1918 that are not in use on the host machine, and assigns it to docker0. By default it chooses a 16-bit netmask providing 65,534 addresses for the host machine and its containers. The MAC address is generated using the IP address allocated to the container to avoid ARP collisions, using a range from 02:42:ac:11:00:00 to 02:42:ac:11:ff:ff.

Que: How does ifconfig look like?

Every time Docker creates a container, it creates a pair of “peer” interfaces that are
like opposite ends of a pipe — a packet sent on one will be received on the other. It
gives one of the peers to the container to become its eth0 interface and keeps the other
peer, with a unique name like vethAQI2QT, out in the namespace of the host machine. By
binding every veth* interface to the docker0 bridge, Docker creates a virtual subnet shared between the host machine and every Docker container.

Que: How does traditional Docker Host network look like before Docker is installed?

Dock_Net2

Que: How does Docker Host network configuration look like after Docker is installed?

Dock_Net3

Que: How does Docker Host network configuration look like after Docker container is created?

Dock_Net5

Que: How can I see bridge details sitting on the Docker Host?

Let’s install bridge-utils utility to see how does it look like:

1. Install bridge-utils package:

root@dell-virtual-machine:~# apt-get install bridge-utils
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following NEW packages will be installed:
bridge-utils
0 upgraded, 1 newly installed, 0 to remove and 152 not upgraded.
Need to get 29.2 kB of archives.
After this operation, 146 kB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu/ trusty/main bridge-utils amd64 1.5-6ubuntu2

[29.2 kB]
Fetched 29.2 kB in 0s (31.0 kB/s)
Selecting previously unselected package bridge-utils.
(Reading database … 195531 files and directories currently installed.)
Preparing to unpack …/bridge-utils_1.5-6ubuntu2_amd64.deb …
Unpacking bridge-utils (1.5-6ubuntu2) …
Processing triggers for man-db (2.6.7.1-1ubuntu1) …
Setting up bridge-utils (1.5-6ubuntu2) …
root@dell-virtual-machine:~#

Showing brctl output:

root@dell-virtual-machine:~# brctl show docker0
bridge name     bridge id               STP enabled     interfaces
docker0         8000.56847afe9799       no              veth5247
root@dell-virtual-machine:~#

Showing ifconfig:

docker0   Link encap:Ethernet  HWaddr 56:84:7a:fe:97:99
inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:43473 errors:0 dropped:0 overruns:0 frame:0
TX packets:97379 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2327602 (2.3 MB)  TX bytes:189338797 (189.3 MB)

veth5247  Link encap:Ethernet  HWaddr d6:22:ba:f9:03:37
inet6 addr: fe80::d422:baff:fef9:337/64 Scope:Link
UP BROADCAST RUNNING  MTU:1500  Metric:1
RX packets:43073 errors:0 dropped:0 overruns:0 frame:0
TX packets:97352 errors:0 dropped:1 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2904552 (2.9 MB)  TX bytes:189334263 (189.3 MB)

Checking Iptables:

Let’s go inside the running container and check the ipaddress entry:

Verify the running container:

root@dell-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS

PORTS               NAMES
cdecbc0a80ef        dc29bb81b6b8        /bin/bash           26 hours ago        Up 26

hours                             stoic_lumiere

Checking the container networking config:

root@cdecbc0a80ef:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
60: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen

1000
link/ether aa:7a:fc:28:67:cf brd ff:ff:ff:ff:ff:ff
inet 172.17.0.30/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::a87a:fcff:fe28:67cf/64 scope link
valid_lft forever preferred_lft forever
root@cdecbc0a80ef:/#

Que: How shall I confirm that all the network traffic flows through Docker bridge?

If I traceroute to other host machine from this container , it will flow through docker0
bridge as shown below:

root@cdecbc0a80ef:/# traceroute 10.94.214.207
traceroute to 10.94.214.207 (10.94.214.207), 30 hops max, 60 byte packets
1  172.17.42.1 (172.17.42.1)  0.202 ms  7.754 ms  5.453 ms
2  10.94.214.207 (10.94.214.207)  0.536 ms  0.815 ms  0.534 ms

If we try to check iptables entry:

root@dell-virtual-machine:~# iptables -t nat -L -n|grep MAS
MASQUERADE  all  —  172.17.0.0/16       !172.17.0.0/16
MASQUERADE  all  —  0.0.0.0/0            0.0.0.0/0
root@dell-virtual-machine:~#

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  —  172.17.0.0/16       !172.17.0.0/16
POSTROUTING_direct  all  —  0.0.0.0/0            0.0.0.0/0
POSTROUTING_ZONES_SOURCE  all  —  0.0.0.0/0            0.0.0.0/0
POSTROUTING_ZONES  all  —  0.0.0.0/0            0.0.0.0/0

Que: Can you showcase any example which shows how iptables entry changes while we add new containers?

Let’s install httpd container:

root@dell-virtual-machine:~# docker run -itd -P httpd
Unable to find image ‘httpd’ locally
Pulling repository httpd
924d2d66a3b5: Download complete
575489a51992: Download complete
6845b83c79fb: Download complete
4f64efbea1d3: Download complete
08101e1b920e: Download complete
932fa81787bc: Download complete
b5bbe0bc4a47: Download complete
07239fa805ff: Download complete
17c09b5e274d: Download complete
6ffd7cced2c0: Download complete
b14dd1447073: Download complete
b8d3a847be50: Download complete
f66c1d4454c0: Download complete
5c6d62f9d593: Download complete
3f09f511bbedb5984ff3053e5f50715eb9bd17a2be2e29756012720b7b3f5598
root@dell-virtual-machine:~#

lets check the docker history:
root@dell-virtual-machine:~# docker history httpd
IMAGE               CREATED             CREATED BY

SIZE
924d2d66a3b5        8 days ago          /bin/sh -c #(nop) CMD [“httpd-foreground”]      0

B
5c6d62f9d593        8 days ago          /bin/sh -c #(nop)                  0 B
f66c1d4454c0        8 days ago          /bin/sh -c #(nop) COPY file:f465a45ed4146a281

135 B
b8d3a847be50        8 days ago          /bin/sh -c buildDeps=’

ca-certificates                         cu                  31.18 MB
b14dd1447073        8 days ago          /bin/sh -c #(nop) ENV HTTPD_BZ2_URL=https://w   0

B
6ffd7cced2c0        8 days ago          /bin/sh -c #(nop) ENV HTTPD_VERSION=2.4.17      0

B
17c09b5e274d        8 days ago          /bin/sh -c gpg –keyserver ha.pool.sks-keyser

145.9 kB
07239fa805ff        8 days ago          /bin/sh -c apt-get update

&& apt-get install   5.506 MB
b5bbe0bc4a47        8 days ago          /bin/sh -c #(nop) WORKDIR /usr/local/apache2    0

B
932fa81787bc        8 days ago          /bin/sh -c mkdir -p “$HTTPD_PREFIX”

&& chown            0 B
08101e1b920e        8 days ago          /bin/sh -c #(nop) ENV PATH=/usr/local/sbin:/u   0

B
4f64efbea1d3        8 days ago          /bin/sh -c #(nop) ENV HTTPD_PREFIX=/usr/local   0

B
6845b83c79fb        9 days ago          /bin/sh -c #(nop) CMD [“/bin/bash”]             0

B
575489a51992        9 days ago          /bin/sh -c #(nop) ADD file:5f0fca122586fe4ea7

125.1 MB
root@dell-virtual-machine:~#

It must be able to see EXPOSE 80/tcp entry which indicates that iptables automatically handles the NATing part.

Lets try running another container:

So far we saw that:

root@dell-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS

PORTS                   NAMES
3f09f511bbed        httpd:latest        httpd-foreground    About a minute ago   Up About

a minute   0.0.0.0:49153->80/tcp   nostalgic_brown
cdecbc0a80ef        dc29bb81b6b8        /bin/bash           26 hours ago         Up 9

minutes                                stoic_lumiere

Lets create a new container with 8080 instead of 80.

root@dell-virtual-machine:~# docker run -itd -p 8080:80 httpd
6b0ff011f85dea77e2bec937b8c39d29131ba1bed3606c530d0750d9f4daaaac
root@dell-virtual-machine:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS

PORTS                   NAMES
6b0ff011f85d        httpd:latest        httpd-foreground    3 seconds ago       Up 2

seconds        0.0.0.0:8080->80/tcp    dreamy_pasteur
3f09f511bbed        httpd:latest        httpd-foreground    2 minutes ago       Up 2

minutes        0.0.0.0:49153->80/tcp   nostalgic_brown
cdecbc0a80ef        dc29bb81b6b8        /bin/bash           26 hours ago        Up 9

minutes                                stoic_lumiere
root@dell-virtual-machine:~#

Now running iptables shows us the new entry:

root@dell-virtual-machine:~# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
PREROUTING_direct  all  —  0.0.0.0/0            0.0.0.0/0
PREROUTING_ZONES_SOURCE  all  —  0.0.0.0/0            0.0.0.0/0
PREROUTING_ZONES  all  —  0.0.0.0/0            0.0.0.0/0
DOCKER     all  —  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type

LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
OUTPUT_direct  all  —  0.0.0.0/0            0.0.0.0/0
DOCKER     all  —  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type

LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  —  172.17.0.0/16       !172.17.0.0/16
POSTROUTING_direct  all  —  0.0.0.0/0            0.0.0.0/0
POSTROUTING_ZONES_SOURCE  all  —  0.0.0.0/0            0.0.0.0/0
POSTROUTING_ZONES  all  —  0.0.0.0/0            0.0.0.0/0

Chain DOCKER (2 references)
target     prot opt source               destination
DNAT       tcp  —  0.0.0.0/0            0.0.0.0/0            tcp dpt:49153

to:172.17.0.3:80
DNAT       tcp  —  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080

to:172.17.0.4:80

Clap