Deploying a minimal flask app in docker – server connection issues

Posted on

Problem :

I have an app whose 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
def main():
    return 'hi'
if __name__ == '__main__':

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 listed above;

# Dockerfile
FROM dreen/flask

# 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
CMD ["python", ""]

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

Is it actually running?

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

$> sudo docker logs 1c50b67d45b1
 * Running on (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 -v
 * Rebuilt URL to:
 * Hostname was NOT found in DNS cache
 *   Trying
 * Connected to ( port 5000 (#0)
 > GET / HTTP/1.1
 > User-Agent: curl/7.35.0
 > Host:
 > Accept: */*
 * Empty reply from server
 * Connection #0 to host 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
root                2117                2084                0                   10:26               ?                   00:00:00            /usr/bin/python

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*               LISTEN
tcp        0      0          TIME_WAIT
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
root@1c50b67d45b1:/srv# curl -I
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?

Solution :

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

if __name__ == '__main__':


if __name__ == '__main__':'')

It should work.

Note that this will bind to all interfaces on the host, which may in some circumstances be a security risk – see for more information on binding to a specific interface.

When using the flask command instead of, you can pass the --host option to change the host. The line in Docker would be:

CMD ["flask", "run", "--host", ""]


CMD flask run --host

Your Docker container has more than one network interface. For example, my container has the following:

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet brd scope global eth0
       valid_lft forever preferred_lft forever

if you run docker network inspect bridge, you can see that your container is connected to that bridge with the second interface in the above output. This default bridge is also connected to the Docker process on your host.

Therefore you would have to run the command:

CMD flask run --host

To access your Flask app running in a Docker container from your host machine. Replace with whatever the particular IP address is of your container.

You need to modify the host to in the docker file. This is a minimal example

# Example of Dockerfile

FROM python:3.8.5-alpine3.12



COPY . /app
RUN pip install -r requirements.txt

ENTRYPOINT [ "flask"]
CMD [ "run", "--host", "" ]

and the file is

from flask import Flask

app = Flask(__name__)

def home():
    return "Hello world"

if __name__ == "__main__":

Then compile with

docker build . -t deploy_flask

and run with

docker run -p 5000:5000 -t -i deploy_flask:latest

You can check the response with curl -v

First of all in your python script you need to change code from


Second, In your docker file, last line should be like

CMD ["flask", "run", "-h", "", "-p", "5000"]

And on host machine if doesn’t work then you should try with localhost:5000

Note – The CMD command has to be proper. Because CMD command provide defaults for executing container.

To build on other answers:

Imagine you have two computers. Each computer has a network interface (WiFi, say), which is its public IP. Each computer has a loopback/localhost interface, at This means “just this computer.”

If you listed on on computer A, you would not expect to be able to connect to that via when running on computer B. After all, you asked to listen on computer A’s local, private address.

Docker is similar setup; technically it’s the same computer, but the Linux kernel is allowing each container to run with its own isolated network stack. So in a container is the same as on a different computer than your host—you can’t connect to it.

Longer version, with diagrams:

For fast readers, three quick things to check:

  1. Make sure you have exposed the port in the Dockerfile.
  2. Running the command in container using flask run --host=
  3. Specifying the port in your docker run command docker run -it -p5000:5000 yourImageName

Leave a Reply

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