4

When creating docker containers with a docker-compose file which specifies hostname (hostname:) and ip addresses (ipv4_address:), I would like the local computer (the computer that runs the docker daemon service, aka my laptop) to be able to resolve those hostnames, without the need of (too much) manual intervention. I.e. if the container is a webserver service with hostname my_webserver, I would like that my_werbserver resolve to the IP address I assigned to that container.

What's the best way to achieve that? Anything better than maintaining /etc/hosts on my laptop manually?

Christophe Schmitz
  • 2,896
  • 2
  • 14
  • 21
  • I think you need to check the resolver > https://docs.docker.com/v17.09/engine/userguide/networking/default_network/configure-dns/ – callmemath Jun 28 '19 at 03:27
  • Merci Matthieu. Doesn't look like this help me resolve from my laptop itself. Those options help control how hostnames are resolved from within the container(s). – Christophe Schmitz Jun 28 '19 at 05:06
  • you just need one entry in `/etc/hosts` exp : `my_werbserver localhost` and you will be able to connect whatever the ip is, sure you need to call `my_werbserver` with your local port – LinPy Jun 28 '19 at 06:10
  • Thanks @LinSel I am trying to achieve that without the need to manually edit /etc/hosts, as I don't want to manually update that if for example I rename the service, or change the IP address. – Christophe Schmitz Jun 30 '19 at 23:10

2 Answers2

3

As @Kārlis Ābele mentioned, I don't think you can do what you need without additional services. One solution would be to run dnsmasq in a docker container in the same network as the other docker containers. See Make the internal DNS server available from the host

docker run -d --name dns -p 53:53 -p 53:53/udp --network docker_network andyshinn/dnsmasq:2.76 -k -d

Check that it works using localhost as DNS

nslookup bar localhost

Optionally setup localhost as DNS server. On Ubutu 18.04 for example, edit /etc/resolvconf/resolv.conf.d/head.

nameserver localhost

Restart the resolvconf service.

sudo service resolvconf restart

Now you should be able to ping the containers by name.

EDITED: An alternative solution (based on @Kārlis Ābele answer) is to listen to docker events and update /etc/hosts. A barebones implementation:

#!/usr/bin/env bash

while IFS= read -r line; do
  container_id=$(echo ${line}| sed -En 's/.*create (.*) \(.*$/\1 /p')
  container_name=$(echo ${line}| sed -En 's/.*name=(.*)\)$/\1 /p')

  ip_addr=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${container_id})

  echo ${ip_addr} ${container_name} >> /etc/hosts
done < <(docker events --filter 'event=create')
b0gusb
  • 4,283
  • 2
  • 14
  • 33
  • That sounds very promising, I'll try that, and report back later, thanks @b0gusb – Christophe Schmitz Jun 30 '19 at 23:11
  • You will not be able to reach the container by defined `hostname:`. Use either the service name or set `container_name:`. See [Service can't be reached by defined hostname](https://stackoverflow.com/q/29924843/8482479) – b0gusb Jul 01 '19 at 05:50
  • Yea I got it to work, sort of. Was a bit of a pain on Fedora with NetworkManager, I ended up writting a custom script in /etc/NetworkMangager/dispatcher.d to make sure the first entry in /etc/resolv.conf is 127.0.0.1 as the head file does not seem to be taken into account; then I had to do a few more hacks in the dnsmasq image (ended up writting my own), but got it to work, mostly. – Christophe Schmitz Jul 01 '19 at 07:03
2

Well it seems like something that won't be possible without some custom service that is listening for events on Docker daemon...

How I would do this, is write a simple service that is listening for Docker events (https://docs.docker.com/engine/reference/commandline/events/) and updates /etc/hosts file accordingly.

Other than that, without manually updating hosts file I don't think there are other options though.

Kārlis Ābele
  • 971
  • 4
  • 9
  • Thanks @Kārlis Ābele that sounds like a very interesting approach, haven't thought if it.. I'll try first the dns solution suggestion from b0gusb, but your solution is a solide plan B for my use case. – Christophe Schmitz Jun 30 '19 at 23:12
  • @Kārlis Ābele That's a very interesting approach. However `docker events` doesn't seem to show any event related to IP address or name assignment. Would you expand on that? – b0gusb Jul 02 '19 at 06:25
  • 1
    @b0gusb Let's say you need to do some specific action once a new container has been started. You can create a service that runs in background (can even be in a container itself if you mount the docker socket in the container) and checks for container create event. Along with the event you can retrieve the container ID from which you can then pretty much get any information necessary about the container and even make changes to the container itself. Once you have the container ID, you can use build in docker commands to retrieve any network information you need and use it accordingly – Kārlis Ābele Oct 03 '19 at 07:39
  • I think that could be a pretty good alternative and it's quite easy to implement. @KārlisĀbele. I added a basic script that does that. – b0gusb Oct 04 '19 at 06:21