Port Publishing When Running with Docker Compose

64,604

Solution 1

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

Solution 2

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
Share:
64,604
JimmidyJoo
Author by

JimmidyJoo

Updated on November 26, 2020

Comments

  • JimmidyJoo
    JimmidyJoo over 3 years

    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"
    
  • JimmidyJoo
    JimmidyJoo about 8 years
    Oh. Not one of my finer moments, this. I guess posting SO questions while bleary-eyed at the end of a working day is not a good idea in general... Sorry for wasting your time and thanks for the help.
  • JimmidyJoo
    JimmidyJoo about 8 years
    Accepted theJeztah's answer but there is still some good information here. Strangely enough, --service-ports worked fine enough for me.
  • JimmidyJoo
    JimmidyJoo about 8 years
    @thaJezah. I have a further issue which is related enough so as not to deserve a separate question. On Mac OS (running Docker Machine) using --service-ports with docker-compose does not solve the problem when using curl from the host -- the -p option is the only way to solve it. Is this a bug I should be submitting as a GitHub Issue or am I missing something else?
  • thaJeztah
    thaJeztah about 8 years
    The --service-ports should publish the ports as they are defined in the yaml file, but perhaps it's not done if the actual service is already running? If it doesn't work, then definitely open an issue on GitHub (but be sure to search for existing ones). I haven't followed the docker-compose issue tracker closely the last few weeks, so perhaps it's a known issue.
  • Luke101
    Luke101 almost 7 years
    Any update on this issue? I am running into this now.
  • Elle Mundy
    Elle Mundy almost 6 years
    Strange how this isn't documented right next to the ports option here
  • franck
    franck over 5 years
    2) doesn't seem to work anymore : I'm getting this error ignoring IP-address (127.0.0.1:6379:6379/tcp) service will listen on '0.0.0.0'
  • Mog0
    Mog0 almost 3 years
    @Elle Mundy It is documented in the ports section of the v3 docs here