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 containers take DNS IPs from the host machine, which is managed by systemd-resolve . Those IPs themselves are the cloud provider's DNS.
DNS services conf configuration file. Containers that use the default bridge network get a copy of this file, whereas containers that use a custom network use Docker's embedded DNS server, which forwards external DNS lookups to the DNS servers configured on the host.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With