4

This section specifies that a Docker container gets a copy of the host's /etc/resolv.conf. However, when i run a simple container on Fedora 34, i get a different result:

$ cat /etc/resolv.conf
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
# Do not edit.

...

nameserver 127.0.0.53
options edns0 trust-ad
search .
$ docker run --rm -it alpine /bin/sh

/ # cat /etc/resolv.conf 
# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).
# Do not edit.

...

nameserver 192.168.0.1
nameserver 192.168.0.2
search .

The docker container got nameservers of my primary interface maintained by systemd-resolved:

$ resolvectl dns enp1s0
Link 2 (enp1s0): 192.168.0.1 192.168.0.2

This works when i want to access the Internet. But does this mean that Docker somehow integrates with systemd-resolved?

Furthermore, i found that there's a problem with running containers requiring my corporate VPN connection. As i understand, DNS requests go straight to my router (192.168.0.*) and not to the virtual interface set up by the VPN. I solved it somewhat artificially by adding --dns 127.0.0.53 --network host flags to the docker run command.

It won't work with just the --dns flag. Why is the host networking mode necessary? After all, 192.168.0.1 and 192.168.0.2 are not in the container's network either and they work?

Lastly, i found this repository which seems to address the problem but i don't quite get how it works. Could someone describe the matter more broadly?

1
  • Please don’t ask too many questions at once.
    – Daniel B
    Jan 29, 2022 at 22:01

1 Answer 1

4

Yes, Docker certainly does “integrate” with systemd-resolved: By detecting 127.0.0.53 and then not using it. You can see the relevant code here:

        if len(ns) == 1 && ns[0] == "127.0.0.53" {
            pathAfterSystemdDetection = alternatePath
            logrus.Infof("detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: %s", alternatePath)
        }

Docker then uses /run/systemd/resolve/resolv.conf, which is the non-stub-resolver file that systemd-resolved manages. If your DNS client properly integrates with systemd-resolved, its DNS servers should also show up in this file, but only while the connection is active.


Why does it not work without --network host? Because addresses within 127.0.0.0/8 are only reachable on the same host (or, more accurately: network namespace). This is a critical security feature. Inside a different network namespace, 127.0.0.0/8 refers to the localhost in this namespace only. Different hosts are accessible like normal using Docker’s default NAT network.


The project you found is, in simple terms, a DNS resolver. So basically the same as systemd-resolved, except it’s programmed to listen on the Docker default bridge. The requests are delegated to systemd-resolved. In reality, it does some more stuff like resolving container names and whatnot.

4
  • it’s programmed to listen on the Docker default bridge : Just to clarify that point, you mean it's listening on port 53 of the host's docker0 interface?
    – yakom
    Jan 29, 2022 at 23:28
  • 1
    Yes, exactly. Though it does not rely on the name but instead queries Docker for it.
    – Daniel B
    Jan 30, 2022 at 17:41
  • Is this documented in more detail anywhere? Because it doesn't appear to work for me: I get 8.8.8.8 in my container's resolv.conf instead and that DNS server is blocked.
    – cdleonard
    Jun 11, 2022 at 17:38
  • @cdleonard Is what documented? If you get an unexpected resolv.conf in your containers, you could always turn up the Docker log verbosity to get a better grasp of what’s going on.
    – Daniel B
    Jun 12, 2022 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.