A brief overview of container networking

Networking is a critical infrastructure component of enterprise and cloud IT. Especially, as computing becomes extremely distributed, networking becomes indispensable. Typically, a Docker host comprises multiple Docker containers and hence the networking has become a crucial component for realizing composite containerized applications. Docker containers also need to interact and collaborate with local as well as remote ones to come out with distributed applications. Precisely speaking, different and distributed containers need to be publicly found, network-accessible, and composable to bring forth business-centric and process-aware applications.

One of the key strengths of the Docker containerization paradigm is the ability to network seamlessly without much effort from the user. The earlier version of Docker supported just the bridge network; later, Docker acquired the SDN startup SocketPlane to add additional networking capabilities. Since then, Docker's networking capability has grown leaps and bounds and a separate set of subcommands, namely docker network connect, docker network create, docker network disconnect, docker network inspect, docker network ls, and docker network rm, were introduced to handle the nitty-gritty of the Docker networking. By default, during installation, the Docker Engine creates three networks for you, which you can list using the docker network ls subcommand, as shown here:

As you can see in the preceding screenshot, during the Docker setup, the Docker Engine creates the bridge, host, and none (null) networks. When Docker spins up a new container, by default, it creates a network stack for the container and attaches to the default bridge network. However, optionally, you could attach the container to the host or none network or the user-defined network using the --net option of the docker run subcommand. If you choose the host network, the container gets attached to the host network stack and shares the host's IP addresses and ports. The none network mode creates a network stack with just the Loopback (lo) interface. We can confirm this using the docker run --rm --net=none busybox ip addr command, as shown here:

Evidently, as you can see in the preceding screenshot, the container has got just a Loopback interface. Since this container has got just a Loopback interface, the container cannot communicate with other containers or the external world.

The bridge network is the default network interface that Docker Engine assigns to a container if the network is not configured using the --net option of the docker run subcommand. To have a better understanding of the bridge network, let's begin by inspecting it using the docker network inspect subcommand, as shown here:

Here, in the preceding screenshot, we have highlighted three paramount insights. You can find the relevant description of what happens during the Docker installation process:

  • docker0: Docker creates an Ethernet bridge interface inside the Linux kernel with the docker0 name on the Docker host. This interface is used as a bridge to pass the Ethernet frames between containers and also between containers and an external network.
  • Subnet: Docker also selects a private IP subnet from the address range of 172.17.0.0 to 172.17.255.255 and keeps it revered for its containers. In the preceding screenshot, Docker has selected the 172.17.0.0/16 subnet for the containers.
  • Gateway: The docker0 interface is the gateway for the bridge network and Docker, from the IP subnet range selected earlier, assigns an IP address to docker0. Here, in the preceding example, 172.17.0.1 is assigned to the gateway.

We can cross-check the gateway address by listing the docker0 interface using the ip addr show Linux command:

$ ip addr show docker0

The third line of the output shows the assigned IP address and its network prefix:

inet 172.17.0.1/16 scope global docker0 

Apparently, from the preceding text, 172.17.0.1 is the IP address assigned to docker0, the Ethernet bridge interface, which is also listed as the gateway address in the output of the docker network inspect bridge command.

Now that we have a clear understanding of the bridge creation and the subnet/gateway address selection process, let's explore the container networking in the bridge mode a bit more in detail. In the bridge network mode, the Docker Engine creates a network stack with a Loopback (lo) interface and an Ethernet (eth0) interface during the launch of the container. We can quickly examine this by running the docker run --rm busybox ip addr command:

Evidently, the preceding output of the ip addr command shows that the Docker Engine has created a network stack for the container with two network interfaces, which are as follows:

  • The first interface is the lo (Loopback) interface, for which the Docker Engine assigned the 127.0.0.1 Loopback address. The Loopback interface is used for local communication within a container.
  • The second interface is an eth0 (Ethernet) interface, for which the Docker Engine assigned the 172.17.0.3 IP address. Obviously, this address also falls within the same IP address range of the docker0 Ethernet bridge interface. Besides, the address assigned to the eth0 interface is used for intra-container communication and host-to-container communication.
The ip addr and/or ifconfig commands are not supported by all Docker images, including ubuntu:14.04 and ubuntu:16.04. The docker inspect subcommand is the reliable way to find the IP address of the container.

Earlier, we mentioned that docker0, the Ethernet bridge interface, acts as a conduit to pass the Ethernet frames between containers and also between containers and the external world. However, we have not yet clarified how the containers connect with the docker0 bridge. The following diagram unravels some of the mystery around this connection:

As depicted here, the container's eth0 interface is connected to the docker0 bridge using veth. The eth0 and veth interfaces belong to a special type of Linux network interface called a Virtual Ethernet (veth) Interface. The veth interface always comes in a pair, and they are like a water pipe wherein the data send from one veth interface will come out of the other interface and vice versa. The Docker Engine assigns one of the veth interfaces to the container with the eth0 name and assigns the container IP address to that interface. The other veth interface of the pair is bound to the docker0 bridge interface. This ensures the seamless flow of data between the Docker host and the containers.

Docker assigns private IP addresses to the container, which is not reachable from outside of the Docker host. However, the container IP address comes in handy for debugging within the Docker host. As we noted earlier, many Docker images do not support the ip addr or ifconfig commands, besides we may not directly have access to the container prompt to run any of these commands. Fortunately, Docker provides a docker inspect subcommand, which is as handy as a Swiss Army knife, to dive deep into the low-level details of the Docker container or image. The docker inspect subcommand reports quite a lot of details including the IP address and the gateway address. For the practical purpose, here you can either select a running container or temporarily launch a container, as follows:

$ sudo docker run -itd ubuntu:16.04    

Here, let's assume the container ID is 4b0b567b6019 and run the docker inspect subcommand, as shown here:

$ sudo docker inspect 4b0b567b6019

This command generates quite a lot of information about the container. Here, we show some excerpts of the container's network configuration from the output of the docker inspect subcommand:

"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "ID removed for readability",
"EndpointID": "ID removed for readability",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:03"
}
}

Here are the details of some of the important fields in the network configuration:

  • Gateway: This is the gateway address of the container, which is the address of the bridge interface as well
  • IPAddress: This is the IP address assigned to the container
  • IPPrefixLen: This is the IP prefix length, another way of representing the subnet mask

Without doubt, the docker inspect subcommand is quite convenient to find the minute details of a container or an image. However, it's a tiresome job to go through the intimidating details and to find the right information that we are keenly looking for. Perhaps, you can narrow it down to the right information, using the grep command. Alternatively, even better, the docker inspect subcommand helps you pick the right field from the JSON array using the --format option of the docker inspect subcommand.

Notably, in the following example, we use the --format option of the docker inspect subcommand to retrieve just the IP address of the container. The IP address is accessible through the .NetworkSettings.IPAddress field of the JSON array:

$ sudo docker inspect 
--format='{{.NetworkSettings.IPAddress}}' 4b0b567b6019
172.17.0.3

In addition to the none, host, and bridge networking modes, Docker also supports the overlay, macvlan, and ipvlan network modes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset