github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/docs/userguide/networking/default_network/ipv6.md (about)

     1  <!--[metadata]>
     2  +++
     3  title = "IPv6 with Docker"
     4  description = "How do we connect docker containers within and across hosts ?"
     5  keywords = ["docker, network, IPv6"]
     6  [menu.main]
     7  parent = "smn_networking_def"
     8  weight = 3
     9  +++
    10  <![end-metadata]-->
    11  
    12  # IPv6 with Docker
    13  
    14  The information in this section explains IPv6 with the Docker default bridge.
    15  This is a `bridge` network named `bridge` created automatically when you install
    16  Docker.  
    17  
    18  As we are [running out of IPv4
    19  addresses](http://en.wikipedia.org/wiki/IPv4_address_exhaustion) the IETF has
    20  standardized an IPv4 successor, [Internet Protocol Version
    21  6](http://en.wikipedia.org/wiki/IPv6) , in [RFC
    22  2460](https://www.ietf.org/rfc/rfc2460.txt). Both protocols, IPv4 and IPv6,
    23  reside on layer 3 of the [OSI model](http://en.wikipedia.org/wiki/OSI_model).
    24  
    25  ## How IPv6 works on Docker
    26  
    27  By default, the Docker server configures the container network for IPv4 only.
    28  You can enable IPv4/IPv6 dualstack support by running the Docker daemon with the
    29  `--ipv6` flag. Docker will set up the bridge `docker0` with the IPv6 [link-local
    30  address](http://en.wikipedia.org/wiki/Link-local_address) `fe80::1`.
    31  
    32  By default, containers that are created will only get a link-local IPv6 address.
    33  To assign globally routable IPv6 addresses to your containers you have to
    34  specify an IPv6 subnet to pick the addresses from. Set the IPv6 subnet via the
    35  `--fixed-cidr-v6` parameter when starting Docker daemon:
    36  
    37  ```
    38  dockerd --ipv6 --fixed-cidr-v6="2001:db8:1::/64"
    39  ```
    40  
    41  The subnet for Docker containers should at least have a size of `/80`. This way
    42  an IPv6 address can end with the container's MAC address and you prevent NDP
    43  neighbor cache invalidation issues in the Docker layer.
    44  
    45  With the `--fixed-cidr-v6` parameter set Docker will add a new route to the
    46  routing table. Further IPv6 routing will be enabled (you may prevent this by
    47  starting dockerd with `--ip-forward=false`):
    48  
    49  ```
    50  $ ip -6 route add 2001:db8:1::/64 dev docker0
    51  
    52  $ sysctl net.ipv6.conf.default.forwarding=1
    53  
    54  $ sysctl net.ipv6.conf.all.forwarding=1
    55  ```
    56  
    57  All traffic to the subnet `2001:db8:1::/64` will now be routed via the `docker0` interface.
    58  
    59  Be aware that IPv6 forwarding may interfere with your existing IPv6
    60  configuration: If you are using Router Advertisements to get IPv6 settings for
    61  your host's interfaces you should set `accept_ra` to `2`. Otherwise IPv6 enabled
    62  forwarding will result in rejecting Router Advertisements. E.g., if you want to
    63  configure `eth0` via Router Advertisements you should set:
    64  
    65  ```
    66  $ sysctl net.ipv6.conf.eth0.accept_ra=2
    67  ```
    68  
    69  ![](images/ipv6_basic_host_config.svg)
    70  
    71  Every new container will get an IPv6 address from the defined subnet. Further a
    72  default route will be added on `eth0` in the container via the address specified
    73  by the daemon option `--default-gateway-v6` if present, otherwise via `fe80::1`:
    74  ```
    75  docker run -it ubuntu bash -c "ip -6 addr show dev eth0; ip -6 route show"
    76  
    77  15: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500
    78     inet6 2001:db8:1:0:0:242:ac11:3/64 scope global
    79        valid_lft forever preferred_lft forever
    80     inet6 fe80::42:acff:fe11:3/64 scope link
    81        valid_lft forever preferred_lft forever
    82  
    83  2001:db8:1::/64 dev eth0  proto kernel  metric 256
    84  fe80::/64 dev eth0  proto kernel  metric 256
    85  default via fe80::1 dev eth0  metric 1024
    86  ```
    87  
    88  In this example the Docker container is assigned a link-local address with the
    89  network suffix `/64` (here: `fe80::42:acff:fe11:3/64`) and a globally routable
    90  IPv6 address (here: `2001:db8:1:0:0:242:ac11:3/64`). The container will create
    91  connections to addresses outside of the `2001:db8:1::/64` network via the
    92  link-local gateway at `fe80::1` on `eth0`.
    93  
    94  Often servers or virtual machines get a `/64` IPv6 subnet assigned (e.g.
    95  `2001:db8:23:42::/64`). In this case you can split it up further and provide
    96  Docker a `/80` subnet while using a separate `/80` subnet for other applications
    97  on the host:
    98  
    99  ![](images/ipv6_slash64_subnet_config.svg)
   100  
   101  In this setup the subnet `2001:db8:23:42::/80` with a range from
   102  `2001:db8:23:42:0:0:0:0` to `2001:db8:23:42:0:ffff:ffff:ffff` is attached to
   103  `eth0`, with the host listening at `2001:db8:23:42::1`. The subnet
   104  `2001:db8:23:42:1::/80` with an address range from `2001:db8:23:42:1:0:0:0` to
   105  `2001:db8:23:42:1:ffff:ffff:ffff` is attached to `docker0` and will be used by
   106  containers.
   107  
   108  ### Using NDP proxying
   109  
   110  If your Docker host is only part of an IPv6 subnet but has not got an IPv6
   111  subnet assigned you can use NDP proxying to connect your containers via IPv6 to
   112  the internet. For example your host has the IPv6 address `2001:db8::c001`, is
   113  part of the subnet `2001:db8::/64` and your IaaS provider allows you to
   114  configure the IPv6 addresses `2001:db8::c000` to `2001:db8::c00f`:
   115  
   116  ```
   117  $ ip -6 addr show
   118  
   119  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
   120      inet6 ::1/128 scope host
   121         valid_lft forever preferred_lft forever
   122  2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
   123      inet6 2001:db8::c001/64 scope global
   124         valid_lft forever preferred_lft forever
   125      inet6 fe80::601:3fff:fea1:9c01/64 scope link
   126         valid_lft forever preferred_lft forever
   127  ```
   128  
   129  Let's split up the configurable address range into two subnets
   130  `2001:db8::c000/125` and `2001:db8::c008/125`. The first one can be used by the
   131  host itself, the latter by Docker:
   132  
   133  ```
   134  dockerd --ipv6 --fixed-cidr-v6 2001:db8::c008/125
   135  ```
   136  
   137  You notice the Docker subnet is within the subnet managed by your router that is
   138  connected to `eth0`. This means all devices (containers) with the addresses from
   139  the Docker subnet are expected to be found within the router subnet. Therefore
   140  the router thinks it can talk to these containers directly.
   141  
   142  ![](images/ipv6_ndp_proxying.svg)
   143  
   144  As soon as the router wants to send an IPv6 packet to the first container it
   145  will transmit a neighbor solicitation request, asking, who has `2001:db8::c009`?
   146  But it will get no answer because no one on this subnet has this address. The
   147  container with this address is hidden behind the Docker host. The Docker host
   148  has to listen to neighbor solicitation requests for the container address and
   149  send a response that itself is the device that is responsible for the address.
   150  This is done by a Kernel feature called `NDP Proxy`. You can enable it by
   151  executing
   152  
   153  ```
   154  $ sysctl net.ipv6.conf.eth0.proxy_ndp=1
   155  ```
   156  
   157  Now you can add the container's IPv6 address to the NDP proxy table:
   158  
   159  ```
   160  $ ip -6 neigh add proxy 2001:db8::c009 dev eth0
   161  ```
   162  
   163  This command tells the Kernel to answer to incoming neighbor solicitation
   164  requests regarding the IPv6 address `2001:db8::c009` on the device `eth0`. As a
   165  consequence of this all traffic to this IPv6 address will go into the Docker
   166  host and it will forward it according to its routing table via the `docker0`
   167  device to the container network:
   168  
   169  ```
   170  $ ip -6 route show
   171  
   172  2001:db8::c008/125 dev docker0  metric 1
   173  2001:db8::/64 dev eth0  proto kernel  metric 256
   174  ```
   175  
   176  You have to execute the `ip -6 neigh add proxy ...` command for every IPv6
   177  address in your Docker subnet. Unfortunately there is no functionality for
   178  adding a whole subnet by executing one command. An alternative approach would be
   179  to use an NDP proxy daemon such as
   180  [ndppd](https://github.com/DanielAdolfsson/ndppd).
   181  
   182  ## Docker IPv6 cluster
   183  
   184  ### Switched network environment
   185  Using routable IPv6 addresses allows you to realize communication between
   186  containers on different hosts. Let's have a look at a simple Docker IPv6 cluster
   187  example:
   188  
   189  ![](images/ipv6_switched_network_example.svg)
   190  
   191  The Docker hosts are in the `2001:db8:0::/64` subnet. Host1 is configured to
   192  provide addresses from the `2001:db8:1::/64` subnet to its containers. It has
   193  three routes configured:
   194  
   195  - Route all traffic to `2001:db8:0::/64` via `eth0`
   196  - Route all traffic to `2001:db8:1::/64` via `docker0`
   197  - Route all traffic to `2001:db8:2::/64` via Host2 with IP `2001:db8::2`
   198  
   199  Host1 also acts as a router on OSI layer 3. When one of the network clients
   200  tries to contact a target that is specified in Host1's routing table Host1 will
   201  forward the traffic accordingly. It acts as a router for all networks it knows:
   202  `2001:db8::/64`, `2001:db8:1::/64` and `2001:db8:2::/64`.
   203  
   204  On Host2 we have nearly the same configuration. Host2's containers will get IPv6
   205  addresses from `2001:db8:2::/64`. Host2 has three routes configured:
   206  
   207  - Route all traffic to `2001:db8:0::/64` via `eth0`
   208  - Route all traffic to `2001:db8:2::/64` via `docker0`
   209  - Route all traffic to `2001:db8:1::/64` via Host1 with IP `2001:db8:0::1`
   210  
   211  The difference to Host1 is that the network `2001:db8:2::/64` is directly
   212  attached to the host via its `docker0` interface whereas it reaches
   213  `2001:db8:1::/64` via Host1's IPv6 address `2001:db8::1`.
   214  
   215  This way every container is able to contact every other container. The
   216  containers `Container1-*` share the same subnet and contact each other directly.
   217  The traffic between `Container1-*` and `Container2-*` will be routed via Host1
   218  and Host2 because those containers do not share the same subnet.
   219  
   220  In a switched environment every host has to know all routes to every subnet.
   221  You always have to update the hosts' routing tables once you add or remove a
   222  host to the cluster.
   223  
   224  Every configuration in the diagram that is shown below the dashed line is
   225  handled by Docker: The `docker0` bridge IP address configuration, the route to
   226  the Docker subnet on the host, the container IP addresses and the routes on the
   227  containers. The configuration above the line is up to the user and can be
   228  adapted to the individual environment.
   229  
   230  ### Routed network environment
   231  In a routed network environment you replace the layer 2 switch with a layer 3
   232  router. Now the hosts just have to know their default gateway (the router) and
   233  the route to their own containers (managed by Docker). The router holds all
   234  routing information about the Docker subnets. When you add or remove a host to
   235  this environment you just have to update the routing table in the router - not
   236  on every host.
   237  
   238  ![](images/ipv6_routed_network_example.svg)
   239  
   240  In this scenario containers of the same host can communicate directly with each
   241  other. The traffic between containers on different hosts will be routed via
   242  their hosts and the router. For example packet from `Container1-1` to
   243  `Container2-1` will be routed through `Host1`, `Router` and `Host2` until it
   244  arrives at `Container2-1`.
   245  
   246  To keep the IPv6 addresses short in this example a `/48` network is assigned to
   247  every host. The hosts use a `/64` subnet of this for its own services and one
   248  for Docker. When adding a third host you would add a route for the subnet
   249  `2001:db8:3::/48` in the router and configure Docker on Host3 with
   250  `--fixed-cidr-v6=2001:db8:3:1::/64`.
   251  
   252  Remember the subnet for Docker containers should at least have a size of `/80`.
   253  This way an IPv6 address can end with the container's MAC address and you
   254  prevent NDP neighbor cache invalidation issues in the Docker layer. So if you
   255  have a `/64` for your whole environment use `/78` subnets for the hosts and
   256  `/80` for the containers. This way you can use 4096 hosts with 16 `/80` subnets
   257  each.
   258  
   259  Every configuration in the diagram that is visualized below the dashed line is
   260  handled by Docker: The `docker0` bridge IP address configuration, the route to
   261  the Docker subnet on the host, the container IP addresses and the routes on the
   262  containers. The configuration above the line is up to the user and can be
   263  adapted to the individual environment.