Docker default networks
July 15, 2023 -My home network uses IPv4 and IPv6 ranges. Several machines run docker and all have default ranges, which of course overlap. I can setup docker networks with fixed IP ranges, but for one case that does not solve everything since it creates ad-hoc networks.
My setup
For CI/CD I use a Drone CI docker runner for some workloads. For each build step, it spawns a new docker container, so it's quite powerful and flexible. This is a tradeoff against requiring access to the docker socket to manage docker containers.
It is a security issue to give docker containers access to the docker socket, so to mitigate that slightly, I run a VM only to run docker for drone runner.
So I have a machine (apollo)1, which runs drone CI and other services in docker containers. Then I have another machine
(heracles) where I run the drone runner. Both machines use the same subnet (192.168.1.0/24). On apollo I run
docker containers and on orion I run a virsh VM which runs Docker inside. Docker by default recycles the same subnets
(in this case 172.16.0.0/12 in blocks of /16). I have created non-overlapping docker networks on apollo and orion,
so they are stable even between reboots. The VM itself needs their own subnet as well and that is again non-overlapping:
192.168.100.0/24.
Diagram 1 shows this convoluted network setup.
,--[apollo]--------------. ,---[heracles]-----------.
| 192.168.1.1/24 | | 192.168.1.2/24 |
| runs docker | | runs virsh/qemu VM |
| | | |
|,-[various]------------.| |,--[orion]-------------.|
|| 172.16.0.0/16 || || 192.168.100.0/24 ||
|| docker containers <++--. || runs docker ||
|| || | || ||
|`----------------------'| | ||,-[drone runner]-----.||
`-----------------------' | ||| 172.17.0.0/16 |||
| ||| docker container |||
| ||| |||
| ||+-[runner steps]-----+||
| ||| 172.16.0.0/12(!) |||
`--+++> docker containers |||
||`--------------------'||
|`----------------------'|
`------------------------'
The problem
As you can see in the above diagram, the part I did not talk about yet is whenever the drone runner spawns a new
instance for a build job. It will assign a separate network to this instance from the pool of 172.16.0.0/12, which
of course overlaps with the docker network on apollo (172.16.0.0/16), hence the (!) mark there.
I was aware of the /etc/docker/daemon.json configuration bip that configures a network range for docker:
{
"bip": "172.18.0.1/16"
}
Sadly, that only works for the default docker network and not for non-default networks.
A solution
I recently became aware of an option called default-address-pools, which does exactly what I needed; it creates
a pool of subnets (in this case: 10.1.0./16) out of which it takes smaller subnets (in this case, /24) to
assign to ad-hoc networks.
{
"bip": "172.18.0.1/16",
"default-address-pools": [
{"base": "10.1.0.0/16", "size": 24}
]
}
Diagram 2 shows non-overlapping subnets, even with dynamic drone runner instances.
,--[apollo]--------------. ,---[heracles]-----------.
| 192.168.1.1/24 | | 192.168.1.2/24 |
| runs docker | | runs virsh/qemu VM |
| | | |
|,-[various]------------.| |,--[orion]-------------.|
|| 172.16.0.0/16 || || 192.168.100.0/24 ||
|| docker containers <++--. || runs docker ||
|| || | || ||
|`----------------------'| | ||,-[drone runner]-----.||
`-----------------------' | ||| 172.17.0.0/16 |||
| ||| docker container |||
| ||| |||
| ||+-[runner steps]-----+||
| ||| 10.1.X.0/24 |||
`--+++> docker containers |||
||`--------------------'||
|`----------------------'|
`-----------------------'
Alternate solutions
There are other solutions possible, that I did not look into:
- Using a range outside
172.16.0.0/12for my fixed docker subnets. - Only using IPv6 for these as they do not need to be reached from the outside.
The downside of using other IPv4 ranges is obviously that I need to re-number/re-route everything, so I did not feel like it at this time.
The downside of only using IPv6 is that not all services support that, so I have to have IPv4 networks as well anyway. Part of my containers can be IPv6-only though, it is something I'm considering.
Host names and ip address ranges are made up to simplify this example.