Konubinix' opinionated web of thoughts

Docker Looses the Dns Configuration

Fleeting

docker looses the connection a

Actually, the network stuff is still there, but the /etc/resolv.conf file is not.

Say I am running an alpine container while my host is connected to my home router.

docker run --rm -ti alpine
cat /etc/resolv.conf
nameserver 192.168.1.1

Which is exactly what I have on the host.

cat /etc/resolv.conf
nameserver 192.168.1.1

Now, suppose I close this connection and switch to usb connection shared of my phone.

Now, on the host

cat /etc/resolv.conf
nameserver 192.168.42.129

But on the docker container

cat /etc/resolv.conf
nameserver 192.168.1.1

Changing the value of the resolv.conf file is enough to get back to a working network in the container.

Now, this file is actually mounted in the container, as well as the hosts and the hostname file.

mount|grep /etc/
/dev/nvme0n1p2 on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro)
/dev/nvme0n1p2 on /etc/hostname type ext4 (rw,relatime,errors=remount-ro)
/dev/nvme0n1p2 on /etc/hosts type ext4 (rw,relatime,errors=remount-ro)

But I can see no information about how those mount point could be made dynamic.

I can find where those files are located using docker inspect.

d inspect 5ef|gi resolv.conf
        "ResolvConfPath": "/var/lib/docker/containers/5efa6cf6e44f7500a707592780cbbd2f2c872a0f6ecd120d9c0830a40ba99476/resolv.conf",
sudo cat /var/lib/docker/containers/5efa6cf6e44f7500a707592780cbbd2f2c872a0f6ecd120d9c0830a40ba99476/resolv.conf
nameserver 192.168.1.1

I can update this file from the host.

echo foobar | sudo tee /var/lib/docker/containers/5efa6cf6e44f7500a707592780cbbd2f2c872a0f6ecd120d9c0830a40ba99476/resolv.conf > /dev/null
docker exec 5ef cat /etc/resolv.conf
foobar

By default, containers inherit the DNS settings of the host, as defined in the /etc/resolv.conf configuration file. Containers that attach to the default bridge network receive a copy of this file

https://docs.docker.com/config/containers/container-networking/

Also, note that since the hosts is also generated, custom hosts are not propagated in the docker container.

Also, when using systemd-resolved, docker automatically copies the resolved dns at the time of the creation of the container to put it into the container. That does not make the resolution dynamic either (see how should systemd-resolved and docker interact?).

Docker provides an embedded dns that is used to deal with custom networks. It listens to 172.17.0.1:53.

There is a project that aims as replacing this embedded dns to make it work with the host systemd-resolved. I don’t plan to use systemd-resolved, so that won’t work for me.

Containers that attach to a custom network use Docker’s embedded DNS server. The embedded DNS server forwards external DNS lookups to the DNS servers configured on the host.

https://docs.docker.com/config/containers/container-networking/

The most obvious solution as of today appears to provide an external dns when creating docker containers.

That is not ideal, as most application I use, like earthly or k3d start docker themselves, so I need to find a way to use the --dns flag in each of them (and for instance earthly does not provide one now).

I can become quite hairy in some complicated scenarios. It happens that I need to run docker in kubertenes in docker. In that case, I would need to trick the outside and in the inside docker to make them resilient to connection changes.

Also, it makes the container able to use the external addresses, but not my local network managed by my router when I am plugged at home.

You can setup default dns servers in docker to mitigate this issue.

I could also run a command to update ALL the resolv.conf when /etc/resolv.conf changes.

Something like this

docker ps -q|while read hash
do
  docker cp /etc/resolv.conf 5efa6cf6e44f:/etc/resolv.conf
done

This won’t work, but that gives the idea. I still don’t like this idea.