Docker, networks, subnets and IP address pools

by | Jul 12, 2020 | Docker

Docker uses default address pools to create subnets. For most use cases, the shipped defaults fit. But sometimes they cause conflicts with existing networks or subnets. Overlapping networks may conflict with existing systems. Or a large number of docker networks exhaust the pools.

In this article, I explained how to configure your defaults. Docker uses the daemon.json file to change the docker defaults. Here, the “default-address-pools” option allows us to define a set of custom IP subnets. The “base” establishes a network, and the “size” cuts it into more pieces.

How do Docker networks work?

The IP address uses 4 bytes and splits them to a network ID and a host ID. Therefore the standard defines network ID with a length of 8, 16, or 24 bytes. As a result, we call these networks class A, B, or C networks. Furthermore, some bits of the host ID may become part of the network ID. For this reason, the network ID can use nearly any amount of bits.

 

/etc/docker/daemon.json

{
  "default-address-pools": [
     {
        "base": "172.0.0.0/16", "size": 28
     }]
}

Define Docker network pools

The file daemon.json changes the docker defaults. In effect, the section “default-address-pools” defines a set of one or more pools. In this way, a list of “base” and “size” tuples represent new network pools. So, the base is a network definition. For example, “192.168.0.0/20” defines a class C network with a network ID of 20 bits. Settings “size” to a value of 24 will extends the given network mask. In this example, the docker will use 24 bits instead of 20 bits.

Example network configuration

The example script creates a set of docker networks, dumps their definition to the terminal, and finally removes them.

test docker networks

#!/bin/bash

for i in {1..50}; do docker network create net-$i; done
for i in $(docker network ls -q); 
do 
   docker network inspect --format='{{.Name}} {{.IPAM.Config}}' $i; 
done
for i in {1..50}; do docker network rm net-$i; done

Accordingly, the example script creates a set of docker networks, dumps their definition to the terminal, and finally removes them. As a result, the script output shows a list of subnets. Because the network mask length is 28 bit long, so 4 bits for host ID allows 16 different host addresses per network.

3c4a15db156cbb8fc5dcce90ec95aa7cd3ef2766e38ce4d98ee67d249c144423
9fd39f9e008552f1a4bae55adddf798b65616c997be94b621a99552210f9f47e
...
de2bf5548907f65a1e3e8a65c20fe20dd92bed1b33ad70bd658e92e938b1f34e
1c145e88918c7943fcd4e1020939517dcf92220570bf14e3ca9ba666eef7273c
bridge [{172.0.0.0/28   map[]}]
host []
net-1 [{172.0.6.80/28  172.0.6.81 map[]}]
net-2 [{172.0.6.96/28  172.0.6.97 map[]}]
net-3 [{172.0.6.112/28  172.0.6.113 map[]}]
...
net-48 [{172.0.9.64/28  172.0.9.65 map[]}]
net-49 [{172.0.9.80/28  172.0.9.81 map[]}]
net-50 [{172.0.9.96/28  172.0.9.97 map[]}]
none []
timecheck-smoketest_default [{172.18.0.0/16  172.18.0.1 map[]}]
net-1
net-2
net-3
...
net-48
net-49
net-50

Conclusion

The number of networks and host addresses per subnet are related. So more subnets mean fewer hosts per subnet and vice versa. If the subnet is defined too generously, they will quickly run out. Be careful when choosing the IP range. Overlaps with existing addresses in the network can lead to conflicts. Therefore consider the choice of address ranges, the subnets’ size, and the number of hosts to be operated individually.

https://docs.docker.com/engine/reference/commandline/dockerd/