How to resolve docker host names (/etc/hosts) in containers - docker

how is it possible to resolve names defined in Docker host's /etc/hosts in containers?
Containers running in my Docker host can resolve public names (e.g. www.ibm.com) so Docker dns is working fine.
I would like to resolve names from Docker hosts's (e.g. 127.17.0.1 smtp) from containers.
My final goal is to connect to services running in Docker host (e.g. smtp server) from containers. I know I can use the Docker Host IP (127.17.0.1) from containers, but I thought that Docker would have used the Docker host /etc/hosts to build containers's resolve files as well.
I am even quite sure I have seen this working a while ago... but I could be wrong.
Any thoughts?
Giovanni

Check out the --add-host flag for the docker command: https://docs.docker.com/engine/reference/run/#managing-etchosts
$ docker run --add-host="smtp:127.17.0.1" container command
In Docker, /etc/hosts cannot be overwritten or modified at runtime (security feature). You need to use Docker's API, in this case --add-host to modify the file.
For docker-compose, use the extra_hosts option.
For the whole "connect to services running in host" problem, see the discussion in this GitHub issue: https://github.com/docker/docker/issues/1143.
The common approach for this problem is to use --add-host with Docker's gateway address for the host, e.g. --add-host="dockerhost:172.17.42.1". Check the issue above for some scripts that find the correct IP and start your containers.

You can setup on host simple DNS server, and in container setup /etc/resolve.conf to Docker host DNS server.
For example in dnsmasq you can add addn-hosts=/etc/hosts to config file. So container, by using Docker host DNS server, will be able to resolve hosts /etc/hosts.

Related

Get the ip of a container to be seen from outside

I am trying to make a shared folder from a container with Ubuntu installing samba.
It is a test and I want to do it without creating volumes.
So, how could I see the IP of the container to create the folder in Windows?
I've been doing it with docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' containerId but the IP that it returns are only for internal networks to docker
Run the container by mapping a host port and you should be able to access the container instance with HostIP:HostPort
RUN A FTP server in the container and Expose necessary ports, including SSH PORT.
Try accessing the files over FTP
Have you tried the following command?
docker container ps
Check out the ports attribute, this should give you the output you need.

Access host machine in Docker Container on Ubuntu 18.04

I am looking for a way to connect to my host machine in a Docker Container (in my case, access to a specific port for using a proxy in the application container).
I tried network_mode: "host" (or docker run --network="host"), it worked in case of accessing to local machine but caused some other problems which were related to changing network driver to host:
SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known.
Also I can not use ifconfig to define network alias since I'm using Ubuntu 18.04.
What should I do?
UPDATE: Since the docker-host (https://github.com/qoomon/docker-host) image is published in the last few months, you can use that without any manual configuration. Easy peasy!
After struggling for a day, finally found the solution. It can be done by --add-host flag in docker run command or extra_hosts in a docker-compose.yml file with making an alias for Local (lo | 127.0.0.1 ) network interface.
So here are the instructions:
First, create an alias for lo interface. As you may know, ifconfig command does not exist on Ubuntu 18.04 so this is how we do it:
sudo ip addr add 192.168.0.20/24 dev lo label lo:1
Then, put this on you docker-compose.yml file:
extra_hosts:
- "otherhost:192.168.0.20"
If you are not using Docker Compose you can add a host to a container by --add-host flag. Something like
docker run container-name --add-host="otherhost:192.168.0.20"
Finally, when you're done with the above steps, restart your containers with docker-compose down && docker-compose up -d or docker-compose restart
Now you can log-in to your container (docker-compose exec container-name bash) and test it.
NOTE: Make sure your working port is open using telnet [interface-ip] [port] command.
You can use the extra_hosts in you docker-compose, which is what you discovered by yourself. I just wanted to add another way when you are working on your local environment.
In docker-for-mac and docker-for-windows, within a container the DNS name host.docker.internal resolves to an IP address allowing network access to the host.
Here's the related description, extracted from the documentation:
The host has a changing IP address (or none if you have no network access). From 18.03 onwards our recommendation is to connect to the special DNS name host.docker.internal, which resolves to the internal IP address used by the host. This is for development purpose and will not work in a production environment outside of Docker for Windows.
There's an open issue on github concerning the implementation of this feature for docker-for-linux.

Docker: Does container inherit /etc/hosts from docker host?

In case of I have a machine that running docker (docker host) and spin up some containers inside this docker host,
I need containers' services be able to talk to each other - container expose ports and they also need to resolve by hostname (e.g: example.com)
container A needs to talk to container B with URL: example.com:3000
I've read this article but not quite sure about "inherit" from docker host, does docker host's /etc/hosts will be appended to container's /etc/hosts that running inside docker host?
https://docs.docker.com/engine/reference/run/#managing-etchosts
How to achieve?
Does this "inherit" has any connect to type of docker container networking https://docs.docker.com/v17.09/engine/userguide/networking/ ?
It does not inherit the host's /etc/hosts file. The file inside your container is updated by docker when using the --add-host parameter or extra_hosts in docker-compose. You can add individual records by using extra_hosts in docker-compose (https://docs.docker.com/compose/compose-file/#extra_hosts).
Although if you're just trying to get 2 containers talking to each other you can alternatively connect them to the same network. In docker-compose you can create what's called an external network and have all your docker-compose files reference it. you will then be able to connect by using the full docker container name (eg. http://project_app_1:3000).
See https://docs.docker.com/compose/compose-file/#external

How can you make the Docker container use the host machine's '/etc/hosts' file?

I want to make it so that the Docker container I spin up use the same /etc/hosts settings as on the host machine I run from. Is there a way to do this?
I know there is an --add-host option with docker run, but that's not exactly what I want because the host machine's /etc/hosts file may be different on different machines, so it's not great for me to hardcode exact IP addresses/hosts with --add-host.
Use --network=host in the docker run command. This tells Docker to make the container use the host's network stack. You can learn more here.
Add a standard hosts file -
docker run -it ubuntu cat /etc/hosts
Add a mapping for server 'foo' -
docker run -it --add-host foo:10.0.0.3 ubuntu cat /etc/hosts
Add mappings for multiple servers
docker run -it --add-host foo:10.0.0.3 --add-host bar:10.7.3.21 ubuntu cat /etc/hosts
Reference - Docker Now Supports Adding Host Mappings
extra_hosts (in docker-compose.yml)
https://github.com/compose-spec/compose-spec/blob/master/spec.md#extra_hosts
Add hostname mappings. Use the same values as the docker client --add-host parameter.
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
Also you can install dnsmasq to the host machine, by the command:
sudo apt-get install dnsmasq
And then you need to add the file /etc/docker/daemon.json with content:
{
"dns": ["host_ip_address", "8.8.8.8"],
}
After that, you need to restart the Docker service by command sudo service docker restart
This option forces to use the host DNS options for every Docker container.
Or you can use it for a single container, and the command-line options are explained by this link. Also docker-compose options are supported (you can read about it by this link).
If you are using docker-compose.yml, the corresponding property is:
services:
xxx:
network_mode: "host"
Source
Add this to your run command:
-v /etc/hosts:/etc/hosts
If trusted users start your containers, you could use a shell function to easily "copy" the /etc/hosts entries that you need:
add_host_opt() { awk "/\\<${1}\\>/ {print \"--add-host $1:\" \$1}" /etc/hosts; }
You can then do:
docker run $(add_host_opt host.name) ubuntu cat /etc/hosts
That way you do not have to hard-code the IP addresses.
The host machine's /etc/hosts file can't mount into a container. But you can mount a folder into the container. And you need a dnsmasq container.
A new folder on host machine
mkdir -p ~/new_hosts/
ln /etc/hosts ~/new_hosts/hosts
mount the ~/new_hosts/ into container
docker run -it -v ~/new_hosts/:/new_hosts centos /bin/bash
Config dnsmasq use /new_hosts/hosts to resolve name.
Change your container's DNS server. Use the dnsmasq container's IP address.
If you change the /etc/hosts file on the host machine, the dnsmasq container's /new_hosts/hosts will change.
I found a problem:
The file in dnsmasq container /new_hosts/hosts can change. But the new hosts can't resolve. Because dnsmasq use inotify listen change event. When you modify a file on the host machine. The dnsmasq can't receive the signal so it doesn't update the configuration. So you may need to write a daemon process to read the /new_hosts/hosts file content to another file every time. And change the dnsmasq configuration to use the new file.
I had the same problem and found that it is likely in contrast with the containerization concept! however I solved my problem by adding each (ip host) pair from /etc/hosts to an existing running container in this way:
docker stop your-container-name
systemctl stop docker
vi /var/lib/docker/containers/*your-container-ID*/hostconfig.json
find ExtraHosts in text and add or replace null with
"ExtraHosts":["your.domain-name.com":"it.s.ip.addr"]
systemctl start docker
docker start your-container-name
if you can stop your container and re-run it, you'd have better situation, so just do that. But if you do not want to destroy your containers, just like mine, it would be a good solution.
If you are running a virtual machine for running Docker containers, if there are hosts (VMs, etc.) you want your containers to be aware of, depending on what VM software you are using, you will have to ensure that there are entries on the host machine (hosting the VM) for whatever machines you want the containers to be able to resolve.
This is because the VM and its containers will have the IP address of the host machine (of the VMs) in their resolv.conf file.
IMO, passing --network=host option while running Docker is a better option as suggested by d3ming over other options as suggested by other answers:
Any change in the host's /etc/hosts file is immediately available to the container, which is what probably you want if you have such a requirement at the first place.
It's probably not a good idea to use the -v option to mount the host's /etc/hosts filr as any unintended change by the container will spoil the host's configuration.

How do docker containers resolve hostname of other docker containers running on the same machine?

I have started to use docker and liking it mostly because Docker containers are kind of light-weight VMs. But I am unable to figure out, how docker containers may be able resolve each-other's hostnames. They can connect to each other using there IPs, but not using their hostnames, I cannot even edit /etc/hosts in the containers to make up for that somehow. When I restart the containers, they get different IPs and hence I want to use the hostnames in place of IPs to communicate with each other. Let us say, I want to run Zookeeper instances of a Zookeeper cluster in the containers and I want to put the hostnames of the Zookeeper servers in the config (zoo.cfg) files.
As of Docker 1.10, if you create a distinct docker network, Docker will resolve hostnames intra-container-wise using an internal DNS server [1][2][3].
You can change the network hostname by specifying one with --name within the docker run. Otherwise the hostname will refer to the container id (12 char long hash, shown by docker container ls ).
See also:
Docker doesn't resolve hostname
When to use --hostname in docker?
Sources:
[1] = docker docs - Embedded DNS server in user-defined networks
[2] = Docker Engine release notes
- 1.10.0 (2016-02-04) - Networking
[3] = Docker pull requests - Vendoring libnetwork
It may be worth checking out Docker links (https://docs.docker.com/userguide/dockerlinks/). When you link to a running container, a host entry is added for the container you wish to connect to.
In their example they show
$ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
root#aed84ee21bde:/opt/webapp# cat /etc/hosts
172.17.0.7 aed84ee21bde
. . .
172.17.0.5 db
As you see here, they link the application they're in bash with to the container named db, and subsequently a host entry is added for db with the IP address of that container.
So in the instance of having zookeeper running, you could simply make the containers you start just link to zookeeper. I hope this helps!
Can depend on OS of container, but supposing that container runs Linux
you can check your DNS configuration this way:
cat /etc/resolv.conf
It can return something like:
nameserver 127.0.0.11
options ndots:0
/etc/resolv.conf is standard configuration file for DNS in UNIX-like OS-es.
In this particular case container is configured to use 127.0.0.11 as DNS server.
So container can query it to determine IP address of another container using it's host name.
You can check whether that host actually works by using nslookup command, e.g.:
nslookup redis 127.0.0.11
, which will contact DNS server 127.0.0.11 and ask to resolve host name "redis".
It can return something like:
Server: 127.0.0.11
Address 1: 127.0.0.11
Name: redis
Address 1: 172.21.0.3 counter-app_redis_1.counter-app_counter-net
, which would mean that host name resolved to ip 172.21.0.3.
In this specific case nameserver entry was added by using the following entry in the docker-compose.yml configuration file:
...
networks:
counter-net:
This root entry configured common bridge network shared by several docker containers.

Resources