Dockerizing a Python Flask Application

Dockerizing a Python Flask Application

Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.

– from What Is Docker?

If you are new to Docker, this guide will show you how to create a basic Docker container.

I have a small Python Flask web application that I want to put inside a Docker container. I also want to run the web application using a server called uwsgi. Dockerizing a Python Flask application will give you a straightforward intro into Docker containers.

Build a Docker Container

Contents of ./requirements.txt
This file specifies software dependencies needed for our web application.

Flask==0.10.1
itsdangerous==0.24
Jinja2==2.8
MarkupSafe==0.23
Werkzeug==0.11.5

Contents of ./app.py

from flask import Flask


app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"


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

Contents of ./Dockerfile

FROM ubuntu:14.04

# Update OS
RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y upgrade

# Install Python
RUN apt-get install -y python-dev python-pip

# Add requirements.txt
ADD requirements.txt /webapp

# Install uwsgi Python web server
RUN pip install uwsgi
# Install app requirements
RUN pip install -r requirements.txt

# Create app directory
ADD . /webapp

# Set the default directory for our environment
ENV HOME /webapp
WORKDIR /webapp

# Expose port 8000 for uwsgi
EXPOSE 8000

ENTRYPOINT ["uwsgi", "--http", "0.0.0.0:8000", "--module", "app:app", "--processes", "1", "--threads", "8"]

In this configuration:

First, we update the Ubuntu OS that is shipped with the container:

RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y upgrade

Next, we install Python, Python development files and a package manager for Python. Since we are using a Debian-based OS inside the container, apt-get is used to install packages. This may be different, depending on the flavor of Linux you ship:

# Install Python
RUN apt-get install -y python-dev python-pip

Next, we install all dependencies needed for our app. This is donebeforeadding our application files to the container because Docker will skip this step if requirements.txt has not changed upon subsequent builds. Every Docker command builds a layer that is cached and if a single layer is changed, Docker will invalidate this cache. This ordering will prevent our dependencies from being reinstalled upon changes to our application code.

# Add requirements.txt
ADD requirements.txt /webapp

# Install uwsgi Python web server
RUN pip install uwsgi
# Install app requirements
RUN pip install -r requirements.txt

Next, we add all application files to the /webapp directory inside the container:

# Create app directory
ADD . /webapp

Next, we set the working directory to /webapp:

# Set the default directory for our environment
ENV HOME /webapp
WORKDIR /webapp

Next, port 8000 is exposed to allow communication to the container. By default, no ports are exposed:

# Expose port 8000 for uwsgi
EXPOSE 8000

Finally, we specify the command to run when the container is started:

ENTRYPOINT ["uwsgi", "--http", "0.0.0.0:8000", "--module", "app:app", "--processes", "1", "--threads", "8"]

Alternatively, we can set the ENTRYPOINT to a command without flags. This will allow flags to be specified when the container is initialized:

ENTRYPOINT ["uwsgi"]

Build the Docker container:

docker build --no-cache --rm -t travcunn/flask .

Run the Container

docker run -d \ 
  --cpuset-cpus 1 \
  --name flask \
  --restart=always \
  travcunn/flask

In this configuration:

  • -d runs the container in detached mode. To run the container in the foreground, remove this flag.
  • –cpuset-cpus 1 restricts the container to use only 1 CPU. To remove this restriction, remove this flag.
  • –name flask allows custom container names, where we assign the container name “flask”. If a name is not specified, Docker will automatically assign one.
  • –restart=always will automatically restart the container if the application exits.
  • travcunn/flask specifies the image for the container, which was built in a previous step.

Test Your Container

Once the container is running, we can check if the web server is running.

When a Docker container is started, it is automatically assigned an IP address that is accessible only to your local machine. To check our HTTP server, we need to find the IP address of the container. First, find the container ID:

> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5987b02d8c61 travcunn/flask "uwsgi --http 0.0.0.0" 7 seconds ago Up 6 seconds 8000/tcp flask

Next, inspect the container to find the IP:

> docker inspect --format '{{ .NetworkSettings.IPAddress }}' 5987b02d8c61
172.17.0.2

Now visit: http://172.17.0.2:8000 or the IP address of the container in your web browser. You should see a response from the server running inside your container.

Stay Tuned

I hope you enjoyed this article on dockerizing a python flask application. Stay tuned for future Docker posts about application service discovery, connecting Docker containers, and using databases with Docker applications.

SmartFile is a business file mangement platform that gives you more control, compliance and security.

TO SIGN UP