Docker Networking Model — Introduction

HungWei Chiu
9 min readMar 28, 2023

Introduction

This article is a popular science piece that provides an overview of several basic network models for Docker Containers. It does not delve into technical details, but instead focuses on introducing the concepts and usage of these network models. By understanding these network models, one can compare their suitability for different scenarios and have a clearer understanding of the context when encountering Kubernetes in the future.

When creating a container using the docker command, the --network parameter can be used to specify the desired network model. The following network models will be introduced in terms of their concepts, architecture, and usage:

  1. None:
    This network model isolates the container from the host and all other containers, meaning the container does not have access to any network resources.
  2. Host:
    This network model shares the host’s network stack with the container, allowing the container to access all network resources available on the host.
  3. Bridge:
    This network model creates a private network between the host and the container, allowing the container to communicate with the host and other containers on the same network, but isolated from the host’s network.
  4. Container:$ID:
    This network model allows a container to share its network stack with another container, specified by its ID. This allows the two containers to communicate with each other as if they were on the same network.

None

The None option means telling the Docker Engine not to manage any network functions and just to create an isolated network namespace.

Example

$ docker run --network=none -d --name none hwchiu/netutils
$ docker exec none ifconfig -a
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

In our example, we can see that by default, there is only one lo (loopback) interface, and there are no other network interfaces. Therefore, this container does not have the ability to access the internet.

Networking/System View

This section uses two different perspectives to view the behavior. Since this article will interpret different network models using the same concepts, the concepts of the two perspectives will be introduced in detail.

Left Image:
This introduces the network from a system-level perspective. The gray line in the middle divides it into the upper part of UserSpace and the lower part of Kernel Space.

In this example, different color changes in the kernel space represent different network namespace, and each network namespace is isolated from each other.

Right Image:
This provides a more concise introduction and mainly observes the network from the user’s perspective, explaining what changes in the relationship between network components from the example.

After understanding the above concepts, let’s take a look at how to understand this picture:

Left Image:

When a new Container is created, the system will create a new network namespace (yellow block) in the Kernel to achieve network isolation. However, since we did not make any settings for this isolated environment, only one network interface, lo, will be in this network space.

The light blue part represents the original system network namespace and assumes that the default network interface eth0 already exists.

Right Image:

A new Container is generated in the system, but this Container has no interaction with the native host, and the network relationship is irrelevant.

scenario

This mode of creating a clean network is suitable for people who want to develop network models, study the Docker network, and develop CNI. They can start by creating a clean network and then find ways to make it accessible to the internet.

Host

The meaning of the Host option in the --network parameter is to tell Docker not to create a network namespace for the container and that it should share the same network model as the host. The shared content includes network interfaces, routing tables, iptables, conntrack, etc.

Example

$ docker run --network=host -d --name host hwchiu/netutils
$ docker exec -it host ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 0e:e5:e9:25:d8:41 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:71:98:4c:2a brd ff:ff:ff:ff:ff:ff

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 0e:e5:e9:25:d8:41 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:71:98:4c:2a brd ff:ff:ff:ff:ff:ff

By creating a container with the Host option, it can be seen that the network interface information seen inside the container is exactly the same as that of the host machine. Besides using the ip link command, other commands such as ip addr, ifconfig, iptables-save, ipvsadm, etc. will show the same information.

The network ports are also shared, so if a service is already using port 80 on the host machine, you cannot run another service on port 80 in the container.

Networking/System View

Left Image:
When creating a new container, we do not need any network isolation functionality, so no new network namespace is created in the Kernel. Our container will directly use all network resources in the default network namespace, such as network interface eth0.

Right Image:
A new container was generated in the system and this container shares the network namespace with the host, so the network environment seen by the container is exactly the same as the host.

scenario

  • Direct access to the Container without interference from other paths
    . Pay attention to the use of Port Numbers, as conflicts easily arise when enabling the same service
  • When the container needs to use special hardware resources but mounting them to the container is relatively complicated, we use this method to share the host’s resources c
  • When the container itself needs to perform operations or monitoring on the host’s network environment d.
  • When Kubernetes Pod has a special setting of hostNetwork=true

Bridge

The meaning of the “Bridge” parameter is to tell Docker to create a new network namespace for me, and I want to have the ability to interact with the native network through the Linux Bridge.

This part ignores any iptables rules for now.

This model is also the default network model in Docker, and it will perform the following steps for you:

Create a network interface within the container and assign related IP addresses. Create a Linux Bridge on the host. Connect the container and the host through veth, linking the two different network namespaces.

Veth is a complex concept, but for now, just know that it is a special way to connect different network namespaces.

Example

The following commands are more complicated. First, we create a container using the bridge model.

Then we can observe that there are two network interfaces in the container through the ip addr command, namely lo and eth0. Here, we need to pay attention to the number 183 after eth0. This number is related to the concept of veth, but let me skip it for now.

Next, we call ip link on the host side and search with 183, and we find that there is a network interface related to 183 in the system.

Finally, we can use the brctl tool to find that there is a Linux Bridge called docker0 in the system, and the veth interface we just found is bound to this docker0.

$ docker run --network=bridge -d --name bridge hwchiu/netutils

$ docker exec bridge ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
182: eth0@if183: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
$ ip link | grep 183
183: veth980af09@if182: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default

$ brctl show | grep veth980af09
docker0 8000.024271984c2a no veth980af09

Networking/System View

Left Image:
This architecture is more complex and can be divided into several aspects:

  1. When the container is created, a new network interface eth0 is created within its own network space (yellow block), so there will be two network interface in the network space, lo and eth0.
  2. In the default network namespace of the host machine (light blue block), a new Linux Bridge, docker0, will be created, and eth0 in the Container will be connected to it through the veth mechanism.

Right Image: In addition to producing the Container, the system will also produce a new Linux Bridge and connect the Linux Bridge and Container through the veth mechanism.

If we create another new Container (pink block) at this time, the result will be as follows:

  1. The new Container creates a new network namespace (green block) and sets up the network interface.
  2. Because there is already a docker0 available in the system, Docker will not create a new Bridge to bridge the Container.
  3. Connect the new network namespace (green block) to the host network namespace (light blue block) through veth.
  4. From the right picture, there are more and more veth network interface in the system, which actually connect to different Containers.

scenario

  1. The default network model of Docker allows access to the internet. Cooperation with iptables is required to access the internet, but this article will skip the part about iptables.
  2. Containers can communicate with each other through IPs. There are no requirements for the network, as long as one node can communicate with the other, it’s fine.
  3. This mode is used by some CNI to provide basic network connectivity, even without Linux Bridge and Veth, it is widely used.

Container

The meaning of the parameter “Container:$ID” is to tell Docker not to create a new network namespace for me, but instead, use the existing network namespace of the specified Container and share the same network environment. Therefore, both containers will see the same network interfaces, routing tables, and other network-related information.

Example

$ docker run --network=container:$(docker ps --filter name=bridge -q) -d --name co_container hwchiu/netutils

$ docker exec co_container ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 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:1366 (1.3 KB) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

$ docker exec bridge ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 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:1366 (1.3 KB) TX bytes:0 (0.0 B)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

Networking/System View

Left Image:
This architecture is more complex, and can be seen from several angles:

  • The original container (light blue) is created using the Bridge mode, so the system will generate all the resources used by the bridge environment.
  • Then, the new container (pink) is created using the shared network mode, the new container is mounted in the network space of the blue container, so there will be no new network namespace, it will share the network space of the blue container (yellow area), including eth0, lo, etc.

Right Image:
After generating the Container in the system, it will directly share the network space with the target Container, so you will see that these two Containers share the same network card eth0.

scenario

  1. The containers in the same network namespace can access each other’s services through localhost, because they share the lo interface.
  2. Different containers that have access needs can enjoy faster network access speeds through this mode.
  3. Kubernetes Pods are implemented based on this model, so multiple Containers can exist within a Kubernetes Pod and can access each other’s services through localhost.
    Kubernetes starts a container called Pause and shares the network with all user-defined containers.

Summary

In this article, we introduced the basic models of Docker without diving into too many technical details. By understanding the differences between these network environments, we also compared each environment’s use cases, providing a better understanding of these network models.

These virtual network environments are actually always around us, and understanding the differences between these network architectures can also help us think about the architecture of the entire system.

--

--