Using IPv6 with Docker Compose on Ubuntu Server

I recently started using PiHole to block ads on my home network. As the name suggests, you install it on a raspberry pi. I left it in situ for about a month, until I decided I wanted to swap out the pi, but keep PiHole.

The natural solution to this, is to use a docker container. Rather helpfully, there is a publicly available docker build of PiHole. Simple, right? Well my home network is also IPv6, thus the DNS on the raspberrypi should be also. The problem is, Docker has support for IPv6, but it’s not very straightforward with Docker Compose.

After a lot of fiddling about, I finally managed it. As per the Docker IPv6 documentation, on Linux (I used Ubuntu Server) you need to add a configuration file to enable IPv6, at /etc/docker/daemon.json:

  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"

Then you need to restart Docker daemon:

$ sudo systemctl restart docker

that will allow the new daemon.json file to take effect.

After this, I had an existing setup with Plex and other things already controlled by docker-compose. The solution here is to kill all your containers and recreate the compose network by hand with IPv6 subnet:

$ cd <my_compose_dir>
$ docker network ls # name of compose network should have directory name in it
$ docker network inspect <compose_net_name> # Make note of exisiting IPv4
$ docker-compose kill # Kill all your existing containers
$ docker network prune # Remove/Prune the network (as no more containers are attached)
$ docker network create --subnet= --gateway= --ipv6 --subnet=2001:db8:2::/64 <compose_net_name>

and lastly for the piece de resistance, let’s bring up our compose containers:

$ docker-compose up -d

now we can also verify we get IPv6 working internally (see this helpful post here):

$ docker run -itd ajeetraina/ubuntu-iproute bash # Start first container
$ docker run -itd ajeetraina/centos-iproute bash # Start second container (new

In both containers you can run:

$ ifconfig eth0

which will show you the IPv6 address of each. Then from either container, you can ping the other with:

$ ping6 <ipv6_address>

and it all should work nicely!