Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Port Publishing When Running with Docker Compose

I can't seem to work out a way to get port publishing to work with docker-compose run in the same way as I can with docker run.

Using Docker Compose (and therefore the port mapping in docker-compose.yml) gives a "Failed to connect" error from curl:

$ docker-compose run flask  * Running on http://0.0.0.0:2048/ (Press CTRL+C to quit)  $ curl http://localhost:2048/ curl: (7) Failed connect to localhost:2048; Connection refused 

However, things are fine when manually passing the ports to docker run:

$ docker run -p 2048:2048 --name flask -t flask_image  * Running on http://0.0.0.0:2048/ (Press CTRL+C to quit)  $ curl http://localhost:2048 Hello World! 

What am I missing?


Dockerfile

FROM centos:7  # Install EPEL repo. RUN rpm -iUvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm  # Install Python and Pip. RUN yum -y update && yum -y install \     python \     python-pip  # Flask is necessary to run the app. RUN pip install flask  EXPOSE 2048  ADD hello_world_flask_app.py /src/hello_world_flask_app.py CMD ["python", "/src/hello_world_flask_app.py"] 

hello_world_flask_app.py

from flask import Flask app = Flask(__name__)  @app.route("/") def hello():     return "Hello World!"  if __name__ == "__main__":     app.run(host='0.0.0.0', port=2048) 

docker-compose.yml

version: '2' services:   flask:     build: .     ports:       - "2048:2048" 
like image 638
JimmidyJoo Avatar asked Mar 30 '16 21:03

JimmidyJoo


People also ask

Does Docker compose publish ports?

Docker Compose exposes all specified container ports, making them reachable internally and externally from the local machine. Once again, in the PORTS column, we can find all the exposed ports. The value to the left of the arrow shows the host address where we can reach the container externally.

What is published port in Docker?

Publishing Ports Publishing a port makes it accessible from outside the container. It lets you take a port you've discovered by an EXPOSE instruction, then bind a host port to it. This command binds port 8080 on your Docker host to 80 inside your new container.

How do you expose a port to a host?

You can expose a port through your Dockerfile or use --expose and then publish it with the -P flag. This will bind the exposed port to your Docker host on a random port (verified by running docker container ls ). You can expose a port through your Dockerfile or use --expose and then publish it with the -p 80:80 flag.


2 Answers

By default, docker-compose run does not publish the service's ports. You can either pass the --service-ports option to publish the ports as they are defined in the docker-compose.yml, or use the -p option to publish all ports.

See the documentation for docker-compose run

like image 68
thaJeztah Avatar answered Nov 11 '22 09:11

thaJeztah


EDIT

Tried with --service-ports (it doesn't work with up command and we should somehow stop and run it again) also it doesn't change this behavior, ports are exposed but can't curl and unreachable for mentioned reasons from 127.0.0.1


This is due to fact that you are using docker-compose 2 syntax.

By default it creates an internal network ( or overlay network in some cases) between each compose project containers.

You can use docker inspect <container_name> to get container network status.

Also using netstat It gives a strange behavior from docker which seems only listens on tcp6 interfaces :

$ sudo netstat -lt|grep 2048    tcp6       0      0 [::]:2048           [::]:*         LISTEN      501/docker 

Possible Solutions :

1- Curl from outside host! it works :)

C:\Users\pooya>curl host:2048 Hello World! 

2- Specify Localhost IP (127.0.0.1) in ports Section :

$ cat docker-compose.yml version: '2' services:   flask:       build: .       ports:         - "127.0.0.1:2048:2048" 

And you can simply curl using curl localhost:2048

3 - Change network driver (network_mode) to bridge

** This method doesn't works anymore on newer docker versions **

4- Curl from host`s ip instead of 127.0.0.1


So what was the problem ?

It seems the root problem is from docker bridge method. docker uses iptables to nat INCOMING connections to the correct container's port

$ sudo iptables -L|grep 2048 ACCEPT     tcp  --  anywhere             10.0.0.12            tcp dpt:2048 

As you can see it only dports incoming connections to 10.0.0.12:2048


Wait, what about not using docker-compose ??

Strange ! but to just correctly listens to 0.0.0.0 and everything is fine :)

$ docker run -it -d  -p 2048:2048 test $ netstat -ltn|grep 2048 tcp        0      0 0.0.0.0:2048   0.0.0.0:*               LISTEN 
like image 43
Pooya Avatar answered Nov 11 '22 10:11

Pooya