Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
IPv6 Support #2974
Uses an automatically generated ULA range for the bridge and guests.
No IP6Tables support (is it really necessary since IPv6 does not use NAT?) but I've tested the binary and confirmed that routing works just fine between the containers and host - do note that ULAs are not globally routable so IPv6 internet access is not possible as of yet.
There is some duplicated code for the IPv4-IPv6 decision trees - it seemed unavoidable, especially considering how strict Go seems to be about variable scope within if statements and the like.
All comments, criticism and ideas welcome; this is my first foray into Go, after all!
We'll also want to be careful with this that we don't suddenly put a container internet-facing now that the links feature is in and implies that only host connections or explicit links define valid paths into the container. (Don't accidentally want redis to be internet accessible. :D)
As long as we keep that in mind, I'm all for IPv6 support!
Thanks, pnasrat, I'll heed the advice and make amendments as appropriate ASAP!
tianon: I don't think that's really a worry for this particular implementation - ULA addresses are totally unroutable on the internet. A user has to utilize radvd or a similar service to provide router advertisements so containers can reach outside of the private network and configure their kernel to accept such advertisements. Since there's no such thing as NAT in IPv6, this comes as close to a safe default 'local network configuration' as possible :)
@cvlc is there a chance that you could write about how it works in
I'm hoping that what you write will teach me something about ipv6 :)
I have a rough, work-in-progress branch that has master as of a week ago merged in with @cvlc's branch. If my notes are correct the last things that need ported/written are requesting IPv6 addresses in
Majority of @cvlc's code just needed moved to the 'networkdriver' package and have their tests updated. For new stuff I tried my best to add IPv6 support to existing methods without breaking the API. In cases where I couldn't (or didn't initially know how to) I made a new function that indicated it was for IPv6 just like this original PR did. The one exception is
I intentionally haven't squashed my commits yet in case someone wanted to cherry-pick any of them.
added a commit
this pull request
Feb 18, 2014
@vieux No promises but hoping to have this knocked out by next week if time permits. Doing some testing with it now and finding/fixing bugs as I go along. After that I'll take a run through the code and make sure there are adequate tests in place around the new stuff, write some docs, and then create a pull request.
@vieux Hey sorry for the lack of updates. My life/work commitments took up more time than I expected. I should start having time to jump back into this again.
To bring everyone back up to speed, my branch has the basic IPv6 support outlined in the original branch working as far as I could tell. The part I was working on before I had to stop was getting ip6tables/IPv6 NAT support working on kernels that supported it. If that functionality is not a concern at the moment I could probably get something pushed up relatively quickly. Thoughts?
I found some time this weekend to start poking at this again since expanding the scope with the IPv6 NAT stuff. I need to implement IPv6 support with Docker Links, fix a portion of my code in pkg/iptables to not use the Docker core
@shykes Sounds good. Unfortunately I was trying to balance too many things at once when I started work on this. I'd like to try and pick it back up at some point.
@tmartinx I haven't tried it myself but I think what @cvlc outlined in comment #2 of this thread should work. If you ran something like "radvd" on the host and attached it to the docker0 bridge, your containers should get IPv6 addresses if they're configured to handle router advertisements. Again, I haven't tried this myself so it may not work like I expect.
And while I agree that we don't need IPv6 NAT due to address allocations running out, we still need NAT to perform the port mappings between the host and the container just like we do now with IPv4. The IPv6 addresses that are generated/assigned are Unique Local Addresses as defined in RFC4193 and therefore are not publicly routable. This means you also need masquerade support to reach the public IPv6 internet from those containers.
I've been going with the assumption that the IPv6 support should match that of IPv4, but maybe this is a good time to get clarification from the Docker team on what their vision for this feature is. What is the expected experience for users wanting to use IPv6 on their containers? For example should a user be able to map IPv6 ports the same way ports are currently mapped with IPv4? Will we ever want to give containers public IPv6 addresses or should we only be assigning private addresses? Etc.
Hey Andrew, tks for your answers!
On 7 May 2014 22:07, Andrew Williams email@example.com wrote:
My radvd contains:
Enable RA on this gateway:
Disable clients from getting their IPs from DHCPv6 (no need for it):
Disable clients from getting other configs from DHCPv6:
Enable RA to the following subnet
Ubuntu IPv6 clients requires the package rdnssd to deal with RDNSS (Not
required for Docker containers if the host have it under its
All Docker containers have now IPv6 automatically... =D
docker.io run --privileged -t -i tmartinx/ubuntu-14.04-server-cloudimg
But, lots of times I need a fixed IPv6 address based on MAC / SLAAC, so,
docker.io run --privileged
And while I agree that we don't need IPv6 NAT due to address allocations
I'm pretty sure I'll never use NAT66. IPv6 is already working smoothly, no
BTW, I see that lots of suites/appliances provides NAT44 as a "solution" to
The Internet should be routed, not NATed... I think that it works much
But, nevertheless, people must have the option to enable / disable this
I've been going with the assumption that the IPv6 support should match that
What is the expected experience for users wanting to use IPv6 on their
For example should a user be able to map IPv6 ports the same way ports are
Will we ever want to give containers public IPv6 addresses or should we
I'll use private IPv6 address only, and only if, that subnet will remain
So, I truly believe that NAT66 support in Docker can wait a bit more and
Please, forgive me if I'm being rude, that is not my intention... E-mail is
+1 for IPv6 support (no NAT, with IPv6 you don't need NAT anymore)
I'd be looking forward to be able to route a static address into a container without workarounds like custom lxc configs or static mac addresses. Unfortunately I don't know Go, so I can't help with the code, but I'm willing to help with testing and stuff like that
I would like to vote +1000 for this! I'll not be able to use Docker until
Also, a bit off-topic but, OpenvSwitch support is a must to have!
I'm planning to use Docker with OpenStack and, of course, with IPv6...
On 23 June 2014 19:13, niclashoyer firstname.lastname@example.org wrote:
To add to this discussion - it's my understanding that port forwarding/NAT66 is used with Docker only to conserve IP addresses, something totally unnecessary with IPv6. Then again, there are security implications for non-IPv6 aware users if all containers are given a publicly-routable IPv6 address without any firewall or other network-level controls.
As a happy middle ground, I'd suggest assigning each Docker container a unique IPv6 address. To provide the closest parallel to the expected IPv4 behaviour, I'd further suggest a ULA (unique local address) for each container provided by the Docker service in the same way that it provisions IPv4 local addresses. The alternative is to not assign addresses at all, but this will mean effectively nothing has changed (radvd or similar will need to be used).
Of course, users would still need to use radvd or a similar daemon if they want their Docker containers to become publicly routable - It'll be fairly easy to work out documentation for this. It's entirely possible to have multiple IPv6 and IPv4 addresses on a single interface simultaneously, this will permit local communication with other containers and the host through their ULA addresses.
All outgoing internet traffic will continue to go over IPv4/NAT and each container's network namespace can be firewalled via ip6tables to only allow traffic from other containers to specific ports.
I'd love to hear others' thoughts on this approach! I was considering picking this up again but I'm reluctant to invest the time without confirmation that I'm going the right way about it for Docker.
I think there should be options for both and we should select a reasonable default, e.g.
The default way (no IPv6), just IPv4 port mapping:
IPv6 local (assign a link-local address to the docker container. Could be default, too):
IPv6 public (Assign a public IPv6 address if there is a public subnet available on the host. Shouldn't be default):
And mixing the arguments shouldn't be a problem:
edit: I don't like the radvd approach, because that requires containers running in privileged mode at the moment, which is quite heavy.
IPv6 link-local addresses should be added regardless according to spec, I'd probably have --ipv6 allocate a ULA (good enough for inter-container communication on the same host or sub/net). I wouldn't add routable addresses via the Docker address provisioner since that's not done with IPv4. To keep the behaviour as similar as possible, I'd try to fix the issue with radvd or use DNSMasq as a SLAAC or DHCPv6 server!
You're right that it is not done with IPv4, but the problem with IPv4 is that we simply don't have enough free addresses to add them as public routable. I'd also be happy if a simple radvd configuration could provide the same (if there is good documentation), but having to start every container with
great! If there is a way to automate the assignment of an IPv6 address after container startup without privileged mode I'd also be happy with that. Is there any documentation for that scenario?
For some background, the reason I was working on the NAT66 support was so that containers with IPv6 addresses could hit the public IPv6 internet just as containers with NAT'd IPv4 addresses could. Basically I was just trying to match the current behavior. Also, so far in my experience all of the cloud providers that offer public IPv6 connectivity do it by handing you a single IPv6 address, not a subnet for SLAAC.
I started looking back at this again last week and I don't think it'd be too difficult to rip out the IPtables stuff. It'll likely be more time consuming to merge with 1.0 code base. I'll also be at Velocity this week if anyone is here and wants to discuss in person.
@TheDude05 I know that OVH and online provide /48s or /64s, SixxS also provide public-routable subnets for free if you have a good reason for one, though additional configuration will be required as they're tunnelled via IPv4.
NAT66 isn't ideal, but perhaps the reality is that it'd be more immediately useful to dual-stack users. I do understand why you chose that approach, @TheDude05 - somebody certainly needs to make the call! The problem is that it's not likely going to work very well for an IPv6 user's imagined use case and won't allow Docker it's full scaling capabilities, adding native IPv6 support is a Big Thing in terms of future potential, especially when scaled to thousands of microservices across a large platform. I do like your plugin idea, @niclashoyer!
Agreed! Address allocation using autoconf with radvd (or similar) is the way to go. If you know what IPv6 prefix is being advertised to your containers and you know each container's MAC, then you have all the information you need for the IP. #4033 relates to this question.
This, or they provision a /64 'on link' which means you then have to bridge
Was able to rip out all of the IPv6 IPtables/Portmapper code from my branch below. Note that this was based on master of 0.8 so I'll still need to do some work on making this work with master as of today
I went ahead and squashed all of my commits and put up a new PR here: #6923
Note that if you want to see the original commit log pre-squash you can have a look at this branch: https://github.com/TheDude05/docker/compare/ipv6_no_nat_pre_merge
@tianon Yes it should just be a matter of rebasing/merging master but because of the extent of the changes that happened between 0.8 and 1.0 a simple rebase/merge wont suffice. Several files were moved/deleted and libcontainer was added since work was done on this branch. Also, we should determine how we want to deal with links if a user has disabled ICC and wants to talk over IPv6.
I signed my squashed commit with the Docker DCO so there shouldn't be any legal issues if someone wants to take my branch and continue work on it.
referenced this pull request
Jul 11, 2014
I have been looking into how to contribute code because I really think IPv6 is important and was quite disappointed it was not in from the beginning. to be a little extremist, Docker could have skipped IPv4 entirely by assigning IPv6 link-local addresses to each container (instead of 172.x.x.x.) and then doing to port mapping to the host as external eth to that IPv6 link-local address. If the user wanted IPv4 then the host external eth would be IPv4 and the port would be pipped through to the container as it currently is. ie
This could be taken further and have the 1111:2222:3333 component of the IPv6 address be set to the containerID (the D0C0 part of the address could be used as an indicator of a docker address).
If the container was to be exposed to the world then all you would need to do is use the IPv6 Router Advertisement to set the first 64bits (as with normal IPv6 auto conf) and use the host forward IP routing to expose the container.
This would also make it easier for those wanting to go directly out a physical interface from the container which I have seen some people do and graph the performance advantage.
The expose ports settings could then be used to just set firewall open ports if security is a concern.
PS I am only a basic level programmer, have not programmed in GO before and don't know anything about how docker is coded but I would really like to help with this feature. I do pretty good documentation and could offer use-case testing.