This guide tries to explain workarounds required to live with Docker on a IPv6-only host.
Docker hub itself works great with IPv6, but other services - like github - not so much. In order to enable communication with IPv4-only services wee need to use a proxy like https://github.via-ipv6.com/ or NAT64.
However, we don't necessarily want all traffic being routed through that service. Therfore, we're using dnsmasq to use NAT64 only for domains we need.
cat <<EOF > /etc/dnsmasq.conf
proxy-dnssec
no-resolv
no-poll
no-hosts
# Default DNS: quad9
server=2620:fe::fe
server=2620:fe::9
# Alternative DNS: https://meta.wikimedia.org/wiki/Wikimedia_DNS
server=2001:67c:930::1
# For specific hosts use Public NAT64 service: https://nat64.net/
server=/github.com/2a00:1098:2c::1
server=/github.com/2a00:1098:2b::1
server=/github.com/2a01:4f8:c2c:123f::1
server=/api.github.com/2a00:1098:2c::1
server=/api.github.com/2a00:1098:2b::1
server=/api.github.com/2a01:4f8:c2c:123f::1
server=/objects.githubusercontent.com/2a00:1098:2c::1
server=/objects.githubusercontent.com/2a00:1098:2b::1
server=/objects.githubusercontent.com/2a01:4f8:c2c:123f::1
EOF
Restart dnsmasq and set the DNS to ::1
.
echo "nameserver ::1" > /etc/resolv.conf
It's crucial for our setup not to bind dnsmasq to a specific interface or address. We want it to listen on both IPv4 and IPv6 on all interfaces.
netstat -lnptu | grep dnsmasq
tcp 0 0 0.0.0.0:53 0.0.0.0:* LISTEN 2341/dnsmasq
tcp 0 0 :::53 :::* LISTEN 2341/dnsmasq
udp 0 0 0.0.0.0:53 0.0.0.0:* 2341/dnsmasq
udp 0 0 :::53 :::* 2341/dnsmasq
We need to enable IPv6 support in Docker explicitly:
cat <<EOF > /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64",
"experimental": true,
"ip6tables": true
}
EOF
Then restart docker.
IPv6 docker is still experimental and I found fixed-cidr-v6
not working as expected, yet required, so I leave it be with an example subnet. We are going to set the proper network in docker compose.
Now, for a specific use-case it's best to use Docker Composer to set the network and point to the dnsmasq daemon.
First of we define the network:
networks:
net6:
enable_ipv6: true
driver: bridge
ipam:
driver: default
config:
- subnet: fd00:fd00:ffff::/64
gateway: fd00:fd00:ffff::1
Because it's bridged and our dnsmasq is listening everywhere, the gateway fd00:fd00:ffff::1
will also be used as a DNS address.
Service-wide we're going to point the IPv6 network, assign an uniqe address within fd00:fd00:ffff::/64 network, and set the DNS.
services:
nginx:
networks:
net6:
ipv6_address: fd00:fd00:ffff::10
dns: fd00:fd00:ffff::1
php:
networks:
net6:
ipv6_address: fd00:fd00:ffff::20
dns: fd00:fd00:ffff::1
Now, let's test it out:
mkdir v6test && cd v6test
cat <<EOF > docker-compose.yml
version: '3.9'
services:
nginx:
image: nginx:latest
networks:
net6:
ipv6_address: fd00:fd00:ffff::10
dns: fd00:fd00:ffff::1
php:
image: php:fpm
networks:
net6:
ipv6_address: fd00:fd00:ffff::20
dns: fd00:fd00:ffff::1
networks:
net6:
enable_ipv6: true
driver: bridge
ipam:
driver: default
config:
- subnet: fd00:fd00:ffff::/64
gateway: fd00:fd00:ffff::1
EOF
docker compose up -d
docker compose exec -it php sh -c "curl -v https://ipv4.google.com" # this should fail
docker compose exec -it php sh -c "curl -v https://ipv6.google.com" # but this should work
In case something's not right, make sure to explicitly allow traffic to UDP/53 with DST: fd00:fd00:ffff::1
ip6tables -I INPUT -d fd00:fd00:ffff::1 -p udp --dport 53 -j ACCEPT -m comment --comment 'Allow ULA to dnsmasq'
In this example I use ULA. There is some controversy around it, but it's already widely (or rather wildly) used. The "proper" way is probably figure out a network setup using ordinary public IPv6 addresses from the subnet assigned to your host.
If you care about being compliant, these tools will help you generate some random ULA subnet:
- https://unique-local-ipv6.com/
- https://it-tools.tech/ipv6-ula-generator
- https://github.com/andrewlkho/ulagen
Although, given current IPv6 adoption it will probably take another 20 years until anyone cares.
If you found this article helpful, please consider making donation to a charity on my behalf. Thank you.