• Enable IPv6 on the Droplet
  • Note the IPv6 detail (the data below is for demo only)
PUBLIC IPV6 ADDRESS:
aaaa:bbbb:cccc:dddd:eeee:ffff:1001

PUBLIC IPV6 GATEWAY:
aaaa:bbbb:cccc:dddd:eeee:ffff:1

CONFIGURABLE ADDRESS RANGE:
aaaa:bbbb:cccc:dddd:eeee:ffff:1000 - aaaa:bbbb:cccc:dddd:eeee:ffff:100f
  • Since docker-compose version 3 does not support IPv6 network creation, and we don't want to use an old version, we create a network interface manually.
    The command below creates a network named "ipv6net" using granted address range given by DigitalOcean.
docker network create --attachable --ipv6 --subnet=aaaa:bbbb:cccc:dddd:eeee:ffff:1000/124 ipv6net
  • To avoid creating routing rules of all addresses one by one, we use NDPPD.
    (make sure you have build-tools installed)
git clone https://github.com/DanielAdolfsson/ndppd.git
cd ndppd
make all && make install
  • Create the configuration file /etc/ndppd.conf
# route-ttl <integer> (NEW)
# This tells 'ndppd' how often to reload the route file /proc/net/ipv6_route.
# Default value is '30000' (30 seconds).

route-ttl 30000

# address-ttl <integer> (NEW)
# This tells 'ndppd' how often to reload the IP address file /proc/net/if_inet6
# Default value is '30000' (30 seconds).

address-ttl 30000

# proxy <interface>
# This sets up a listener, that will listen for any Neighbor Solicitation
# messages, and respond to them according to a set of rules (see below).
# <interface> is required. You may have several 'proxy' sections.

proxy eth0 {
   
   # router <yes|no|true|false>
   # This option turns on or off the router flag for Neighbor Advertisement
   # messages. Default value is 'true'.
   
   router yes

   # timeout <integer>
   # Controls how long to wait for a Neighbor Advertisment message before 
   # invalidating the entry, in milliseconds. Default value is '500'.

   timeout 500   

   # autowire <yes|no|true|false>
   # Controls whether ndppd will automatically create host entries
   # in the routing tables when it receives Neighbor Advertisements on a
   # listening interface. The the default value is no.
   # Note: Autowire will ignore all rules with 'auto' or 'static' given it
   # is expected that the routes are already defined for these paths

   autowire no

   # keepalive <yes|no|true|false>
   # Controls whether ndppd will automatically attempt to keep routing
   # sessions alive by actively sending out NDP Solicitations before the the
   # session is expired. The the default value is yes.
   
   keepalive yes

   # retries <integer>
   # Number of times a NDP Solicitation will be sent out before the daemon
   # considers a route unreachable. The default value is 3

   retries 3

   # promiscuous <yes|no|true|false>
   # Controls whether ndppd will put the proxy listening interface into promiscuous
   # mode and hence will react to inbound and outbound NDP commands. This is
   # required for machines behind the gateway to talk to each other in more
   # complex topology scenarios. The the default value is no.

   promiscuous no
   
   # ttl <integer>
   # Controls how long a valid or invalid entry remains in the cache, in 
   # milliseconds. Default value is '30000' (30 seconds).
   
   ttl 30000

   # rule <ip>[/<mask>]
   # This is a rule that the target address is to match against. If no netmask
   # is provided, /128 is assumed. You may have several rule sections, and the
   # addresses may or may not overlap.

   rule 1111:: {
      # Only one of 'static', 'auto' and 'interface' may be specified. Please
      # read 'ndppd.conf' manpage for details about the methods below.

      # 'auto' should work in most cases.

      # static (NEW)
      # 'ndppd' will immediately answer any Neighbor Solicitation Messages
      # (if they match the IP rule).

      # iface <interface>
      # 'ndppd' will forward the Neighbor Solicitation Message through the
      # specified interface - and only respond if a matching Neighbor
      # Advertisement Message is received.
      
      # auto (NEW)
      # Same as above, but instead of manually specifying the outgoing
      # interface, 'ndppd' will check for a matching route in /proc/net/ipv6_route.

      auto

      # autovia <yes|no|true|false>
      # Any addresses updated using NDP advertisments will use a gateway to
      # route traffic on this particular interface (only works wiith the iface
      # rule type). Default is no

      autovia no

      # Note that before version 0.2.2 of 'ndppd', if you didn't choose a
      # method, it defaulted to 'static'. For compatibility reasons we choose
      # to keep this behavior - for now (it may be removed in a future version).
   }
}
  • Change "rule 1111::" to:
aaaa:bbbb:cccc:dddd:eeee:ffff:1000/124
  • Change "auto" to:
sysctl --system
  • Save, and run:
ndppd -d
  • To autorun in the future:
crontab -e
@reboot /usr/local/sbin/ndppd -d
  • Modify /etc/sysctl.conf
net.ipv6.conf.eth0.proxy_ndp=1

# Below maybe needed
# net.ipv6.conf.all.accept_ra = 2
# net.ipv6.conf.default.forwarding = 1
# net.ipv6.conf.all.forwarding = 1
  • To apply changes without reboot, run:
sysctl
  • To use IPv6 on Docker-compose, in docker-compose.yml
version: '3.5'
services:
  ipv6test:
    networks:
      - ipv6net
networks:
  ipv6net:
    external: true
  • To test if IPv6 works (on host or inside Docker container), run:
ping6 2606:4700:4700::1111
curl -6 ifconfig.co

Reference: https://qiita.com/konosuke/items/f2bc33887c1259616616#forward%E3%81%A8nat%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB%E3%82%92%E8%BF%BD%E5%8A%A0