How to dockerize a Python application?


Welcome to the next pikoTutorial!

If you ever wanted to ensure a consistent environment for your application, you most probably know that containerization is the way to go. To containerize a Python application, let’s first set up a simple file structure:

python_docker
|- src
|  |- app.py
|- Dockerfile
|- requirements.txt

Now add a simple Python application:

import time

if __name__ == '__main__':
    while True:
        print('Hello from the inside of the container', flush=True)
        time.sleep(1)

Note for beginners: You may be wondering why flush is added at the end of the print function. When running inside a Docker container, the standard output (stdout) is often connected to a pipe rather than a direct terminal. Python buffers output to be efficient, sending data only when the buffer is full, the program ends, or flush is explicitly requested. Without flush, logs may appear all at once when the container stops, rather than appearing every second. When running the same application in a system terminal, you don’t need flush since stdout switches to line buffering, which flushes the buffer when a newline character is encountered.

Having this, it’s time to write the Dockerfile:

# Use an official Python runtime as a parent image
FROM python:3.9-slim
# Set the working directory in the container
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Run app.py when the container launches
CMD ["python", "app.py"]

When the Dockerfile is ready, you can build a Docker image by running the following command:

docker build -t python_docker_image .

If you don’t want to use sudo every time when calling docker command, you may want to change the permissions of one of the docker files by running sudo chmod 666 /var/run/docker.sock.

Note for beginners: remember that changing permissions of /var/run/docker.sock may have consequences related to security, so you want to think twice before you do this in the production environment!

After successful build, you can check the list of the images by running:

docker images

This will show you a table like the following:

REPOSITORY            TAG       IMAGE ID       CREATED              SIZE
python_docker_image   latest    e132d245100b   About a minute ago   132MB

To create a container out of your image, use command:

docker run python_docker_image

This is the simplest form of this command, but most likely you would like to extend it with the following option and flags:

  • --rm – removes container after it has been stopped
  • --name – allows you to assign a custom name to your container (otherwise Docker will choose some random name)
  • -d – detaches process from your current terminal what effectively makes the container to run in the background.

Eventually our command looks like this:

docker run --rm --name my_python_application -d python_docker_image

Now you can check the table of currently running containers with docker ps command. If everything went ok, you should see such output:

CONTAINER ID   IMAGE                 COMMAND               CREATED         STATUS         PORTS     NAMES
005a84629e1b   python_docker_image   "python src/app.py"   3 seconds ago   Up 2 seconds             my_python_application

Finally, let’s look at the logs from the application. Run docker logs my_python_application and check if you see the following output:

Hello from the inside of the container
Hello from the inside of the container
Hello from the inside of the container

If yes, you’ve just successfully containerized a Python application.

Note for beginners: if you leave the container like this, it will run in the background forever. To stop the application, run docker container stop my_python_application command.

Note for advanced: if you need more in-depth look into your container, you can get inside the container’s shell terminal using command docker container exec -it my_python_application /bin/bash. You can also do this at the container startup by using command docker run -it python_docker_image /bin/bash.