Docker Networking : Basics
Docker Networking : Basics
Scott Lowe has done a great job introducing Docker on his blog so I won't repeat it here. In this article, I am trying to put together my understanding of Docker networking. I am creating Docker containers in an Ubuntu 14.04 based virtual machine. Let's begin.
Installing Docker
Although Scott's post has commands to install Docker, they are specific to Ubuntu 12.04 while I am running Ubuntu 14.04. So, here are the commands I used to install Docker.
# Ensure kernel version is higher than 3.8
uname -a
# Update and add dependencies
sudo apt-get update
sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
# Add Docker repository key to apt-key
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
# Add Docker repository to apt source list
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
# Update and install Docker
sudo apt-get update
sudo apt-get install lxc-docker
After installation, a quick sudo docker version command shows the version of docker installed for Client and Server.
amit@ubuntu:~$ sudo docker version
Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.1
Git commit (client): a8a31ef
OS/Arch (client): linux/amd64
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.1
Git commit (server): a8a31ef
amit@ubuntu:~$
Note that in this article, both Client and Server are co-located but they can be made to communicate over network.
docker0 Bridge
Once Docker daemon starts (can be checked using service docker status), Docker creates a virtual interface called docker0 and assigns an IP address from the private address range that is currently unused on the Docker host. This subnet is usually /16 and is shared between all containers on the Docker host. docker0 is a bit more than a virtual interface - it is a virtual Ethernet bridge which is created in software inside the kernel of Docker host.
Note:
Docker requires a bridge to function but it does not have to be docker0. It can be a linux bridge or even an open vswitch.
Now, every time a container is created, Docker creates two interfaces - one interface is given to the container and called eth0, and the other interface (with a unique name starting with veth) is given to the host and is bound to docker0 bridge. Inside the host kernel, the two interfaces are linked so that packets can travel between them. The container's eth0 interfaces are assigned an IP address from the private subnet and given a random MAC address (or assigned using --mac-address parameter).
With no containers created yet, the status of docker0 is as follows. The docker0 interface is assigned the IP address from the subnet 172.17/16 subnet. Notice the interfaces column has no veth interfaces bound yet.
amit@ubuntu:~$ ifconfig docker0
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
UP BROADCAST MULTICAST MTU:1500 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)
amit@ubuntu:~$ sudo brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no
Container Networking
I created and started few containers on the local Docker host with the Docker daemon listening on Unix socket (default - unix://var/run/docker.sock). Here is the link to my Github page that has the Ansible playbook and the custom module I wrote to gather networking information. Here's the output after running the playbook.
name = C4
ip_address = 172.17.0.3
prefix_len = 16
gateway = 172.17.42.1
mac_address = 02:42:ac:11:00:03
bridge = docker0
name = C3
ip_address = 172.17.0.5
prefix_len = 16
gateway = 172.17.42.1
mac_address = 02:42:ac:11:00:05
bridge = docker0
name = C2
ip_address = 172.17.0.4
prefix_len = 16
gateway = 172.17.42.1
mac_address = 02:42:ac:11:00:04
bridge = docker0
Notice that all containers' eth0 interface IP address is within the bridge's range of network addresses and the gateway is docker0 bridge's IP address. Also note the veth interfaces bound to docker0 bridge.
amit@ubuntu:~$ sudo brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no veth5e3f58c
vethd10bbd4
vethfc203cb
By default, all containers can communicate with each other and the outside world. Docker adds a default rule in iptables with an ACCEPT policy.
amit@ubuntu:~$ sudo iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
To prevent any type of communication, it is recommended that iptables rules are applied appropriately.
Further, NAT is implemented in iptables on host when Docker starts. This way containers can talk to outside world but not in other direction. This can be changed using -p or -P flag to expose any ports on the container to the outside world.
amit@ubuntu:~$ sudo iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
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
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 0.0.0.0/0
Chain DOCKER (2 references)
target prot opt source destination
Conclusion
Docker is a very easy to use and understand open platform that has the potential to be the next VMware. There are some providers that are already providing Docker containers including Google Container Engine. Docker is constantly in development so a lot of changes are expected but personally, I would like to see Clustering/HA, automation, and other features. So to get started, I will be exploring Swarm, Kubernetes and others next.