Docker IPv6 networking: The redux

A few years ago, I wrote about setting up IPv6 connectivity in Docker, focusing mainly on hooking up a RIPE Atlas probe using NDP proxying. Since then, I’ve moved house and now want to set up another probe in a slightly different environment.

Firstly, I’ll mention that the Proper Way™ to get IPv6 connectivity to Docker containers for general use is probably to enable IP forwarding on the Docker host and allocate a GUA range to it via a static route/RA/DHCPv6-PD. Then the Docker documentation should be able to get you the rest of the way. This aspect seems to have improved a lot since my previous post! 🎉

But I’m trying to do something a bit more obscure. I want the container to have a v6 address:

  • In whatever dynamic prefix is announced on my LAN. My ISP does offer static IPv6 prefixes but I haven’t found any other use for one yet so haven’t set it up. This isn’t possible under my previous approach nor the aforementioned Proper Way™.
  • With a specific suffix/token, mainly so I can easily filter Atlas traffic out of packet captures. This was possible under my previous approach, but only because the address was fully statically defined anyway.

The solution I found is the macvlan network driver with some funky config. Firstly, the relevant compose directives:

services:
  probe:
    image: jamesits/ripe-atlas:latest-armv7l
    # ...
    configs:
      - source: setIP6.sh
        target: /usr/local/bin/setIP6.sh
        mode: 0555
    entrypoint: setIP6.sh
    cap_add:
      # ...
      - NET_ADMIN
    sysctls:
      net.ipv6.conf.all.disable_ipv6: 0
    networks:
      probe-network:

configs:
  setIP6.sh:
    content: |
      #!/usr/bin/env bash
      ip token set ::a:71a5 dev eth0
      exec tini -- entrypoint.sh atlas

networks:
  probe-network:
    driver: macvlan
    driver_opts:
      parent: eth0
    ipam:
      config:
        - subnet: "192.0.2.0/24"
          ip_range: "192.0.2.47/32"
          gateway: "192.0.2.1"

The networks section is pretty standard, just restricting the available IPv4 addresses to a single address outside the DHCP range of my network. This is also an improvement over my previous solution, which NATted the container behind the host’s v4 address.

IPv6 is more tricky. macvlan still wants static v6 ranges like the other drivers, which I specifically didn’t want to do. However because macvlan essentially puts the container in the same broadcast domain as the host, simply flipping off the disable_ipv6 sysctl that Docker sets by default is enough to get the container picking up addresses via SLAAC.

The only remaining hurdle is setting the suffix I want the container to use. This is easily done using the ip token set command, which I’m calling through an inline override of the container’s entrypoint that then execs the original entrypoint. The only other change is that ip needs the NET_ADMIN capability.

Comments