How to setup IPv6 with docker-compose

I am using Ubuntu 18.04 on DigitalOcean, with IPv6 turned on:

PUBLIC IPV6 ADDRESS:
xxxx:xxxx:2:d0::216f:3001
PUBLIC IPV6 GATEWAY:
xxxx:xxxx:2:d0::1
CONFIGURABLE ADDRESS RANGE:
xxxx:xxxx:2:d0::216f:3000 - xxxx:xxxx:2:d0::216f:300f

According to this page: https://docs.docker.com/v17.09/engine/userguide/networking/default_network/ipv6/#docker-ipv6-cluster

Is it correct to put the 16 IPv6 addresses like this?

{
  "ipv6": true,
  "fixed-cidr-v6": "xxxx:xxxx:2:d0::216f:3000/124"
}

Or, is it just fine to use these (as if something like 192.168.0.x)?

{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8::c008/125"
}

Anyway I have tried the first one.

docker run -d --name ipv6test alpine ash -c "ping6 2606:4700:4700::1111"

I "docker inspect" for the IPv6 address. I make the NDP record:

ip -6 neigh add proxy xxxx:xxxx:2:d0::216f:3004 dev eth0

In this case, the container could communicate with the outside world.

Testing finished. I want to apply IPv6 to my project. It starts with docker-compose.

According to this page: https://docs.docker.com/compose/compose-file/#ipv4_address-ipv6_address

version: "3.7"

services:
  app:
    image: nginx:alpine
    networks:
      app_net:
        ipv6_address: xxxx:xxxx:2:d0::216f:3010

networks:
  app_net:
    ipam:
      driver: default
      config:
        - subnet: "xxxx:xxxx:2:d0::216f:3000/124"

Inside the container, no connection could be made:

# ping6 2606:4700:4700::1111
PING 2606:4700:4700::1111 (2606:4700:4700::1111): 56 data bytes
ping6: sendto: Address not available

Have I missed anything?

Thanks.


Solution 1:

Might be a little bit late, but this is the setup that worked for me on DigitalOcean:

  1. Create /etc/docker/daemon.json:
{
    "ipv6": true,
    "fixed-cidr-v6": "<Your IPv6 address range start in DO console>/124"
}
  1. sudo systemctl restart docker

  2. Add to your docker-compose.yml:

    sysctls:
      - "net.ipv6.conf.all.disable_ipv6=0"

Basically it seems the default is to disable IPv6 and we need to enable it in sysctl.

EDIT: Actually this allows the docker container to obtain an IPv6 address and perform IPv6 name resolution, but somehow it cannot send data (Network unreachable).

Although docker containers started with docker directly, which runs on the default bridge network, is able to access external IPv6 hosts, docker containers started by docker-compose runs in its dedicated network, so maybe one will need more routing work. My use case was actually limited (socat as IPv4 to IPv6 proxy) so I simply resorted to using the host network directly, with:

    network_mode: host

Solution 2:

My personal setup, that works. It uses docker's internal default bridge instead of users supplied networking.

  1. /etc/docker/daemon.json
{
    "ipv6": true,
    "fixed-cidr-v6": "2a02:168:7a0e:11::/64"
}
  1. docker-compose.yml
version: '3.3'

services:
  shell:
    networks:
      - bridge
    image: centos:8

networks:
  bridge:
    external: true
  1. Testing
docker-compose run --rm shell
  1. In container
[root@dfeb2fe7917d /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
218917: eth0@if218918: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2a02:168:7a0e:11:0:242:ac11:2/64 scope global nodad 
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link 
       valid_lft forever preferred_lft forever
[root@dfeb2fe7917d /]# ping6 -c 3 google.ch
PING google.ch(zrh04s15-in-x03.1e100.net (2a00:1450:400a:803::2003)) 56 data bytes
64 bytes from zrh04s15-in-x03.1e100.net (2a00:1450:400a:803::2003): icmp_seq=1 ttl=114 time=0.774 ms
64 bytes from zrh04s15-in-x03.1e100.net (2a00:1450:400a:803::2003): icmp_seq=2 ttl=114 time=1.12 ms
64 bytes from zrh04s15-in-x03.1e100.net (2a00:1450:400a:803::2003): icmp_seq=3 ttl=114 time=1.13 ms

--- google.ch ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 4ms
rtt min/avg/max/mdev = 0.774/1.008/1.128/0.165 ms

Solution 3:

ipv6_address: xxxx:xxxx:2:d0::216f:3010 does not look like being in the same subnet: xxxx:xxxx:2:d0::216f:3000/124

Try with something like xxxx:xxxx:2:d0::216f:300[0-f].