Resolve docker windows container name from host - docker

I'm trying to resolve a docker container address from the host. Windows host. Windows container. I've reviewed number of similar questions:
How do I resolve hostnames to Docker containers from the host?
Docker 1.10 access a container by it's hostname from a host machine
Docker - Windows Container Not Resolving Hosts
None of these questions address this specific question. Seems like a trivial operation and I simply don't understand why it doesn't work.
So for example
$ docker network create -d nat --subnet 172.25.0.0/16 test-net
$ docker container run --network test-net --name example-1 test/example1
Where test/example1 is simply an asp.net core web server.
So it seems to me I should be able to resolve the container name from the host based on the various clues I see in the above referenced answers. For example
$ nslookup example-1 172.25.0.1
$ nslookup example-1 127.0.0.11
$ nslookup example-1.test-net.docker 127.0.0.11
However nothing works.
Naturally I don't need this capability for production, but it would be very helpful for testing. I simply don't understand why I can't get this to work. What am I missing?

Related

How to ping Docker-Container inside host network?

I'm working with Docker containers for a while now but can't figure out how to ping docker containers which are part of my host network.
So until now I created my containers specifing the name and networks flags like described in many tutorials like: https://www.digitalocean.com/community/questions/how-to-ping-docker-container-from-another-container-by-name
Where I am able to create a network and afterwards run my containers in these networks for example like:
docker run -d --name web1 -n testnetwork
docker run -d --name web2 -n testnetwork
That would enable me to ping my containers from each other with:
docker exec -it web1 bash # enter container
ping web2 #ping second container
Now I have to use a given application which only runs in the "host" network for now. To access this container from my other containers they have to be in the same network (== "host").
But It seems like I cant ping my containers from each other anymore. I'm also unable to ping my containers from my host machine using their name.
Did I overlooked something?
Any help would be appreciated!
Best regards
If you set --network host, you basically disable Docker's entire networking stack. Among other things, that disables normal inter-container communications: if you're using host networking you can't call another container by its name. Host networking is very rarely necessary (and doesn't work well on some host platforms); the first thing I'd look at is whether you can switch back to standard (bridged) networking.
If you do run a container with --network host, it's indistinguishable from other processes running on that host. That means you can't directly send ICMP packets to it, any more than you can ping(1) your ssh daemon or Web browser. You need to connect to the container using the host's IP address or DNS name, even from other containers on the same host. From inside of a Docker container, how do I connect to the localhost of the machine? discusses several ways to do this.
(I don't think you can customize the behavior of Docker or Linux when a container receives an ICMP ECHO packet; ping(1) a container doesn't seem that useful.)

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.

Why can't I curl one docker container from another via the host

I really don't understand what's going on here. I just simply want to perform a http request from inside one docker container, to another docker container, via the host, using the host's public ip, on a published port.
Here is my setup. I have my dev machine. And I have a docker host machine with two containers. CONT_A listens and publishes a web service on port 3000.
DEV-MACHINE
HOST (Public IP = 111.222.333.444)
CONT_A (Publish 3000)
CONT_B
On my dev machine (a completely different machine)
I can curl without any problems
curl http://111.222.333.444:3000 --> OK
When I SSH into the HOST
I can curl without any problesm
curl http://111.222.333.444:3000 --> OK
When I execute inside CONT_B
Not possible, just timeout. Ping is fine though...
docker exec -it CONT_B bash
$ curl http://111.222.333.444:3000 --> TIMEOUT
$ ping 111.222.333.444 --> OK
Why?
Ubuntu 16.04, Docker 1.12.3 (default network setup)
I know this isn't strictly answer to the question but there's a more Docker-ish way of solving your problem. I would forget about publishing the port for inter-container communication altogether. Instead create an overlay network using docker swarm. You can find the full guide here but in essence you do the following:
//create network
docker network create --driver overlay --subnet=10.0.9.0/24 my-net
//Start Container A
docker run -d --name=A --network=my-net producer:latest
//Start Container B
docker run -d --name=B --network=my-net consumer:latest
//Magic has occured
docker exec -it B /bin/bash
> curl A:3000 //MIND BLOWN!
Then inside container be you can just curl hostname A and it will resolve for you (even when you start doing scaling etc.)
If you're not keen on using Docker swarm you can still use Docker legacy links as well:
docker run -d --name B --link A:A consumer:latest
which would link any exposed (not published) ports in your A container.
And finally, if you start moving to production...forget about links & overlay networks altogether...use Kubernetes :-) Bit more difficult initial setup but they introduce a bunch of concepts & tools to make linking & scaling clusters of containers a lot easier! But that's just my personal opinion.
By running your container B with --network host argument, You can simply access your container A using localhost, no public ip needed.
> docker run -d --name containerB --network host yourimagename:version
After you run container B with above command then you can try curl container A from container B like this
> docker exec -it containerB /bin/bash
> curl http://localhost:3000
None of the current answers explain why the docker containers behave like described in the question
Docker is there to provide a lightweight isolation of the host resources to one or several containers.
The Docker network is by default isolated from the host network, and use a bridge network (again, by default; you have have overlay network) for inter-container communication.
and how to fix the problem without docker networks.
From "How to connect to the Docker host from inside a Docker container?"
As of Docker version 18.03, you can use the host.docker.internal hostname to connect to your Docker host from inside a Docker container.
This works fine on Docker for Mac and Docker for Windows, but unfortunately, this is not was not supported on Linux until Docker 20.10.0was released in December 2020.
Starting from version 20.10 , the Docker Engine now also supports communicating with the Docker host via host.docker.internal on Linux.
Unfortunately, this won't work out of the box on Linux because you need to add the extra --add-host run flag:
--add-host=host.docker.internal:host-gateway
This is for development purpose and will not work in a production environment outside of Docker Desktop for Windows/Mac.
That way, you don't have to change your network driver to --network=host, and you still can access the host through host.docker.internal.
I had a similar problem, I have a nginx server in one container (lets call it web) with several server blocks, and cron installed in another container (lets call it cron). I use docker compose. I wanted to use curl from cron to web from time to time to execute some php script on one of the application. It should look as follows:
curl http://app1.example.com/some_maintance.php
But I always was getting host unreachable after some time.
First solution was to update /etc/hosts in cron container, and add:
1.2.3.4 app1.example.com
where 1.2.3.4 is the ip for web container, and it worked - but this is a hack - also as far as I know such manual updates are not encouraged. You should use extra_hosts in docker compose, which requires explicit ip address instead of name of container to specify IP address.
I tried to use custom networks solution, which as I have seen is the correct way to deal with this, but I never succeeded here. If I ever learn how to do this I promise to update this answer.
Finally I used curl capability to specify IP address of the server, and I pass domain name as a header in separate parameter:
curl -H'Host: app1.example.com' web/some_maintance.php
not very beautiful but does work.
(here web is the name of my nginx container)

Docker container doesn't expose ports when --net=host is mentioned in the docker run command

I have a CentOS docker container on a CentOS docker host. When I use this command to run the docker image docker run -d --net=host -p 8777:8777 ceilometer:1.x the docker container get host's IP but doesn't have ports assigned to it.
If I run the same command without "--net=host" docker run -d -p 8777:8777 ceilometer:1.x docker exposes the ports but with a different IP. The docker version is 1.10.1. I want the docker container to have the same IP as the host with ports exposed. I also have mentioned in the Dockerfile the instruction EXPOSE 8777 but with no use when "--net=host" is mentioned in the docker run command.
I was confused by this answer. Apparently my docker image should be reachable on port 8080. But it wasn't. Then I read
https://docs.docker.com/network/host/
To quote
The host networking driver only works on Linux hosts, and is not supported on Docker for Mac, Docker for Windows, or Docker EE for Windows Server.
That's rather annoying as I'm on a Mac. The docker command should report an error rather than let me think it was meant to work.
Discussion on why it does not report an error
https://github.com/docker/for-mac/issues/2716
Not sure I'm convinced.
The docker version is 1.10.1. I want the docker container to have same ip as the host with ports exposed.
When you use --net=host it tells the container to use the hosts networking stack. So you can't expose ports to the host, because it is the host (as far as the network stack is concerned).
docker inspect might not show the expose ports, but if you have an application listening on a port, it will be available as if it were running on the host.
On Linux, I have always used --net=host when myapp needed to connect to an another docker container hosting PostgreSQL.
myapp reads an environment variable DATABASE in this example
Like Shane mentions this does not work on MacOS or Windows...
docker run -d -p 127.0.0.1:5432:5432 postgres:latest
So my app can't connect to my other other docker container:
docker run -e DATABASE=127.0.0.1:5432 --net=host myapp
To work around this, you can use host.docker.internal instead of 127.0.0.1 to resolve your hosts IP address.
Therefore, this works
docker run -e DATABASE=host.docker.internal:5432 -d myapp
Hope this saves someone time!

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