loading...

How to containerize a Python Application

barrachri profile image Christian Barra Updated on ・4 min read
Containers are everywhere, but how do you run a Python application inside a Docker container? This article will show you how!

In case you are wondering, the examples require Python 3.x.

Before diving into containers, let’s talk a bit more about the Python application we want to containerize.

The application is a web API that returns a random movie from a movie collection. Inside our local folder we have 3 files:

app.py # Python application
movies.json # movie collection
requirements.txt # where we specifiy our Python dependencies

app.py contains one API endpoint that returns a random movie:

import os
import json
from pathlib import Path
from random import choice
import cherrypy

PORT = os.environ.get('PORT', 8888)

FOLDER_PATH = Path(__file__).parent

with open(FOLDER_PATH / "movies.json", "r") as f:
    MOVIES = json.loads(f.read())

class Movie:
    @cherrypy.expose
    @cherrypy.tools.json_out()
    def index(self):
        return {"movie": choice(MOVIES)}

cherrypy.quickstart(
    Movie(), config=cherrypy.config.update({
        'server.socket_host': '0.0.0.0',
        'server.socket_port': PORT,
        }))

Inside requirements.txt, we have our dependencies and after running

pip install -r requirements.txt

we are able to run our application with python app.py.

Running curl localhost:8888 should return a random movie, something like:

{
  "movie": {
    "Title": "Opal Dreams",
    "US_Gross": 14443,
    "Worldwide_Gross": 14443,
    "US_DVD_Sales": null,
    "Production_Budget": 9000000,
    "Release_Date": "Nov 22 2006",
    "MPAA_Rating": "PG",
    "Running_Time_min": null,
    "Distributor": "Strand",
    "Source": "Based on Book/Short Story",
    "Major_Genre": "Drama",
    "Creative_Type": "Contemporary Fiction",
    "Director": null,
    "Rotten_Tomatoes_Rating": null,
    "IMDB_Rating": 6.5,
    "IMDB_Votes": 468
  }
}

Cool, the application is working!

How do we containerize our application?

Containerizing a Python application means creating a Docker image that has everything needed to run it: source code, dependencies and configuration..

The first step to containerize our application is to create a new text file, named Dockerfile:

app.py
movies.json
requirements.txt
Dockerfile

Inside the Dockerfile (for what we consider a minimal viable Dockerfile), we need to specify three steps:

  • Select the base image we want to use
  • Select the files we want to copy inside the Docker image
  • Install the app's dependencies

Base image

To specify a base image, we use the FROM command followed by either a private or public image.

In our case, we will use the official Python Docker image, available on the Docker hub.

We will select the latest available Python 3 image based on Ubuntu.

# 1. Base image
FROM python:3.8.5-slim-buster

The image name is made up of two different parts: image:tag. In our case the image is python and the tag is 3.8.5-slim-buster.

That's everything we need for the first step.

Copy our application

To copy our application inside the Docker image, we will use the COPY command:

# 2. Copy files
COPY . /src

This command copies the specified files (or folder) into the Docker image. In our case, we want to copy all files available in our local folder inside the Docker image under the /src path.

It's important to note that the first part of the COPY command is a path relative to the context of the build and not to our local machine.

Install the requirements.txt

The last step is to install our dependencies inside the Docker image. To achieve that we will use the RUN command to RUN pip install:

# 3. Install our deps
RUN pip install -r /src/requirements.txt

One thing to notice is that the path of requirements.txt is different compared with the first time we ran pip install.

The reason behind this is that the copied files are under the /src path inside the image.

Build and run a Docker image

# 1. Base image
FROM python:3.8.3-slim-buster

# 2. Copy files
COPY . /src

# 3. Install our deps
RUN pip install -r /src/requirements.txt

Our Dockerfile is now complete and we can use it to build a Docker image. For that we need to use the docker build command:

docker build -t movie-recommender .

This command builds a Docker image named movie-recommender using your current folder as building context (the . at the end specifies the path of the building context we want to use).

Now we can run the image we just built using the docker run command:

docker run movie-recommender python /src/app.py

This command will execute python /src/app.py inside a container based on the movie-recommender image.

However, if we try to connect to our application using curl localhost:8888, we will get an error.

How is that possible? Why can't we connect to our application that runs inside the container?

The reason is that we didn’t expose our application's port to the local machine. We can do that by using the -p HostPort:ContainerPort flag.

So let’s try to rerun the command again, this time specifying that we want to expose port 8888 locally:

docker run -p 8888:8888 movie-recommender python /src/app.py

and then curl localhost:8888.

Now it works—great! We just containerized a Python application!

Quick recap

  • Containerizing an application means to create a Docker image that has everything needed to run it—source code, libraries, and configuration.
  • We used a Dockerfile to specify how to build a Docker image.
  • docker build builds a Docker image starting from a Dockerfile.
  • docker run runs a container using a Docker image.

Useful resources

Posted on by:

barrachri profile

Christian Barra

@barrachri

Technical Lead at INFARM • Trainer • Founder • @ThePSF Fellow

Discussion

pic
Editor guide