APNIC Pty Ltd.

05/23/2022 | Press release | Distributed by Public on 05/22/2022 17:38

Running Docker / Alpine Linux in an IPv6-only environment

This month, my virtual private server started offering IPv6-only as a general service.

At the OS level, both servers and clients support IPv4 and IPv6 network environments using dual-stack but there are quite a few HTTP/HTTPS servers that do not yet have AAAA records. By default, the Docker server configures container networks for IPv4-only, so I had a hard time running it in this environment.

To help others facing similar scenarios, I wanted to share my experience running Docker/Alpine Linux in the IPv6-only environment of Rocky Linux 8.5.

Installing Docker

First, install Docker using the command.

I used the dnf command because yum is not recommended on recent CentOS Linux.

Permission settings for users running Docker

If you want to run Docker somewhere other than root, set your user to belong to the Docker group.

sudo groupadd docker
#groupadd: group'docker' already exists
sudo usermod -aG docker $ USER

Create a daemon .json for IPv6

Add IPv6-compatible settings to the Docker daemon startup options at .

sudo vi /etc/docker/daemon.json

The contents of the created file are as follows:

{
  "ipv6": true,
  "fixed-cidr-v6": "fd11:2233:4455:6677::/64",
  "registry-mirrors": ["https://mirror.gcr.io"]
}

Docker's default registry only returns IPv4 addresses, so you can't communicate in an IPv6-only environment. In this case, set Google's registry mirror that supports IPv6. The setting is a Unique Local Address (ULA) that you set yourself and is equivalent to an IPv6 private address. To use it, specify any address starting with 'fd.', for example

Restart Docker

Restart Docker for these settings to take effect.

sudo systemctl restart docker

If you get an error, review the daemon.json configuration file and fix it.

Add NAT with ip6tables

Set NAT in of daemon.json so that you can communicate outwards from the internal network.

Check if the NAT table has been added correctly by specifying as an argument.

sudo ip6tables -t nat -L
MASQUERADE all fd11:2233:4455:6677::/64 anywhere

It's okay if the following has the line anywhere in the output.

Chain PREROUTING (policy ACCEPT)
target prot opt ​​source destination

Chain INPUT (policy ACCEPT)
target prot opt ​​source destination

Chain POSTROUTING (policy ACCEPT)
target prot opt ​​source destination
MASQUERADE all fd11:2233:4455:6677::/64 anywhere

Chain OUTPUT (policy ACCEPT)
target prot opt ​​source destination

Rc.local settings on reboot

Set so that the NAT setting is valid even after rebooting.

sudo vi /etc/rc.d/rc.local

The is a backwards compatibility file but you should add the following line at the end.

If this is your first time setting up , run the following command to make it run on reboot:

sudo chmod +x/etc/rc.d/rc.local
sudo systemctl start rc-local

Check the current settings with Docker info

Run to see the current settings. You should get an output like this:

It's not a problem if the output has in .

Creating a Dockerfile for Alpine Linux

Create a Dockerfile in a directory of your choice with . The contents of the Dockerfile are as follows:

FROM alpine: 3.15.4
RUN apk update && apk add bind-tools curl
CMD ["/bin/sh"]

After pulling the image of , I wanted to use the dig command and curl command, so I installed the bind tools and curl apk package and start the shell by default.

Build Docker

The tag name can be whatever you like, but you must build Docker with .

docker build -t ipv6/alpine

If you can download the apk package from the IPv6 server and get the following result at build time, it has been successful.

If there are no errors, it has been successful. Congratulations!

Errors in registry-1.docker.io

If you get the following error when building Docker, it has failed.

This means does not have an IPv6 AAAA record and you are trying to communicate with an IPv4 address.

In this case, you'll need to specify in the above daemon.json so the mirror server can communicate with IPv6. If that fails, it may be that the download URL is mis-cached by Docker. Try changing the setting and downloading another version such as or .

If you get an error on dl-cdn .alpinelinux.org

If you get the following error when building Docker, it is failing because you cannot communicate from outwards from Docker in an IPv6-only environment.

The ip6tables NAT is necessary to communicate from the internal network and is specified with in the daemon.json mentioned above. You need to check if it is enabled.

Also, as of 3 May 2022, is dual-stacked and has IPv6 AAAA records, so you should be able to communicate in an IPv6-only environment.

If the server does not return AAAA records, it will fail when trying to communicate with an IPv4 address. To fix this, specify a mirror server that can communicate with IPv6, such as by executing with Dockerfile:

You can check the list of official mirror servers at Official Alpine Linux mirrors.

Run Docker

Docker runs with the tag name specified at build time. You can run the shell interactively with the option.

docker container run -it ipv6/alpine

After successfully entering the shell, use the curl command to check if HTTP communication with the IPv6 server is possible.

A 301 response indicates success, showing it was possible to communicate with IPv6-only. Congratulations.

BusyBox wget isn't completely compatible with IPv6

BusyBox's wget is not fully IPv6 compliant, so it's a good idea to replace the command with or use the curl command.

It would be great if the Internet could be used more in an IPv6-only environment.

Translated and adapted from the original post on Hatena Blog.

Yoshinori Takesako is the founder of SECCON.

The views expressed by the authors of this blog are their own and do not necessarily reflect the views of APNIC. Please note a Code of Conduct applies to this blog.