DooD Pitfalls: Port Mapping

In this post, we will continue with docker-outside-of-docker pitfalls. This time we will focus on port mapping with the -p flag to docker. When invoking a container with this flag using DooD, the end result may not be what you expect. I’ll show some examples with a nginx docker container.

Pitfall: Port Mapping

I’ll spin up a nginx from my local machine and map the nginx port to 8080.

docker run --rm -d  -p 8080:80 nginx:latest

I now have a nginx container running with 8080 opened on my localhost.

Stop the nginx container using docker stop on the container id (docker ps gives you the id)
Now let’s run that same command from our maven container that we spin up using DooD.

First, let’s start a maven continer:

$ docker run -it --rm  -v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock maven:3.5.2-jdk-8-alpine bash

Next, let’s start the nginx container from the maven container. You should be inside a bash shell on the maven container at this point:

bash-4.3# docker run --rm -d  -p 8080:80 nginx:latest
1f0496344e313ea471b19831daf53c2f43401d618f0e630231f2d6dd5b4aa9c4
bash-4.3#

Let’s view localhost:8080 in a browser.

Great, nginx is up and running. Now let’s try to access nginx from our maven container on localhost:8080. This maven image already has curl installed; I’ll use that to access nginx.

bash-4.3# curl http://localhost:8080
curl: (7) Failed to connect to localhost port 8080: Connection refused

Looks like I cannot access nginx from inside the maven container. Why? Well, that’s because the port mapping that we used to spin up the nginx container using -p 8080:80 bound 8080 to docker’s host machine. Because we are using DooD, the host is not the maven container, but the host machine.

Resolution:

Host Network

There are a few ways to solve this. First, we could start up the maven container and tell it to uses the host network using the --network flag.

$ docker run -it --rm  -v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock --network host  maven:3.5.2-jdk-8-alpine bash

Now the maven container is running on the same network as the host. While inside the maven container, let’s access the nginx container that should still be running in detached mode using curl http://localhost:8080.

bash-4.3# curl http://localhost:8080

...

<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

...

<!-- content truncated for brevity -->
bash-4.3#

Nice. Now we can access localhost on the host machine. This works, but you may not want a container to run on the host network. Let’s exit out of this maven container and try another option.

User Defined Network

Stop the nginx container by doing a docker stop on the container id.

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
1f0496344e31        nginx:latest        "nginx -g 'daemon of…"   22 minutes ago      Up 25 minutes       0.0.0.0:8080->80/tcp     dreamy_davinci
$ docker stop 1f0496344e31
1f0496344e31

Next I will run our both the maven container and the nginx container on the same user defined network called demo. First, I’ll create the network.

$ docker network create --driver bridge demo
685407a62649f78ce3a8f67a5975e87f658ac34082e6277270ffb6fd92d57f84

Now I’ll run the maven container on that network.

$ docker run -it --rm --network demo  -v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock  maven:3.5.2-jdk-8-alpine bash
bash-4.3#

Next, I will run the nginx container on that same network. This time, we are going to give the container a --name so we can access it using that name.

bash-4.3# docker run --rm -d --network demo --name mynginx  -p 8080:80 nginx:latest
aac04d31d0cccaff2368b58f25107948b0159edbcbef1453305f047ee5b365fc

Because of the -p 8080:80 flag, nginx will still be accessible on localhost. It will not be accessible on localhost of the maven container, but I should be able to use the nginx container name from the maven container since they are on the same network. This time, I’ll use the command curl http://mynginx:80.

bash-4.3# curl http://mynginx:80

...

<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

...

<!-- content truncated for brevity -->

It works! Notice I did not use port 8080 in my curl command. This is because 8080 is only exposed on localhost. Because both containers are on the same network, I can access ports directly inside the nginx container.

Container Ip

Without adding a custom network, we still can access the nginx container from the maven container using the container’s IP address. I’ll get the ip address of our nginx container by inspecting it.

bash-4.3# docker inspect df6 -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
172.17.0.2

Now I can curl the container by ip and access the port in the container. Note: The containers are not required to be on a custom network for this work. They do, however, need to be on the same network even if it’s the default one.

bash-4.3# curl http://172.17.0.2:80

...

<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

...

<!-- content truncated for brevity -->
bash-4.3#

Success!

All of these methods allow containers to talk with each other wether you are using DooD or not. Just remember if you are using DooD, then port mapping via the -p flag always binds to the host machine, not the container you are running in.

Leave a Reply

Your email address will not be published. Required fields are marked *