Enabling IPv6 capabilities in Docker

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.

Getting ready

In this recipe, we'll be using a small lab consisting of two Docker hosts:

Getting ready

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.

How to do it…

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.

Note

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:

  • On the host docker1:
    ExecStart=/usr/bin/dockerd --ipv6 --fixed-cidr-v6=2003:cd11::/64
  • On the host 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:

How to do it…

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:~$

Note

When using curl with IPv6 addresses, you need to put the IPv6 address inside of brackets and then tell curl not to glob by passing the -g flag.

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:~$
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset