Why is DNS behaviour different in container vs container's network namespace?

I’ve set up a Docker container with the ubuntu image. I get different results when I curl from the Docker container than when I enter the container’s network namespace and try the same command. What’s taking place here?

# Set up the container
docker run -d -it --name mycontainer ubuntu
docker exec mycontainer apt update
docker exec mycontainer apt install -y curl

# Run curl
docker exec mycontainer curl http://yahoo.com
    # => redirect
PID=$(docker inspect -f '{{.State.Pid}}' mycontainer)
sudo nsenter -n -t $PID curl http://yahoo.com
    # => curl: (6) Could not resolve host: yahoo.com

Why is dns not working from the network namespace when it appears to work from the container? Likewise, I fail to get dns info when I nslookup or dig from the namespace but succeed when I do it from the container.

When in the network namespace, I can check the dns, and I get the same values as I do when checking from my host:

sudo nsenter -n -t $PID nmcli dev show | grep DNS
# => IP4.DNS[1]:                             208.76.152.1
# => IP4.DNS[2]:                             208.76.152.9
# => IP4.DNS[3]:                             192.168.68.1

I’m running Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1.

Network namespaces doesn’t mean that you get the network-related services like DNS. The DNS server’s IP address is in /etc/resolv.conf inside the container. Which is part of the filesystem, not the network namespace. The only thing you get with network namespace is the network interfaces so you could use “ping” to ping some external ip address or use curl with an IP address without domain name.

Of course, your host machine’s filesystem has its own /etc/resolv.conf but it is often a local IP address like 127.0.0.53 and the real, remote DNS server ip address is configured somewhere else.

Since you entered the container’s network namespace, 127.0.0.53 is a local IP address inside the container so your host will not get the request. If you change the DNS configuration on your host to contain an external IP address like one of the DNS server of Google (8.8.8.8) you can use curl http://yahoo.com from the network namespace of the container too.

1 Like

Thanks, rimelek. Your explanation makes sense. When I update my host’s /etc/resolv.conf file to include nameserver 8.8.8.8, the problem persists, but when I update it to include 127.0.0.11 (which is what the container’s /etc/resolv.conf file holds), then I can successfully execute my curl command in the container’s network namespace.

Have you any idea why this might be?

Here’s the docker inspect for my container (running ubuntu). I’ve set that container’s default route to point to this other container (running mitmproxy).

8.8.8.8 may not be allowed from your location. For example you are behind a company firewall which allows only the DNS server on LAN.

127.0.0.11 is the DNS server inside the container when you use user defined Docker networks. For example when you statr your containers with Docker Compose. This way you can use Docker’s DNS to use container names as domain names.

This is actually completely normal. I should have told you this before instead of telling you to use 8.8.8.8. So the point is to use the same DNS server address as your container would use. Since I didn’t remember what that IP address is and I could not check it then, I mentioned an address that I knew so you could try it.