Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker: container can't find domain on private network

I'm trying to figure out a problem with identical docker containers being run on different hosts, where one container can find/ping/nslookup a domain on a private network, and another can't. One host is OSX 10.11, the other is Ubuntu 16.04. Both are running docker 1.12. I'm using docker-compose to bring up my application, and I'm hoping to figure out what is going on and how to fix it, or some configuration changes I could make without resorting to hardcoding domains or ip addresses that would make the container behave the same on both hosts.

On my OSX box, I have the following dns nameservers set automatically by my domain:

osx:$ cat /etc/resolv.conf
domain redacted.lan
nameserver 172.16.20.19
nameserver 10.43.0.11

I'm aware that resolv.conf isn't used by most OSX tools, but System Preferences > Network shows the same settings.

I have similar settings on my Ubuntu 16 box as well (command from https://askubuntu.com/questions/152593/command-line-to-list-dns-servers-used-by-my-system):

ubu:$ cat /etc/resolv.conf 
nameserver 127.0.1.1
search redacted.lan

ubu:$ nmcli device show eno1 | grep IP4.DNS
IP4.DNS[1]:                             172.16.20.19
IP4.DNS[2]:                             10.43.0.11

Then, on both OSX and Ubuntu, I start my container with this:

$ docker run -it redacted_web bash

And then I run these commands to diagnose my problem:

$ apt-get update
$ apt-get install -y dnsutils
$ cat /etc/resolv.conf
$ nslookup redacted.lan

On OSX, the output from the last 2 commands is:

root@d19f49322fda:/app# cat /etc/resolv.conf
search local
nameserver 192.168.65.1
root@d19f49322fda:/app# nslookup redacted.lan
Server:     192.168.65.1
Address:    192.168.65.1#53

Name:   redacted.lan
Address: 172.18.0.23

On Ubuntu, the output is:

root@91e82d652e07:/app# 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
search redacted.lan

nameserver 8.8.8.8
nameserver 8.8.4.4
root@91e82d652e07:/app# nslookup redacted.lan 
Server:     8.8.8.8
Address:    8.8.8.8#53

** server can't find redacted.lan: NXDOMAIN

Possible differences I can think of:

  • On OSX there is a vm running docker, where as on ubuntu it's native
  • On Ubuntu, docker is run with sudo, possibly picking up different configuration settings
like image 319
davethegr8 Avatar asked Oct 20 '25 11:10

davethegr8


2 Answers

Updated Answer (2017-06-20)

Newer versions of Ubuntu (17.04+) don't use dnsmasq (it now uses systemd-resolved). You'll run into a similar problem with host resolution, but the original solution here no longer works. In fact, Docker containers can't even communicate with systemd-resolvd because it's running its own DNS in a location that's unreachable from within a container.

A good solution on newer versions of Ubuntu is to put the following configuration in /etc/docker/daemon.json (create this file if it doesn't exist):

{
    "dns": ["172.16.20.19", "10.43.0.11"],
    "dns-search": ["redacted.lan"]
}

This allows you to configure the DNS servers and search domains. The DNS IPs above are from the original question, but you can use your own custom ones too. You probably want to match the DNS config on your host machine. Search domain is optional, and you could entirely omit that line (careful with your commas!). Again, you probably want to match your host machine.

Essentially, what these daemon.json options do, is automatically inject the DNS config and search domain into the config files inside the container for any container that is started on that daemon. This is necessary because you cannot use systemd-resolved from the host to resolve DNS within the container due to limitations of the way systemd-resolved works. The docs are here and here.


Original Answer

The problem is that the host is using dnsmasq to resolve the private IP and Docker is not using dnsmasq on the host.

The simple fix is to turn off dnsmasq on the host machine.

  1. Run sudo vi /etc/NetworkManager/NetworkManager.conf
  2. Comment out this line: #dns=dnsmasq
  3. Run sudo service network-manager restart

Now, you should be able to use the docker container and it will resolve your private DNS correctly.

like image 89
mkasberg Avatar answered Oct 24 '25 05:10

mkasberg


Check your startup scripts for the docker daemon, it includes the following option to adjust the DNS used when creating containers:

$ dockerd --help
# ...
  --dns=[]                                 DNS server to use
  --dns-opt=[]                             DNS options to use
  --dns-search=[]                          DNS search domains to use

On Ubuntu, I believe these settings are in /etc/default/docker which is read by /etc/init.d/docker. Leaving these unset should default to the /etc/resolv.conf values.


Update: Docker's DNS networking documentation has a lot of detail that should point you in the right direction.

if there are no more nameserver entries left in the container’s /etc/resolv.conf file, the daemon adds public Google DNS nameservers (8.8.8.8 and 8.8.4.4) to the container’s DNS configuration.

This looks like it's probably happening in your situation. The filters are looking for local addresses, which I wouldn't think is happening in your situation with a 172.16.0.0/12 private addr, but it's possible.

You might wonder what happens when the host machine’s /etc/resolv.conf file changes. The docker daemon has a file change notifier active which will watch for changes to the host DNS configuration.

Note: The file change notifier relies on the Linux kernel’s inotify feature. Because this feature is currently incompatible with the overlay filesystem driver, a Docker daemon using “overlay” will not be able to take advantage of the /etc/resolv.conf auto-update feature.

If this is happening, then giving the daemon a restart would likely resolve it and would indicate you want Docker to start after the NetworkManager.


Update #2: looking over this github issue it's possible that they also included 172.16.0.0/12 to avoid conflicts with docker's bridged networks. If you can be sure to avoid using the same network inside docker, then passing the dns server in /etc/defaults/docker would likely force the correct behavior. There's also a mention at the end of the post about lxc causing conflicts, so if you have that installed and can remove it, give that a try first.

like image 37
BMitch Avatar answered Oct 24 '25 04:10

BMitch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!