Posts tagged ‘docker’

07/22/2014

IPv6 in Docker Containers on DigitalOcean

by Jeff Loughridge

This post details how I enabled IPv6 addresses in docker containers on DigitalOcean.

DigitalOcean supports IPv6 in its London 1 and Singapore 1 data centers as of July 2014. Create a droplet using the Ubuntu 14.04 image and DO’s docker installation under Applications in the “Create VM” screen. Make sure to check “IPv6”.

DO provides a VM with 20 addresses within a /64. docker0 gets assigned 0x1 as the last hex character. I give the docker0 interface 0x4. This leaves 0x5 to 0xf for my containers.

Let’s take an example. DO gives me 2a03:b0c0:1:d0::18:d000 to 2a03:b0c0:1:d0::18:d00f. docker0 gets 2a03:b0c0:1:d0::18:d004. The last double octet for containers ranges from 0xd005 to 0xd00f.

To break up the 20 addresses provided by DO, we need a way for containers to respond to IPv6 neighbor discovery on the host’s eth0 interface. This could be performed using a ND proxy daemon (see here for one implementation). For most docker use cases, a static ND proxy entry should do.

docker does not natively support IPv6. LXC, the foundation of docker, can handle IPv6 in containers. As of docker 1, the software uses libcontainer by default instead of LXC. We’ll have to configure /etc/default/docker to use the LXC driver.

See below for example for one time set-up of the droplet.

#!/bin/bash

# enable IPv6 forwarding and ND proxying
echo net.ipv6.conf.all.proxy_ndp=1 >> /etc/sysctl.conf
echo net.ipv6.conf.all.forwarding=1 >> /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf

# install LXC
sudo apt-get install -y lxc

# use the LXC driver
echo DOCKER_OPTS=\"--exec-driver=lxc\" >> /etc/default/docker

service docker restart

The script below demonstrates how to set-up the static ND proxy entries. Make sure to change the V6_START variable.


#!/bin/bash
 
# This script provides an example of setting up IPv6 static
# ND proxy entries. Edit the V6_START to match
# what you see in the DO control panel
 
V6_START=2a03:b0c0:1:d0::18:d000
 
# strip the last hex character
V6_MINUS_LAST_HEX_CHAR=`echo $V6_START|sed s/.$//`
 
ip addr add ${V6_MINUS_LAST_HEX_CHAR}4/124 dev docker0
 
echo "adding ND proxy entries..."
for character in 4 5 6 7 8 9 a b c d e f; do
  echo "ip -6 neigh add proxy ${V6_MINUS_LAST_HEX_CHAR}${character} dev eth0"
  ip -6 neigh add proxy ${V6_MINUS_LAST_HEX_CHAR}${character} dev eth0
done

Now we’re ready to bring up the container. The first argument must be an IPv6 address in your assigned
range with the last double octet between 0xXXX5 and 0xXXXF. For me, this is 0xd005 to 0xd00f.

#!/bin/bash
 
# first argument to script must be IPv6 address from DO-allocated
# space that is not part of the first /126 (e.g. 0x4 to 0xF as last
# hex character
 
IPV6_ADDRESS=$1
 
if [ -z "$IPV6_ADDRESS" ]; then
  echo "please specify IPv6 address for container's eth0"
  exit 1
fi
 
echo "container eth0: $IPV6_ADDRESS"

# run container so that docker0 gets a link local address
docker run busybox:ubuntu-14.04 /bin/true
docker rm $(docker ps -lq)

# get docker0's link local address
LINK_LOCAL=$( \
  ip addr show docker0 | \
   grep "inet6 fe80" | \
    awk '{print $2}' | \
      sed 's/\/.*//' \
)

if [ -z "$LINK_LOCAL" ]; then
  echo "unable to find link local address on docker0. something is wrong."
  exit 1
fi
 
echo "docker0 link local: $LINK_LOCAL"
 
docker run -i -t \
   --lxc-conf="lxc.network.flags = up" \
   --lxc-conf="lxc.network.ipv6 = $IPV6_ADDRESS/124" \
   --lxc-conf="lxc.network.ipv6.gateway = $LINK_LOCAL" busybox:ubuntu-14.04 /bin/sh

Executing the script will put you in interactive mode in a shell in the container. Try ‘ping6 2600::’ to to test connectivity. If you are having trouble, let me know in the comments.

I want to thank Andreas Neuhaus for his IPv6 in Docker Containers post and his suggestion to use static ND proxy when the provider does not route a /64 to your docker host.

UPDATE 1/17/2015 – Docker now has native IPv6 functionality. See this post.