Deploying a minimal flask app in docker - server connection issues

I have an app who's only dependency is flask, which runs fine outside docker and binds to the default port 5000. Here is the full source:

    from flask import Flask

    app = Flask(__name__)
    app.debug = True

    @app.route('/')
    def main():
        return 'hi'

    if __name__ == '__main__':
        app.run()

The problem is that when I deploy this in docker, the server is running but is unreachable from outside the container.

Below is my Dockerfile. The image is ubuntu with flask installed. The tar just contains the index.py listed above;

    # Dockerfile
    FROM dreen/flask
    MAINTAINER dreen
    WORKDIR /srv

    # Get source
    RUN mkdir -p /srv
    COPY perfektimprezy.tar.gz /srv/perfektimprezy.tar.gz
    RUN tar x -f perfektimprezy.tar.gz
    RUN rm perfektimprezy.tar.gz

    # Run server
    EXPOSE 5000
    CMD ["python", "index.py"]

Here are the steps I am doing to deploy

$> sudo docker build -t perfektimprezy .

As far as I know the above runs fine, the image has the contents of the tar in /srv. Now, let's start the server in a container:

    $> sudo docker run -i -p 5000:5000 -d perfektimprezy
    1c50b67d45b1a4feade72276394811c8399b1b95692e0914ee72b103ff54c769

Is it actually running?

    $> sudo docker ps
    CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS                    NAMES
    1c50b67d45b1        perfektimprezy:latest   "python index.py"   5 seconds ago       Up 5 seconds        0.0.0.0:5000->5000/tcp   loving_wozniak

    $> sudo docker logs 1c50b67d45b1
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
     * Restarting with stat

Yep, seems like the flask server is running. Here is where it gets weird. Lets make a request to the server:

     $> curl 127.0.0.1:5000 -v
     * Rebuilt URL to: 127.0.0.1:5000/
     * Hostname was NOT found in DNS cache
     *   Trying 127.0.0.1...
     * Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
     > GET / HTTP/1.1
     > User-Agent: curl/7.35.0
     > Host: 127.0.0.1:5000
     > Accept: */*
     >
     * Empty reply from server
     * Connection #0 to host 127.0.0.1 left intact
     curl: (52) Empty reply from server

Empty reply... But is the process running?

    $> sudo docker top 1c50b67d45b1
    UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
    root                2084                812                 0                   10:26               ?                   00:00:00            python index.py
    root                2117                2084                0                   10:26               ?                   00:00:00            /usr/bin/python index.py

Now let's ssh into the server and check...

    $> sudo docker exec -it 1c50b67d45b1 bash
    root@1c50b67d45b1:/srv# netstat -an
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State
    tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN
    tcp        0      0 127.0.0.1:47677         127.0.0.1:5000          TIME_WAIT
    Active UNIX domain sockets (servers and established)
    Proto RefCnt Flags       Type       State         I-Node   Path
    root@1c50b67d45b1:/srv# curl -I 127.0.0.1:5000
    HTTP/1.0 200 OK
    Content-Type: text/html; charset=utf-8
    Content-Length: 5447
    Server: Werkzeug/0.10.4 Python/2.7.6
    Date: Tue, 19 May 2015 12:18:14 GMT

It's fine... but not from the outside :( What am I doing wrong?

The problem is you are only binding to the localhost interface, you should be binding to 0.0.0.0 if you want the container to be accessible from outside. If you change:

    if __name__ == '__main__':
        app.run()

to

    if __name__ == '__main__':
        app.run(host='0.0.0.0')

It should work.

From: stackoverflow.com/q/30323224

Back to homepage or read more recommendations: