IPv6 functionality is disabled by default in Docker. Much like other features we reviewed earlier, enabling it requires doing so at the service level. Once enabled, Docker will provision the host interfaces associated with Docker, as well as the containers themselves, with IPv6 addressing.
In this recipe, we'll be using a small lab consisting of two Docker hosts:
Each host has both an IPv4 address as well as an IPv6 address assigned to its physical interface. You'll need root-level access to each host to make network configuration changes. It is assumed that Docker is installed, and it's a default configuration.
As mentioned, Docker will not provision containers with an IPv6 address unless told to do so. To enable IPv6 in Docker, we need to pass a service-level flag to the Docker service.
If you need a refresher on defining Docker service-level parameters, see the last recipe in Chapter 2, Configuring and Monitoring Docker Networks, where we discuss configuring these on a system running systemd
.
In addition to enabling IPv6 functionality, you also need to define a subnet for the docker0
bridge. To do this, we'll modify our systemd
drop-in file for Docker and make sure that it has the following options:
docker1
:ExecStart=/usr/bin/dockerd --ipv6 --fixed-cidr-v6=2003:cd11::/64
docker2
:ExecStart=/usr/bin/dockerd --ipv6 --fixed-cidr-v6=2003:ef11::/64
If we apply this configuration, reload the systemd
configuration and restart the Docker service on each host, we should see that the docker0
bridge has taken the first available IP address from the defined IPv6 CIDR range:
user@docker1:~$ ip -6 addr show dev docker0 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 inet6 2003:cd11::1/64 scope global tentative valid_lft forever preferred_lft forever inet6 fe80::1/64 scope link tentative valid_lft forever preferred_lft forever user@docker1:~$ user@docker2:~$ ip -6 addr show dev docker0 5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 inet6 2003:ef11::1/64 scope global tentative valid_lft forever preferred_lft forever inet6 fe80::1/64 scope link tentative valid_lft forever preferred_lft forever user@docker2:~$
At this point, our topology looks a lot like it did in the first recipe:
Docker will issue an IPv6 address along with an IPv4 address to each container it creates. Let's spin up a container on the first host to see what I mean:
user@docker1:~$ docker run -d --name=web1 jonlangemak/web_server_1
50d522d176ebca2eac0f7e826ffb2e36e754ce27b3d3b4145aa8a11c6a13cf15
user@docker1:~$
Note that we did not pass the -P
flag to the containers to publish the containers exposed ports. If we test locally, we can validate that the host can reach the service within the container from both the containers IPv4 and IPv6 address:
user@docker1:~$ docker exec web1 ifconfig eth0 eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:02 inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link inet6 addr: 2003:cd11::242:ac11:2/64 Scope:Global UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:16 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:1792 (1.7 KB) TX bytes:648 (648.0 B) user@docker1:~$ curl http://172.17.0.2 <body> <html> <h1><span style="color:#FF0000;font-size:72px;">Web Server #1 - Running on port 80</span> </h1> </body> </html> user@docker1:~$ curl -g http://[2003:cd11::242:ac11:2] <body> <html> <h1><span style="color:#FF0000;font-size:72px;">Web Server #1 - Running on port 80</span> </h1> </body> </html> user@docker1:~$
As we can see, the behavior with the IPv6 address is the same as it is with the IPv4 address. Following suit, containers on the same host can talk directly to each other across the docker0
bridge using their assigned IPv6 address. Let's start a second container on the same host:
user@docker1:~$ docker run -d --name=web2 jonlangemak/web_server_2
A quick validation will prove to us that these two containers are allowed to talk directly to one another with their IPv6 addresses just as expected:
user@docker1:~$ docker exec web2 ip -6 addr show dev eth0 10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 inet6 2003:cd11::242:ac11:3/64 scope global nodad valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:3/64 scope link valid_lft forever preferred_lft forever user@docker1:~$ user@docker1:~$ docker exec -it web1 curl -g http://[2003:cd11::242:ac11:3] <body> <html> <h1><span style="color:#FF0000;font-size:72px;">Web Server #2 - Running on port 80</span> </h1> </body> </html> user@docker1:~$