Understanding Docker Networking Part II

February 6, 2020

Table of Contents

1. Overview

2. Standalone Docker Networking

          2.1 Default Bridge Network

3. User-defined Bridge Networks

          3.1 The Host Network

          3.2 Macvlan Network

          3.3 None

4. Distributed Networking

          4.1 Overlay Networks

          4.2 Ingress

5. Docker Network Plugins

1. Overview

Docker can be used in various use cases: the standalone mode, using Docker Compose, in a single host, or by deploying containers and connecting Docker engines across multiple hosts. The user can use Docker containers with the default network, the host network, or other types of more advanced networks like overlays. This depends on the use case and/or the adopted technologies.

In this tutorial, we are going to understand the different types of container networking. We are also going to study containers networking. We will see different types of networking, and finally, we will understand how to extend Docker networking using plugins. This article is the second part of a series. For part I, check out this article. We also have resources on Kubernetes Networking and monitoring Docker containers with cAdvisor, for some great further reading.

2. Standalone Docker Networking

2.1 Default Bridge Network

After a fresh Docker installation, you can find a default bridge network up and running.

We can see it by typing docker network ls:

<p>CODE:https://gist.github.com/denshirenji/d61a3ad0499e50565f5a2f838e0a69b4.js</p>

If you use ifconfig command, you will also notice that this network interface is called "docker0":

<p>CODE:https://gist.github.com/denshirenji/2069f70f0e0045b91dff0236a285b835.js</p>

All Docker installations have this network. If you run a container, say, Nginx, it will be attached by default to the bridge network:

docker run -dit --name nginx nginx:latest

You can check the containers running inside a network, by using the "inspect" command:

<p>CODE:https://gist.github.com/denshirenji/4e29da1735dd8e5f241cd232e1c8cf55.js</p>

Docker uses a software-based bridge network which allows containers connected to the same bridge network to communicate while isolating them from other containers not running in the same bridge network.

Let's see how containers running in the same bridge network can connect to each other. Let's create two containers for testing purposes:

<p>CODE:https://gist.github.com/denshirenji/effef368a2f9c75388914f504d11b488.js</p>

These are the IP addresses of our containers:

<p>CODE:https://gist.github.com/denshirenji/92e535d127d380bc9152b13063721a1b.js</p>

Let's try to ping a container from another one using one of these IP addresses. For example, ping the container named "busybox1" from "busybox2", using its IP 172.17.0.3.

<p>CODE:https://gist.github.com/denshirenji/1fe3504920dc23359e095039bd18effb.js</p>

So, containers on the same bridge can see each other using their IPs. What if I want to use the containers' name instead of the IP.

<p>CODE:https://gist.github.com/denshirenji/a60c9629afe52ab8febed47e351cd5f2.js</p>

We can understand that containers running on the same bridge network are able to see each other using their IP addresses. On the other hand, the default bridge network does not support automatic service discovery.

3. User-defined Bridge Networks

Using the Docker CLI, it is possible to create other networks. You can create a second bridge network using:

docker network create my_bridge --driver bridge

Now, attach "busybox1" and "busybox2" to the same network:

<p>CODE:https://gist.github.com/denshirenji/132a8f6bd3596e722382eb478aa2030a.js</p>

Retry pinging "busybox1" using its name:

<p>CODE:https://gist.github.com/denshirenji/2a3b0a8e860bab52016e39dd39f41eb2.js</p>

We can conclude that only user-defined bridge networks support automatic service discovery. If you need to use service discovery with containers, don't use the default bridge, create a new one.

3.1 The Host Network

A container running in the host network matches the networking configurations of the host.

If we take the example of an Nginx image, we can notice that it exposes the port 80.

EXPOSE 80

If we run the container, we should normally publish the port 80 on another port, say 8080.

docker run -dit -p 8080:80 nginx:latest

The container is now accessible on port 8080:

<p>CODE:https://gist.github.com/denshirenji/795447b468c244ae0eaafd027ab1f9e9.js</p>

When we run the same container on the host network, published ports will be ignored since the port 80 of the host will be used in all cases. If you run:

docker run -dit --name nginx_host --network host -p 8080:80 nginx:latest

Docker will show a warning:

WARNING: Published ports are discarded when using host network mode

Let's remove this container and re-run it without publishing its ports:

<p>CODE:https://gist.github.com/denshirenji/2bc1f53afec698ae0a6cb4dd9b566387.js</p>

You can now run a "curl" on the port 80 of the host machine to check that the web server responds:

<p>CODE:https://gist.github.com/denshirenji/a77f32b9a41ba881e0b9bcf9e3790e00.js</p>

Since there is no network address translation (NAT), running a container on the host network can optimize performance. When you run a container on the host network, its network will not be isolated from the host, and it will not get its own IP; these are the limits of this type of network.

3.2 Macvlan Network

If you are, for instance, developing an application to monitor traffic, which is expected to be directly connected to the underlying physical network, you can use the macvlan network driver. This driver assigns a MAC address to each container's virtual network interface.

Example:

<p>CODE:https://gist.github.com/denshirenji/5452161adb4acee15c87928913986506.js</p>

When you create a macvlan network, you need to specify the parent, which is the used host interface through which the traffic is physically routed.

3.3 None

In some cases, you need to isolate a container even from ingoing/outgoing traffic, you can use this type of network that lacks a network interface.

The only interface the container will have is the local loopback interface (127.0.0.1).

4. Distributed Networking

4.1 Overlay Networks

Your container platform may have different hosts, and in each there are some containers running. These containers may need to communicate with each other. This is when overlay networks are useful.

The overlay network is a distributed network created among multiple Docker daemons in different hosts. All containers connected to this network can communicate.

4.2 Ingress

Docker Swarm, for example, uses overlay networking to handle the traffic between swarm services.

In order to test this, let's create 3 Docker Machines (a manager + 2 workers):

<p>CODE:https://gist.github.com/denshirenji/6122ed2e5ed59949aa66713fd3b7b818.js</p>

After configuring a different shell for each of these machines (using eval $(docker-machine env <machine_name>), you initialize Swarm on the manager, using the following command:

docker swarm init --advertise-addr <IP_address>

Don't forget to execute the join command on both workers:

docker swarm join --token xxxx <IP_address>:2377

If you list the networks on each host using docker network ls, you will notice the existence of an overlay ingress network:

o5dnttidp8yq   ingress      overlay      swarm

On the manager, create a new service with three replicas:

<p>CODE:https://gist.github.com/denshirenji/1ec66230b391bd358e3efbf349aca0a9.js</p>

To see the swarm nodes where your service has been deployed, use docker service ps nginx.

<p>CODE:https://gist.github.com/denshirenji/ba0af97ca3a42b6d9df59cb0d833623e.js</p>

In my case, I have a container running in each of my nodes.

If you inspect the ingress networking using docker inspect ingress, you will be able to see the list of peers (swam nodes) connected to the same network:

<p>CODE:https://gist.github.com/denshirenji/45a9a4abaac7e34bbf393068618d93b9.js</p>

The ingress network is a particular type of overlay network created by default.

When we create a service without connecting it to a user-defined overlay network, it connects by default to this ingress network. Using Nginx, here is an example of a service running without a user-defined overlay network but connected by default to the ingress network.

<p>CODE:https://gist.github.com/denshirenji/b8d8ead6693bff108c6613d17b49a579.js</p>

5. Docker Network Plugins

There are other types of use cases that need new types of networks. You may also want to use another technology to manage your overlay networks and VXLAN tunnels.

Docker networking is extensible and allows using plugins to extend the features provided by default.

You can use or develop networking plugins. You can also find some verified networking plugins on Docker Hub.

Each plugin has different use cases and installation procedures. For example, Weave Net is a virtual Docker network that connects containers across a cluster of hosts and enables automatic discovery.

To install it, you can follow the official instructions on the Docker Hub:

<p>CODE:https://gist.github.com/denshirenji/f52f57cb63b9692750eebd1e76d59a20.js</p>

You can create a Weave Net network and make it attachable using:

<p>CODE:https://gist.github.com/denshirenji/6c53d71c620e8f1a042a65439f40a145.js</p>

Then, create containers using the same network:

docker run -dit --rm --network=my_custom_network -p 8080:80 nginx

Part III of this series is all about Kubernetes Networking, check it out here. If you missed part I, check it out here. If you're interested in monitoring your Docker containers, learn how to do it in our article about monitoring Docker with cAdvisor. Also, check out our blog post on Monitoring Kubernetes with Prometheus.

Related Posts

GET FREE PROMETHEUS monitoring FOR 14 Days