36

Edit 2020: This is a six year old question. I never figured out how to fix this specific problem back then, but Docker and everything else involved moved on. SE doesn't allow me to delete my question, but it's not relevant anymore.

I have a new Ubuntu 14.04 install, and want to use Docker to run my old stuff that needs 12.04. DNS inside Docker doesn't work.

My laptop's resolv.conf looks like:

nameserver 127.0.0.1

Which doesn't work with Docker, apparently. It therefore tries to set the nameservers to 8.8.8.8 and 8.8.4.4; when I do

$ sudo docker run -i -t ubuntu /bin/bash

It says:

WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : [8.8.8.8 8.8.4.4]

And sure enough, inside the Docker instance, resolv.conf looks like:

nameserver 8.8.8.8
nameserver 8.8.4.4

I can ping both of those successfully from within the Docker instance. However, there is no DNS (e.g., ping google.com fails).

ifconfig output inside Docker:

eth0      Link encap:Ethernet  HWaddr aa:e9:9f:83:9d:92  
          inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::a8e9:9fff:fe83:9d92/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:648 (648.0 B)  TX bytes:738 (738.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Now what?

1
  • I'm using Ubuntu 16.04 and Docker 19.03.7 and your question and its solution helped me today.
    – elmicha
    Mar 5, 2020 at 22:04

6 Answers 6

27

When the Ubuntu Docker package updated to using systemd, it dropped support for the /etc/default/docker config file, so the initial solution suggested by rocketman10404 will no longer work (disabling dnsmasq would still work, but it has the downside of preventing Ubuntu from automatically updating the DNS server).

Fixing in the new daemon.json config file

Find your network's DNS server:

$ nmcli dev show | grep 'IP4.DNS'
IP4.DNS[1]:                             10.0.0.2

Open or create, if it doesn't exist, /etc/docker/daemon.json and add the DNS servers that you want to use:

# /etc/docker/daemon.json
{
    "dns": ["10.0.0.2", "8.8.8.8"]
}

Restart the docker daemon:

$ sudo service docker restart

I wrote an in-depth blog post and also filed a bug about this issue if you'd like more details.

(Originally I solved it by opening up /lib/systemd/system/docker.service and add DNS settings to the ExecStart line, but that's bad - we shouldn't edit systemd files directly.)

2
  • Thanks for your solution - it was helpful on the road I took to my solution - which I think is a slightly more elegant match for my own circumstances and the peculiarities of running Docker on Ubuntu (or other desktop distros that use NetworkManager+dnsmasq).
    – Adrian
    Sep 19, 2016 at 10:51
  • Warning: Using non-default DNS server makes host.docker.internal stop being resolved on MacOS/Wndows Docker Desktop.
    – rfay
    Sep 4, 2021 at 15:30
16

I don't use docker myself, so I normally wouldn't butt-in here on a docker question, but I just happened to be reading about it and stumbled on some docker documentation that appears to address this exact problem. To sum-up...

The documentation suggests a few workarounds. The first is to specify the DNS server to be used by the docker daemon for the containers by adding the following line to /etc/default/docker:

docker_OPTS="--dns 8.8.8.8"

where the DNS provided could be a local DNS server, such as 192.168.1.1 (gateway). Then, restart with

sudo restart docker

An alternative solution involves disabling dnsmasq in NetworkManager by commenting out the config in /etc/NetworkManager/NetworkManager.conf like so:

#dns=dnsmasq

then, restart both

sudo restart network-manager
sudo restart docker
5
  • 3
    disabling dnsmasq worked for me.
    – bennyl
    Oct 26, 2015 at 11:05
  • 2
    This latter approach will of course mean network manager can't control dnsmasq, meaning for example that it can't change your dns server when you change network, including switching to a VPN. The former approach seems better to me, but I'd like to be able to have dnsmasq also listen on the docker IP (172.17.0.1) so I can point docker hosts at that.
    – mc0e
    Mar 22, 2016 at 0:13
  • 1
    Since Ubuntu switched to setting up Docker with sytemd, /etc/default/docker no longer has any effect. See my solution for how to solve this in a post-init.d/upstart world. Sep 19, 2016 at 15:23
  • /etc/NetworkManager/NetworkManager.conf doesn't exist on Ubuntu 18.04 LTS. :/ Aug 31, 2018 at 6:06
  • Note that with some Ubuntu 18.04 setups (e.g. the minimal image on Amazon) systemd-resolved is acting as a caching DNS server by default and will provoke the WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. problem (Ubuntu 16.04 setups don't appear to enable it by default). The workaround is to either disable systemd-resolved or use the --dns option when starting the container as mentioned in the main answer.
    – Anon
    Sep 29, 2018 at 21:08
10

I ran into this in my situation which is specifically

  • Running Docker containers on my local development machine
  • Which is connected to a VPN
  • Some of our container build scripts do things like run npm install from a custom repository on the VPN, inside the container.
    • This works from a CI pipeline but not from our developer machines, because npm can't do a successful DNS lookup
    • We also had problems with containers that need to do lookups to call external REST APIs

Ubuntu by default uses dnsmasq started up by NetworkManager to cache DNS requests, and configures /etc/resolv.conf to point to this instance on 127.0.1.1

  • The VPN client we're using is not NetworkManager compatible and forces it's own /etc/resolv.conf which overwrites the NetworkManager config
  • This configures the DNS servers for the VPN
  • Docker shadows your /etc/resolv.conf to the container by default
    • Usually on Ubuntu, it passes the Google DNS servers to the container (because it knows about the dnsmasq situation.
    • But it's happy to pass the VPN DNS server config to the container
    • There's no route from the container on the docker0 network bridge, to the DNS servers over the VPN tap0 adapter.
  • Ergo, all DNS lookups in the container fail because it can't reach the only DNS servers it's supplied with
  • Additionally, some networks block requests to the Google DNS servers because they want to be able to snoop all your DNS lookups

The solution :

It would seem to be more elegant to use NetworkManager and it's captive dnsmasq instance in the way it was designed.

  1. Tell Docker to use your dnsmasq instance for DNS

    • Add or edit file /etc/docker/daemon.json to tell docker to use the docker0 bridge adapter for DNS

      {
        "dns": ["172.17.0.1"]
      }
      
  2. Configure the NM dnsmasq instance to listen to the Docker bridges as well, because by default it only listens to 127.0.1.1 - create file /etc/NetworkManager/dnsmasq.d/docker-bridge.conf

    # Default Docker bridge
    interface=docker0
    # Other Docker bridges
    interface=br-*
    
  3. I don't like the rude behaviour of that VPN client and I'd rather only use the DNS at the VPN end for VPN lookups (if you have a polite VPN client that uses NetworkManager configured correctly, you won't have to do this)

    • Turn off DNS feature in VPN client (it stops overwriting resolv.conf on connect and now all DNS goes through dnsmasq again)
    • Add a config file to tell dnsmasq to direct DNS requests for your domain appropriately - add file `/etc/NetworkManager/dnsmasq.d/vpn-dns.conf

      server=/myprivatedomain.net/10.0.0.1  
      # or whatever your private DNS server is
      
    • Optionally, add a search domain for your domain so you can use short names

      • I just added our local domain to the search list in my default network connection
  4. Restart NetworkManager and Docker

    sudo service network-manager restart
    sudo service docker restart
    

At this point your Docker containers should be able to do nslookup without issues when you're on VPN, for domains both inside and outside your VPN.

5
  • 1
    A small tweak that doesn't involve hard-coding the docker0 bridge IP is to use interface instead of the listen-address directive: interface=docker0
    – siwyd
    Dec 4, 2016 at 16:58
  • Awesome explanations and instructions. A +1 well-deserved.
    – ereOn
    Aug 9, 2017 at 14:15
  • Cheers @simonwydooghe - I've incorporated your suggestion - you can also use wildcards in that field so I've added a pattern for all the bridge names used by non-default networks (at least, as used by docker-compose).
    – Adrian
    Aug 9, 2017 at 19:03
  • 1
    It seems that the dns value in daemon.json has to be an array, otherwise I get an error: cannot unmarshal string into Go value of type []string when restarting the docker service. Sep 15, 2017 at 14:12
  • Update for Bionic : 18.04 no longer uses a captive instance of dnsmasq managed by NetworkManager for DNS and instead uses systemd-resolved ; which brings it's own problems, because that can't be configured to listen to the docker0 bridge. I've resorted to disabling it, and re-installing the NetworkManager dnsmasq and configuring it correctly.
    – Adrian
    Jul 21, 2018 at 9:02
2

Here is how I set up docker on my Ubuntu 14.04 server running headless.

I am running Ubuntu server 14.04 with the following docker version installed.

#docker version
Client version: 0.9.1
Go version (client): go1.2.1
Git commit (client): 3600720
Server version: 0.9.1
Git commit (server): 3600720
Go version (server): go1.2.1

The file /etc/init/docker.io.conf and the script contains the following line:

# modify these in /etc/default/$UPSTART_JOB (/etc/default/docker)
    DOCKER=/usr/bin/$UPSTART_JOB
    DOCKER_OPTS=

The answer above helped me find the file above.

I uncommented the following in /etc/default/docker.io and added my local DNS server:

# Use DOCKER_OPTS to modify the daemon startup options.  
DOCKER_OPTS="--dns 192.168.X.X"

Restarted the service with:

sudo service docker.io restart

Ran docker run <image> /bin/bash

No dns messages when starting the container.

Started a new container, installed dnsutils.

Ran dig and the server message is the correct local DNS server.

0

I had a similar issue, reported it to StackOverflow. It appears that I could not query the 8.8.8.8 nameserver that is specified in the default Ubuntu installation of Docker; however, I could ping it. In this case, use a DNS server which you can actually query. Test with

nslookup - dns.server.name

and start the container via

docker run --dns=ip.addr.of.dns

I have yet to find a way to https://askubuntu.com/q/607172/30266 to derive an automagic solution.

1
  • My answer may be automagic enough for you...
    – Adrian
    Sep 19, 2016 at 11:07
0

You can use the host's local DNS resolver (e.g. dnsmasq) from your Docker containers if they are on a user defined network. In that case a container's /etc/resolv.conf will have the nameserver 127.0.0.11 (a.k.a. the Docker's embedded DNS server), which can forward DNS requests to the host's loopback address properly.

$ cat /etc/resolv.conf
nameserver 127.0.0.1
$ docker run --rm alpine cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
$ docker network create demo
557079c79ddf6be7d6def935fa0c1c3c8290a0db4649c4679b84f6363e3dd9a0
$ docker run --rm --net demo alpine cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0    

If you use docker-compose, it will set up a custom network for your containers automatically (with a file format v2+). Note, however, that while docker-compose runs containers in a user-defined network, it still builds them in the default network. To use a custom network for builds you can specify the network parameter in the build configuration (requires file format v3.4+).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .