Docker cannot resolve DNS on private network
For Ubuntu 18.04, and other systems that use systemd-resolved, it may be necessary to install dnsmasq and resolvconf. systemd-resolved is hard-coded to listen on 127.0.0.53, and Docker filters out any loopback address when reading resolv.conf.
1 . Install dnsmasq and resolvconf.
sudo apt update
sudo apt install dnsmasq resolvconf
2 . Find your docker IP (in this case, 172.17.0.1):
root@host:~# ifconfig | grep -A2 docker0
docker0 Link encap:Ethernet HWaddr 02:42:bb:b4:4a:50
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
3 . Edit /etc/dnsmasq.conf
and add these lines:
interface=docker0
bind-interfaces
listen-address=172.17.0.1
4 . Create/edit /etc/resolvconf/resolv.conf.d/tail
and add this line:
nameserver 172.17.0.1
5 . Restart networking, update resolv.conf
, restart docker:
sudo service network-manager restart
sudo resolvconf -u
sudo service dnsmasq restart
sudo service docker restart
Your containers will now be able to resolve DNS from whatever DNS servers the host machine is using.
My case with many images from docker hub (nodered, syncthing and another):
- container is running under not-root user
- /etc/resolv.conf inside container has permissions 600 and owned by root
So my solution is very simple
root@container:~# chmod 644 /etc/resolv.conf
Profit! :))
Docker populates /etc/resolv.conf
by copying the host's /etc/resolv.conf
, and filtering out any local nameservers such as 127.0.1.1. If there are no nameservers left after that, Docker will add Google's public DNS servers (8.8.8.8 and 8.8.4.4).
According to the Docker documentation:
Note: If you need access to a host’s localhost resolver, you must modify your DNS service on the host to listen on a non-localhost address that is reachable from within the container.
The DNS service on the host is dnsmasq, so if you make dnsmasq listen on your docker IP and add that to resolv.conf, docker will configure the containers to use that as the nameserver.
1 . Create/edit /etc/dnsmasq.conf
† and add these lines:
interface=lo
interface=docker0
2 . Find your docker IP (in this case, 172.17.0.1
):
root@host:~# ifconfig | grep -A2 docker0
docker0 Link encap:Ethernet HWaddr 02:42:bb:b4:4a:50
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
3 . Create/edit /etc/resolvconf/resolv.conf.d/tail
and add this line:
nameserver 172.17.0.1
4 . Restart networking, update resolv.conf
, restart docker:
sudo service network-manager restart
sudo resolvconf -u
sudo service docker restart
Your containers will now be able to resolve DNS from whatever DNS servers the host machine is using.
† The path may be /etc/dnsmasq.conf
, /etc/dnsmasq.conf.d/docker.conf
, /etc/NetworkManager/dnsmasq.conf
, or /etc/NetworkManager/dnsmasq.d/docker.conf
depending on your system and personal preferences.
As you know, Docker copy host /etc/resolv.conf file to containers but removing any local nameserver.
My solution to this problem is to keep using systemd-resolvd and NetworkManager but add dnsmasq and use it to "forward" Docker containers DNS queries to systemd-resolvd.
Step by step guide:
- Make /etc/resolv.conf a "real" file
sudo rm /etc/resolv.conf sudo touch /etc/resolv.conf
- Create file /etc/NetworkManager/conf.d/systemd-resolved-for-docker.conf to tell NetworkManager to inform systemd-resolvd but to not touch /etc/resolv.conf
[main] # NetworkManager will push the DNS configuration to systemd-resolved dns=systemd-resolved # NetworkManager won’t ever write anything to /etc/resolv.conf rc-manager=unmanaged
- Install dnsmasq
sudo apt-get -y install dnsmasq
- Configure dnsmasq in /etc/dnsmasq.conf for listening DNS queries comming from Docker and using systemd-resolvd name server
# Use interface docker0 interface=docker0 # Explicitly specify the address to listen on listen-address=172.17.0.1 # Looks like docker0 interface is not available when dnsmasq service starts so it fails. This option makes dynamically created interfaces work in the same way as the default. bind-dynamic # Set systemd-resolved DNS server server=127.0.0.53
- Edit /etc/resolv.conf to use systemd-resolvd nameserver (127.0.0.53) and the host IP (172.17.0.1) in Docker network
# systemd-resolvd name server nameserver 127.0.0.53 # docker host ip nameserver 172.17.0.1
- Restart services
sudo service network-manager restart sudo service dnsmasq restart sudo service docker restart
For more info see my post (in spanish) https://rubensa.wordpress.com/2020/02/07/docker-no-usa-los-mismos-dns-que-el-host/