Clicky

How To Dockerize a Flask Application

ProgrammingAugust 21, 2023
red and black plastic crates

Introduction

If you want to manage applications effectively, Docker is a great tool to use. With Docker, isolating application services is convenient; it ensures that your application remains unaffected by changes in dependencies. This article will provide a detailed guide on how to Dockerize your Flask application, using Python 3 and Gunicorn.

Basic Flask Application

To illustrate this process, we’ll use a simple Flask application. In your working directory, make a new file hello.py:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return "Hello, world!"

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

This is a basic Flask application that returns the phrase “Hello, world!” when accessed.

Dockerizing the Flask Application

Dockerizing the flask application involves building a Docker image that runs Gunicorn to serve the Flask application.

Why Use Gunicorn

While Flask’s built-in server is great for development, it is not suitable for production deployment. Gunicorn, which is a WSGI HTTP Server, is used in production setups. It’s well-suited for collaborating with NGINX or Apache, is stable and has many configuration options making it an excellent choice.

Dockerfile

Create a Dockerfile in the same directory with the following content:

# Use an official Python runtime as a parent image
FROM python:3.11-slim

# Set the working directory in the container to /app
WORKDIR /app

# Add current directory content to /app in the container
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 8000 available to the world outside this container
EXPOSE 8000

# Run gunicorn when the container launches
CMD ["gunicorn", "-b", ":8000", "hello:app"]

requirements.txt

This file contains all the dependencies for the flask application. For our application, requirements.txt should look like this:

Flask>=2.3.2
gunicorn>=21.2.0

Build the Docker Image

Now, we can build our Docker image. Run the following command in the console:

docker build -t flaskapp .

Substitute flaskapp with your desired image name. This builds your Docker image.

Run the Docker Container

To make your application accessible, run the Docker container using the following command:

docker run -p 4000:8000 flaskapp

Here, -p 4000:8000 ensures that the traffic coming in on port 4000 of the host machine gets directed to port 8000 on the Docker container, where Gunicorn is listening. Replace 4000 with your desired port on the host machine.

When to Set Up a Reverse Proxy

Your host machine may be running Apache or Nginx, in which case, you might need to set up a reverse proxy.

A reverse proxy is typically necessary when you have multiple applications running on different networks and ports. It can also provide additional benefits like load balancing, SSL termination, and serving static content.

Handling a SQLite Database or Uploaded Files in a Persistent Data Store

In the case of SQLite databases or file uploads, data persistence becomes paramount. Docker containers are ephemeral, meaning that all data associated with the container ‘disappears’ once the container shuts down. To provide data persistence, we use Docker volumes.

For example, let’s assume we have a SQLite database mydb.sqlite3 for our Flask application in a dbs directory. We would map this directory to a directory in the container to read/write data persistently like this:

docker run -p 4000:8000 -v $(pwd)/dbs:/app/dbs flaskapp

This makes the mydb.sqlite3 persistent across different container “lives” because now it’s actually stored on the host file system, but still accessible from the app.

This ends our tutorial on Dockerizing Flask applications. Docker increases productivity while reducing the time required to develop and ship new application features. It fits seamlessly into the development life cycle and transforms the development environment to a time-saving and more efficient one.