Identify Docker container's IP Address and connect to port - docker

On my windows laptop I have created a Play application which runs fine if I execute its scripts directly. On the local machine, I access the application using localhost:9000 URL.
I have now created a Docker image of the application and have exposed port 9000
#this docker file copies prod specific files to container, eg logback_prod.xml and application_prod.conf
FROM openjdk:8
#ENV APP_NAME myapp
#ENV APP_VERSION 1.0-SNAPSHOT
...
#entrypoint is deploy/....
EXPOSE 9000
ENTRYPOINT ...
But I can't access the application on localhost:9000. I suspect that the image might be running on some other IP created by docker itself.
Am I correct? How can I access my application through the container? I don't need Kubernetes Services etc. as I already have that setup on another machine. My specific question is how to access the docker container directly.
UPDATE
I also tried running the docker image using --network="host" but that doesn't work either
UPDATE 2
Based on the suggestions below, I executed the following commands but still can't access the application.
docker run -p 9000:9000 --env-file env.txt imagename
I see the trace
[debug] a.i.TcpListener - Successfully bound to /0.0.0.0:9000
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0.0.0.0:9000
docker ps -a shows application is up with port binding 0.0.0.0:9000->9000/tcp
docker inspect shows IP - "IPAddress": "172.17.0.2"
but http://172.17.0.2:9000/ on Chrome doesn't work This site can’t be reached172.17.0.2
netstat -ab on cmd shows TCP 0.0.0.0:9000 LAPTOP-788I0GL1:0 LISTENING [com.docker.backend.exe]

Identify container's IP Address
Try these options with a running container.
<docker> refers to container's name or id
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <docker>
//WINDOWS ONLY
docker inspect --format "{{ .NetworkSettings.IPAddress }}" <docker>
docker inspect <docker> | grep "IPAddress"
Grep not avaliable on Windows*
docker network inspect bridge
This last one would output all running containers' info that are allocated in the bridge network (default). Once identified, check the container's IPv4Address field.
Expose ports
In order to be able to connect to the a container's port, you could expose it. Note that the previous step is not needed in this case:
docker run -p 9000:9000 --env-file env.txt manuchadha25/mydockerimage
By default the docker will bind/listen to all interfaces on the host. The -p 9000:9000 option exposes the port, and as a result you get: 0.0.0.0:9000->9000/tcp
Now localhost:9000 succesfully connects to your docker process.

You can try the command docker inspect:
docker inspect <containerid>
for list the containers ids you can run the command:
docker ps
In order to get the ipAddress information you should look to node:
"IPAddress": "172.23.0.2"
In the json output produced.
Here is the documentation for docker inspect command.

Related

Assigning a local IP to docker containers

Is there a way to have docker automatically give it’s containers a local IP address that you can reach with it’s ports exposed?
For example, LXC has ways to do this.
lxc-create -t ubuntu -n myname
lxc-start -n myname -d
Which will then assign a local IP which you can see via lxc-ls if you have a bridge configured:
lxc-ls -f
This is super convenient for throwing up a bunch of containers for testing out deployment/configuration management like ansible.
Is it possible to do something similar in docker without much headache? I come from using LXC and I’m not familiar with the networking modes.
LXC and Docker are very similar. When LXC is installed, a random subnet is picked for configuring the IP addresses of bridge and the containers attached to it. With Docker, the default subnet is 172.17.0.0/16, which can be customized if needed. Every container stared (unless using host network or network of another container) using docker run command are assigned an IP address from the above subnet.
docker ps lists all the containers running but unfortunately it doesn't show the IP addresses.
Looks like a small trick can show the IP addresses: (based on this post)
docker ps -q | xargs docker inspect --format '{{ .Id }} - {{ .Name }} - {{ .NetworkSettings.IPAddress }}'
Also you can expose the ports using the -p option of docker run command.
Example:
docker run -itd -p 8080:80 nginx
This starts the container on the docker bridge and also exposes the nginx on the host network via port 8080.
from_host_running_container# curl http://172.17.x.y
from_not_the_host_running_container # curl http://${HOST_IP}:8080

docker port mapping syntax

I am new to docker, and I am a bit confused about what the following command options do specifically for the command I came across.
--name : appname is the name of the image?
-t : Run in terminal?
-d : run as daemon?
-p : for somebody outside the container to talk to port 9090 they have to connect on port 9000?
Same for port 15501 but it is a udp port?
appname2: name assigned to running image?
docker run -t --name=appname -p 9090:9000 -p 15501:15501/udp -d appname2
docker run -t --name=appname -p 9090:9000 -p 15501:15501/udp -d appname2
Q: --name : appname is the name of the image?
No. It's the name of the container that you are creating (optional).
--name string Assign a name to the container
Q: -t : Run in terminal?
-t, --tty Allocate a pseudo-TTY
Q: -d : run as daemon?
Sort of. It means that you want to run your container detached from your terminal.
-d, --detach Run container in background and print container ID
Q: -p : for somebody outside the container to talk to port 9090 they have to connect on port 9000?
9090:9000 means: port 9090 on the host machine binded to port 9000 on the container. To talk to the container port someone outside should talk to 9090.
-p, --publish list Publish a container's port(s) to the host (default [])
Q: Same for port 15501 but it is a udp port?
Right.
Q: appname2: name assigned to running image?
That is the image that you are running on. The container is based on top of it.
Bonus! You can find all of this info here: docker help run
Bonus 2! Try it yourself:
docker run -d -it --name my-container alpine sh
docker inspect my-container
# See all this funny output. It's all about the container that you've created
From https://docs.docker.com/engine/reference/run/
The -d flag means detached. When you run a docker container, you can either run a container in foreground, or you can run it in the background. The choice of how to run your container really depends on your use case. If, for example, you run an OS container with some functionality, you would probably want run the container in foreground in order to use this functionality. But if you run a DB server, you may want to run it in the background.
The -p flag, when used, publishes all exposed ports to the host interfaces. If for example you run a DB server inside a container which has some ports exposed, and you wish to communicate to the server from a distance, you may want to map the ports inside the container to a single or multiple ports of choice on your host system. That way when you connect to the port on your host, you connect to the docker server running inside of it (I hope this is clear). The mapping format is as follows:
ip:hostPort:contain`enter code here`erPort | ip::containerPort | hostPort:containerPort | containerPort
The --name flag gives the running container a nice name. If not used, it would generate a name. It can be used, for example, if you executed a container in detached mode, and then you wanted to get inside the container using the attach command.
The -t flag allocates a text console for the container.
appname2 is the name of the docker image.

How to get IP address of running docker container

I am using Docker for Mac. I am running a nodejs based microservice in a Docker container. I want to test node microservice through the browser. How to get IP address of running docker container?
If you don't want to map ports from your host to the container you can access directly to the docker range ip for the container. This range is by default only accessed from your host. You can check your container network data doing:
docker inspect <containerNameOrId>
Probably is better to filter:
docker inspect <containerNameOrId> | grep '"IPAddress"' | head -n 1
Usually, the default docker ip range is 172.17.0.0/16. Your host should be 172.17.0.1 and your first container should be 172.17.0.2 if everything is normal and you didn't specify any special network options.
EDIT
Another more elegant way using docker features instead of "bash tricking":
docker inspect -f "{{ .NetworkSettings.IPAddress }}" <containerNameOrId>
EDIT2
For modern docker engines, now it is this way (thanks to the commenters!):
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <containerNameOrId>
Use --format option to get only the IP address instead whole container info:
sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' <CONTAINER ID>
For modern docker engines use this command :
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
and for older engines use :
docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id
if you want to obtain it right within the container, you can try
ip a | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | grep 172.17
You can start your container with the flag -P. This "assigns" a random port to the exposed port of your image.
With docker port <container id> you can see the randomly choosen port. Access is then possible via localhost:port.
For my case, below worked on Mac:
I could not access container IPs directly on Mac. I need to use localhost with port forwarding, e.g. if the port is 8000, then http://localhost:8000
See https://docs.docker.com/docker-for-mac/networking/#known-limitations-use-cases-and-workarounds
The original answer was from: https://github.com/docker/for-mac/issues/2670#issuecomment-371249949
If you want to view the IP address from within the running container, /etc/hosts file is a great place to look at. Now, to uniquely identify the entry within the hosts file, it is a good practise to run the container with the -h option. Sample commands are given below:
Run the container with -h set:
docker run -td -h guju <image name>
Log in to the running container and view the /etc/hosts file. It will show an entry like this:
172.17.0.5 guju
this will list all containers' IP addresses
while read ctr;do
sudo docker inspect --format "$ctr "'{{.Name}}{{ .NetworkSettings.IPAddress }}' $ctr
done < <(docker ps -a --filter status=running --format '{{.ID}}')
You can not access the docker's IP from outside of that host machine.
If your browser is on another machine better to map the host port to container port by passing -p 8080:8080 to run command.
Passing -p you can map host port to container port and a proxy is set to forward all traffix for said host port to designated container port.

Problems getting docker containers to see (ping) each other by name

I have three docker containers,
java container (JC): for my java application (spring boot)
elasticsearch container (EC): for ElasticSearch
test container (TC): testing container to troubleshoot with ping test
Currently, the JC cannot see the EC by "name". And when I say "see" I mean if I do a ping on the JC to EC, I get a ping: unknown host. Interestingly, if I do a ping on the TC to EC, I do get a response.
Here is how I start the containers.
docker run -dit --name JC myapp-image
docker run -d --name EC elasticsearch:1.5.2 elasticsearch -Des.cluster.name=es
docker run --rm --name TC -it busybox:latest
Then, to ping EC from JC, I issue the following commands.
docker exec JC ping -c 2 EC
I get a ping: unknown host
With the TC, since I am already at the shell, I can just do a ping -c 2 EC and I get 2 replies.
I thought maybe this had something to do with my Java application, but I doubt it because I modified my Dockerfile to just stand up the container. The Dockerfile looks like the following.
FROM java:8
VOLUME /tmp
Note that you can create the above docker image by docker build -no-cache -t myapp-image ..
Also note that I have Docker Weave Net installed, and this does not seem to help getting the JC to see the EC by name. On the other hand, I tried to find the IP address of each container as follows.
docker inspect -f '{{ .NetworkSettings.IPAddress }}' JC --> 172.17.0.4
docker inspect -f '{{ .NetworkSettings.IPAddress }}' EC --> 172.17.0.2
docker inspect -f '{{ .NetworkSettings.IPAddress }}' TC --> 172.17.0.3
I can certainly ping EC from JC by IP address: docker exec JC ping -c 2 172.17.0.2. But getting the containers to see each other by IP address does not help as my Java application needs a hostname reference as a part of its configuration.
Any ideas on what's going on? Is it the container images themselves? Why would the busybox container image be able to ping the ElasticSearch container by name but the java container not?
Some more information.
VirtualBox 5.0.10
Docker 1.9.1
Weave 1.4.0
CentOS 7.1.1503
I am running docker inside a CentOS VM on a Windows 10 desktop as a staging environment before deployment to AWS
Any help is appreciated.
Within the same docker daemon, use the old --link option in order to update the /etc/hosts of each component and make sure one can ping the other:
docker run -d --name EC elasticsearch:1.5.2 elasticsearch -Des.cluster.name=es
docker run -dit --name JC --link ED myapp-image
docker run --rm --name TC -it busybox:latest
Then, a docker exec JC ping -c 2 EC should work.
If it does not, check if this isn't because of the base image and a security issue: see "Addressing Problems with Ping in Containers on Atomic Hosts".
JC is based on docker/_java:8, itself based on jessie-curl, jessie.
Containers in this default network are able to communicate with each other using IP addresses. Docker does not support automatic service discovery on the default bridge network. If you want to communicate with container names in this default bridge network, you must connect the containers via the legacy docker run --link option. docs.docker.org.
It should also work using the new networking.
docker network create -d bridge non-default
docker run --net non-default ...
There isn't a specific option which applies this behavior to the default network (AFAICT from looking at docker network inspect). I guess it's just triggered by the option "com.docker.network.bridge.default_bridge".
In the first part of another question, it's suggested this was changed in Docker 1.9. Note that Docker 1.9 was when they turned on the new networking system in the stable release. The section of the userguide that I quoted from above, did not exist in version 1.8. Docker 1.9.0 "bridge" versus a custom bridge network results in difference in hosts file and SSH_CLIENT env variable

Connect to a service in docker, run from an interactive shell

Suppose I have the following container:
docker run -i -t test/python3 /bin/bash
and run the following in the shell:
python3 -m http.server 8080
How do I connect to this port from the host? Is this possible?
You can connect directly to the container using its private IP. To discover it, in the host terminal you can run docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container_id>. The container_id can be obtained using docker ps once the container is running (also from the host). Once you have that ip you can access directly to it to the port you wish.
Also you have the option to publish a container port to the host machine, thus you can access directly from you localmachine to localhost:8080, or from any other machine that has visibility with the host (to the adequate ip or hostname). To publish the port you have to use the option -p, as describer in the docker run prompt help:
$ docker run --help
(...)
-p, --publish=[] Publish a container's port to the host
format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
(...)
So in that case you could run docker run -i -t -p 8080:8080 test/python3 /bin/bash to, for example, publish the port 8080 of the container to the same number port of your local machine (you could choose any other not already in use in your host machine). Also may be you don't need to run the container in a interactive way if you don't need to perform any further action inside (or doing this using a script), and running directly the command you wish to execute: docker run -i -t -p 8080:8080 test/python3 python3 -m http.server 8080

Resources