My machine is on a private network with private DNS servers, and a private zone for DNS resolution. I can resolve hosts on this zone from my host machine, but I cannot resolve them from containers running on my host machine.
Host:
root@host:~# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.1.1
root@host:~# ping privatedomain.io
PING privatedomain.io (192.168.0.101) 56(84) bytes of data.
Container:
root@container:~# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 8.8.8.8
nameserver 8.8.4.4
root@container:~# ping privatedomain.io
ping: unknown host privatedomain.io
It's fairly obvious that Google's public DNS servers won't resolve my private DNS requests. I know I can force it with docker --dns 192.168.0.1
, or set DOCKER_OPTS="--dns 192.168.0.1"
in /etc/default/docker
, but my laptop frequently switches networks. It seems like there should be a systematic way of solving this problem.
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:
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:2 . Find your docker IP (in this case,
172.17.0.1
):3 . Create/edit
/etc/resolvconf/resolv.conf.d/tail
and add this line:4 . Restart networking, update
resolv.conf
, restart docker: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:
sudo rm /etc/resolv.conf sudo 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
sudo apt-get -y install dnsmasq
# 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
# systemd-resolvd name server nameserver 127.0.0.53 # docker host ip nameserver 172.17.0.1
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/
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.
2 . Find your docker IP (in this case, 172.17.0.1):
3 . Edit
/etc/dnsmasq.conf
and add these lines:4 . Create/edit
/etc/resolvconf/resolv.conf.d/tail
and add this line:5 . Restart networking, update
resolv.conf
, restart docker:Your containers will now be able to resolve DNS from whatever DNS servers the host machine is using.
It was enough for Ubuntu 18.04 LTS: