Reputation: 1880
I am using docker 1.12.1 on Ubuntu 16.04, and docker-compose 1.8.1. I am trying to get the Compose file from https://docs.docker.com/compose/compose-file/#ipv4-address-ipv6-address to run. For reference, I created docker-compose.yml
with the following content:
version: '2'
services:
app:
image: busybox
command: ifconfig
networks:
app_net:
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::10
networks:
app_net:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "true"
ipam:
driver: default
config:
- subnet: 172.16.238.0/24
gateway: 172.16.238.1
- subnet: 2001:3984:3989::/64
gateway: 2001:3984:3989::1
Now, running docker-compose up
produces
Creating network "tmp_app_net" with driver "bridge"
Creating tmp_app_1
Attaching to tmp_app_1
app_1 | eth0 Link encap:Ethernet HWaddr 02:42:AC:10:EE:0A
app_1 | inet addr:172.16.238.10 Bcast:0.0.0.0 Mask:255.255.255.0
app_1 | inet6 addr: fe80::42:acff:fe10:ee0a/64 Scope:Link
app_1 | UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
app_1 | RX packets:4 errors:0 dropped:0 overruns:0 frame:0
app_1 | TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
app_1 | collisions:0 txqueuelen:0
app_1 | RX bytes:520 (520.0 B) TX bytes:90 (90.0 B)
app_1 |
app_1 | lo Link encap:Local Loopback
app_1 | inet addr:127.0.0.1 Mask:255.0.0.0
app_1 | inet6 addr: ::1/128 Scope:Host
app_1 | UP LOOPBACK RUNNING MTU:65536 Metric:1
app_1 | RX packets:0 errors:0 dropped:0 overruns:0 frame:0
app_1 | TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
app_1 | collisions:0 txqueuelen:1
app_1 | RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
app_1 |
tmp_app_1 exited with code 0
The IPv6 address is not assigned.
I already tried:
--ipv6
--ipv6 --fixed-cidr-v6="2001:3984:3989::/64"
docker run -it busybox ifconfig
actually gives me an IPv6 address here (from the --fixed-cidr
subnet which is assigned to the default bridge
network)No success. Any ideas?
Upvotes: 12
Views: 43840
Reputation: 4373
Add (3) directives in your docker-compose.yml
file, (1) to daemon.json then re-build your containers and drop the Docker host's SLAAC addressed interface onto the docker-compose bridge and the container will itself receive an IPV6 SLAAC address.
This solution is demonstrated to be compatible with:
If you don't know how to achieve the above read the longer answer below. It's actually not very difficult or time consuming.
(Feel free to skip this intro- just context on the problems I'm trying to solve).
Like others visiting this question, I too have bumped-up against the issues of IPv6 networking in docker-compose. From what I could see certain IPV6 directives only worked with much older docker-compose file versions. And this could have knock-ons in respect to newer directives not being supported in the older docker-compose file versions I guess. And some of the solutions wouldn't work with swarm.
The only way many folks seemed to be able to get IPV6 connectivity working in their docker-compose configs was to use "IPV6 NAT" that some frustrated Docker user coded. That's not a criticism BTW: we need folks that will not be defeated who doggedly find ways around problems/limitations. But IPv6 was supposed to solve the problem of NAT'ing ;-)
I thought: There has to be an easier way!
And there was...
I'll describe my setup to enable comparative analysis if you run into difficulties:
MikroTik router configured for IPv6 SLAAC addressing which is connected to a dual-stack IPV4/V6 switch.
A Raspberry Pi 4 running 64bit Ubuntu 20.04 LTS connected to the switch via eth0 from which it gains its' IPv6 Global Unicast Address ("GUA") from the router.
Docker version used = Docker Engine Community v. 20.10.11
docker-compose = v. 2.1.1
docker-compose file format = v. 3.9
docker-compose.yml
My networks
section:
networks:
my-custom-network:
name: my-custom-network
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 192.168.XX.0/24
gateway: 192.168.xx.1
Note that the only IPv6-specific directive is just enable_ipv6: true
Next, the relevant part of my docker-compose.yml
file containing the other (2) IPv6-specific directives in the services
section for the container I want to IPV6 address is:
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.eth0.proxy_ndp=1
Obviously being YAML, take care to drop that part in with the correct leading spaces or it will puke misleading errors when the only problems is the indenting of the directives.
/etc/docker/daemon.json
I added just (1) IPv6 specific directive here:
"ipv6": true, "fixed-cidr-v6": "2001:470:1d3f:8::/64",
This step is necessary to assign IPv6 globally routable IPv6 addresses to our containers.
Finally, cut a fresh set of containers (but don't start them yet) after you're done tweaking:
docker-compose build --no-cache
Validate the IPv6 config of the router is righteous before doing the IPv6 Docker config by pinging something with ping6
from your Docker host:
ping6 ipv6.google.com
If response is returned successfully, it establishes that both the Docker host & router can resolve and route IPv6 packets. The problem is now reduced to just getting the container IPV6 addressed.
Locate the docker-compose bridge name "br-series-of-random-chars":
ip addr list
Add eth0 to bridge:
ip link set dev eth0 master br-ckkde30ff0g
NOTE: The above command is NON-Persistent- it won't survive reboot. The process of adding eth0 could be completely automated..
Check eth0 is now joined:
ip link | grep "master br-ckkde30ff0g"
Start your containers:
docker-compose start
Verify the container now as an IPv6 GUA:
docker exec -it containerName bash
and then:
hostname -I
You should see a SLAAC configured IPv6 GUA address now.
What you- thankfully- WON'T see: Any other containers receiving IPv6 GUA addresses.
Only the containers with those above sysctls
directives included in their configuration will receive an SLAAC IPv6 address- no others. In my case, I only wanted to expose the proxy container in front of a WordPress site, not the other containers, a webserver & backing database. So ONLY the proxy is reachable via IPv6.
The below site is a 100% docker-compose contraption configured using the above process, so the procedures outlined here can be demonstrated to work correctly:
http://[2001:470:1d3f:8:42:c0ff:fea8:1504]/
PLEASE NOTE: I'm changing ISP's next week, so might be some down-time while the new link is configured.
You can also validate the IPV6 config for a container's IPv6 addressing using an IPv6 Testing site:
https://ipv6-test.com/validate.php
If the AAAA DNS record is set for the bare domain- domain.com- then enter this as the url in the checker.
If the AAAA record is set for the subdomain www then enter www.domain.com into the checker.
That's it: just (3) IPv6-specific directives in docker-compose
, (1) in daemon.json
, some bridging and a properly IPv6 configured router. Done. And no NATing required.
Again, not a perfect, nor ideal solution, but it's another way of getting round the IPv6 connectivity issues. if I've missed a step out somewhere please ping me a comment.
Upvotes: 5
Reputation: 5362
Yes. Docker compose supports IPv6 protocol and it was introduced into docker engine 1.5 onward. There is still issue with latest compose file format 3.3 so you could use the 2.1 format. Still docker swarm is not mature enough with advance networking configuration and it doesn't support IPv6, hence it is not included under 3.3 fil format. Here is sample example of File,
docker-compose.yml
version: ‘2.1’
services:
app:
image: busybox
command: ping www.google.com
networks:
app_net:
ipv6_address: 2001:3200:3200::20
networks:
app_net:
enable_ipv6: true
driver: bridge
ipam:
driver: default
config:
- subnet: 2001:3200:3200::/64
gateway: 2001:3200:3200::1
This docker compose file will create a new network called testping_app_net based on IPv6 network under the subnet 2001:3200:3200::/64 and container should get IPv6 address automatically assigned.
Let us bring up services using docker-compose up and see if the services communicates over IPv6 protocol:
docker-compose up -d
and you could verify the IPv6 address for each container using,
docker exec -it 905 ip addr
You will see that a new container gets IPv6 address – 2001:3200:3200::20 and hence they are able to communicate with each other.
Note : If you want to enable IPv6 on host machine, which by default uses IPv4 address you need to add these two line into the daemon.json under /etc/docker directory:
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
and restart the docker daemon by command:
$ sudo systemctl restart docker
Upvotes: 6
Reputation: 1880
It turns out this is indeed a docker-compose bug that is going to be fixed in 1.9.0.
Meanwhile, there is a workaround by creating a custom network with the docker network
command:
docker network create --subnet=172.16.2.0/24 --gateway=172.16.2.1 --ipv6 --subnet=<myV6Network/subnet> dockerbridge
... which can then be made available inside docker-composed.yml
by writing
networks:
dockerbridge:
external:
name: dockerbridge
Upvotes: 8