Skip to content

Feature request: IPv6-enabled embedded DNS server #41651

Closed

Description

@enspritz

Feature request: Docker's embedded DNS server is available over IPv6 in addition to the already-existing IPv4. Docker includes the IPv6 address of its embedded DNS name server when generating a containers /etc/resolv.conf.
Following the running example from below, the file's contents would be:

nameserver 127.0.0.11      # Docker's embedded DNS server, accessible over IPv4
nameserver fedc::1         # Docker's embedded DNS server, accessible over IPv6
options ndots:0

Of course, the actual local IPv6 address needs determining.

Background: Docker's embedded DNS server is hard-coded to be available at 127.0.0.11 over IPv4 only. This fact is encoded into containers' generated /etc/resolv.conf files. In our environments, the Docker daemon is configured in /etc/docker/daemon.json with the ISP's upstream IPv4 and IPv6 nameserver addresses. When Docker generates /etc/resolv.conf for a new container, the contents becomes:

nameserver 127.0.0.11      # Docker's embedded DNS server, accessible over IPv4
nameserver 2a00:0123::1    # Upstream ISP name server, accessible over IPv6
options ndots:0

Crucially, notice that the IPv4 nameserver is Docker's embedded DNS server, and that the IPv6 nameserver points to the ISP's upstream server. (Clarifying commentary trailing the nameserver directives was added by me.) This state of affairs causes sporadic run-time faults when resolving the IP addresses of peer containers by their names.

Discussion: When an Alpine container attempts to resolve the IP address by the name of one of its peer containers, Alpine's MUSL performs parallel requests, sending A and AAAA queries over UDP to each of the configured nameservers all at once, and taking the first response.

Thus, when for example Alpine container logic attempts to connect to container db, the software first attempts to resolve the hostname db into an IP address in order to connect to it. MUSL does this by sending out a total of 4 queries in parallel, based on the above /etc/resolv.conf:

  1. UDP request over IPv4 to Docker's embedded DNS server for the A record for db.. The Docker daemon is of course authoritative for db. and responds with its IP address.
  2. UDP request over IPv4 to Docker's embedded DNS server for the AAAA record for db.. Again, Docker responds affirmatively.
  3. UDP request over IPv6 to the ISP's nameserver for the A record for db.. Obviously the ISP is oblivious as to a host named db. run by one of its customers in a privacy-concealing environment; it returns NXDOMAIN.
  4. UDP request over IPv6 to the ISP's nameserver for the AAAA record for db.. Again, the ISP returns NXDOMAIN.

You can observe this using tcpdump -i any -n port 53 & followed by ping db -c 1 in a container setup on a bridge network with IPv6 enabled.

Now, due to network latency and myriad other reasons, the logic container receives Docker's IPv4-based embedded DNS responses generally before those of the ISP's IPv6 responses. Name resolution succeeds according to MUSL, and processing continues down its happy path. But every now and then the ISP's response packets arrive before those of Docker, and MUSL blissfully accepts the NXDOMAIN responses and reports name resolution failure back up to the software, ultimately causing a processing fault.

If Docker offered it's embedded DNS server over IPv6 as a first-class citizen alongside IPv4, name resolution would function properly.

Our usage environment:

  • Docker version 19.03.13.
  • Containers connected to custom bridge network with IPv6 enabled.
  • Plenty of containers are based on Alpine Linux, whose MUSL performs DNS name resolutions by making parallel requests, one to each configured nameserver; this is MUSLs only mode of operation.
  • Some services are at various stages of being IPv6 native (can only be resolved and accessed using IPv6).
  • /etc/docker/daemon.json specifically configures the Docker daemon with the ISP's upstream DNS servers according to location:
{
  "dns": [
    "123.4.5.6",    # IPv4 address of the ISP's DNS server
    "2a00:0123::1"  # IPv6 address of the ISP's DNS server
  ],
  ...
}

Cheers!

Activity

  1. snowsnoot commented on Dec 14, 2021

    @snowsnoot

    Pretty surprising Docker claims to support IPv6 in 2021 without supporting IPv6 on the embedded DNS server. This causes issues on my user-defined network as the containers are unable to resolve their internal hostnames on the upstream IPv6 DNS server.

  2. cnb2412 commented on Jan 18, 2022

    @cnb2412

    This causes issues on my user-defined network as the containers are unable to resolve their internal hostnames on the upstream IPv6 DNS server.

    Running into this very issue on an IPv6-only Server. Having a method to configure the embedded DNS to resolve queries via IPv6 would really be helpful.

  3. added
    kind/featureFunctionality or other elements that the project doesn't currently have. Features are new and shiny
    on Mar 10, 2023
  4. g00g1 commented on Mar 10, 2023

    @g00g1

    I am using dual-stack networking for containers and running into the same issue.

    The only workaround I could imagine is creating firewall rule to block any 53/udp communications for IPv6 prefixes used by Docker containers, which obviously is too bad but solves my issue.

    +1 for possibility to configure embedded DNS for IPv6 network.

  5. cleverer commented on Apr 9, 2023

    @cleverer

    Wow just found this issue. I have been running a fully dual-stack docker-compose based server, and this explains a lot of random errors. Absolutely mind-boggling how this doesn't work out of the box… makes any docker-compose based dual-stack deployment basically useless.

  6. akerouanton commented on Apr 10, 2023

    @akerouanton
    Member

    Hi, after looking at the code I think we can solve this issue without making docker embedded DNS resolver available through IPv6, at least for now.

    Currently, docker doesn't treat IPv4 and IPv6 --dns addresses the same way. If you specify IPv4 --dns addresses, the embedded DNS resolver use them to forward queries for unknown entries. If you specify IPv6 --dns addresses, the embedded DNS resolver ignores them and they end up in your containers' /etc/resolv.conf.

    This weird behavior is a vestige of the time when IPv6 support was absolutely absent from Docker. I have a patch ready for treating IPv6 --dns addresses like IPv4 and I believe it works properly. I'll test it tomorrow and send a PR if it's conclusive.

    As for why the local embedded DNS server would take more time than a roundtrip to your ISP's IPv6 DNS, there're actually multiple plausible explainations: garbage collection, many concurrent DNS queries happening at the same time, libnetwork's controller being locked, etc... For the last two explainations, I think we can/will improve that.

    On the feature request itself, kind seems to require it for IPv6-only clusters. So we'll have to support this feature at some point, but that's surely more work and I'm not sure yet when that will happen.

  7. spinda commented on May 2, 2023

    @spinda

    @akerouanton Did that patch end up working out? Just ran into this today.

  8. simonwiles commented on Sep 25, 2023

    @simonwiles

    Is there any solution to this issue at present? My dual-stack docker compose set up is just failing to resolve internal names seemingly at random because of this issue, and I'd really like to do something about it!

  9. jdannenberg commented on Sep 25, 2023

    @jdannenberg

    Is there any solution to this issue at present? My dual-stack docker compose set up is just failing to resolve internal names seemingly at random because of this issue, and I'd really like to do something about it!

    Do you really want to hear my workaround?

    Based on the very useful information

    When an Alpine container attempts to resolve the IP address by the name of one of its peer containers, Alpine's MUSL performs parallel requests, sending A and AAAA queries over UDP to each of the configured nameservers all at once, and taking the first response.

    I just changed every service to not use an alpine-based image. E.g. for zabbix I changed to the ubuntu flavoured / based image.

  10. simonwiles commented on Sep 25, 2023

    @simonwiles

    Thanks :) I don't have that option easily and immediately available to me, so I'll probably go with something a bit hacky for now; would be great to know if this will be properly fixed at some point, though!

  11. cleverer commented on Feb 14, 2024

    @cleverer

    @akerouanton also wondering if your patch did go anywhere.Mmy docker-compose based setup has several services constantly flapping, as they can't resolve the linked containers (which are mostly the dbs). I'm really surprised to see the ipv6 nameservers still ending up in the resolv.conf.

    This is a huge oversight by docker imho… but also easily fixable by just not writing that line, no?

  12. cleverer commented on Mar 21, 2024

    @cleverer

    Looks like this has been finally (partially) been addressed in docker v26: #47512

    The host v6 dns is not mounted to the container anymore, so docker-network internal dns resolution should properly work for dual-stack setups.

  13. neersighted commented on Mar 21, 2024

    @neersighted
    Member

    I'm not sure what partially means as this should also work for single-stack setups; this issue should be resolved with v26.

  14. cleverer commented on Mar 21, 2024

    @cleverer

    I'm not sure what partially means as this should also work for single-stack setups; this issue should be resolved with v26.

    I think the expectation of the ticket would be that the embedded docker dns proxy is also available over ipv6 inside the container. For my use case, having only a IPv4 docker proxy inside the container is good enough, hence I called it partially addressed…

  15. neersighted commented on Mar 21, 2024

    @neersighted
    Member

    Ah; you're referring to IPv6-only inside the container network. I would say that's a different ticket, and would be a natural consequence of support for IPv6-only containers, which is not yet implemented. I think we should probably refer back to #44923, and split off a separate ticket only if we decide single-stack doesn't encompass that entire ticket.

  16. cleverer commented on Mar 21, 2024

    @cleverer

    Ah; you're referring to IPv6-only inside the container network. I would say that's a different ticket, and would be a natural consequence of support for IPv6-only containers, which is not yet implemented. I think we should probably refer back to #44923, and split off a separate ticket only if we decide single-stack doesn't encompass that entire ticket.

    Reading through the original issue description, I think this issue is precisely about making the dns server listen on IPv6 insider the container network. However I'm not aware of all the open issues and am fine with just having it as part of #44923, since I'm already very happy my main inconvenience has been resolved :)

  17. neersighted commented on Mar 21, 2024

    @neersighted
    Member

    The root cause of the issue was the race with the upstream server; one possible solution was a dual-stack listener, but not the only one, in my opinion.

    In any case, yeah, I'd rather have fewer issuers with a wider audience than many that are fragmented 👍

  18. thaJeztah commented on Mar 21, 2024

    @thaJeztah
    Member

    Following the discussion on #47442 (comment) (and comments below that), I'm not sure if and IPv6 loopback-only DNS (even for IPv6-only containers) will happen; at least it looks like there's some motivation there describing it may not be a realistic option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions