Use IPv6-enabled Docker containers 2019-07-30

IPv6 is about to start over, and it is time to server your Docker containers with IPv6 addresses. IPv6 with Docker is different in that there is no Port NAT (so no port mapping from host to container), but allows access to the configured IPv6 addresses instead.

This means that if you don't take any precautions, all your IPv6-enabled container ports are reachable by default. So you have to protect your ports with additional firewall rules.

Enable IPv6 on the Docker daemon

Normally you get a IPv6 routed network from your Internet provider, e.g. a /48 or /64 subnet. As Docker assigns its own auto-ip-addresses, it makes sense to limit the Docker networks to smaller subnets (at least /80, for fitting the MAC address in the interface part).

So first create your own (smaller) IPv6 subnets for Docker:

Example: Your full routed subnet:

2a01:xxxx:yyyy:zzzz::/64

We only use a /80 subnet for the Docker self-assigned addresses:

2a01:xxxx:yyyy:zzzz:ffff::/80

and a 2nd /80 subnet for fixed IPv6 addresses:

2a01:xxxx:yyyy:zzzz:dddd::/80

Enable the Docker daemon's IPv6 capabilities in /etc/docker/daemon.json (create if not present), and configure the auto-assign network:

# /etc/docker/daemon.json:
{
  "ipv6": true,
  "fixed-cidr-v6":"2a01:xxxx:yyyy:zzzz:ffff::/80"
}

Create an IPv6 enabled Docker network for static IP addresses:

$ docker network create --subnet 2a01:xxxx:yyyy:zzzz:dddd::/80 --ipv6 ipv6

Restart docker.

Create IPv6-enabled containers

eiter with self-assigned IP, from the ffff-pool from above:

docker run --rm -ti ubuntu bash

or with a static IP in the newly created ipv6 network:

docker run --rm -ti --network ipv6 --ip6 2a01:xxxx:yyyy:zzzz:dddd::2 ubuntu bash

UFW config

UFW's default forward policy is DROP: So all forwardings from your physical interface to the Docker bridges get blocked.

To allow connections to your IPv6 docker containers, use the following scheme:

ufw route allow in on [physical-interface] out on [docker-network bridge if] to [ipv6] port [tcp port] proto tcp

# Example: allow access to port 80 on specific IP, on docker network bridge:
ufw route allow in on eth0 out on br-2edf2be025e1 to 2a01:xxxx:yyyy:zzzz:dddd::2 port 80 proto tcp

The docker network bridge is br- plus the docker network ID shown with docker network ls. The default bridge when no network is set on container creation is docker0.