Run Python in Raspberry PI Containers with Docker

4
(1)

Last Updated on 1st December 2024 by peppe8o

This tutorial will show you how to setup and run Python in Raspberry PI Containers with Docker so that you can run your Python script in isolated containers.

Why Running Python Scripts in Docker Containers

Containers have been a revolution in ICT: they are used in large infrastructures as well as in small projects because they allow developers to keep their programs isolated from the host machine and easy to manage.

docker-logo

Together with Python, containers can allow you to run your scripts and apps in an efficient environment, bringing many advantages:

  • Portability: Docker containers can include all the Python libraries and configurations you need inside the container. This will allow you to run the same Python script in any environment (development, testing, production) and host without worrying about versions or dependencies. With the use of a Dockerfile you can completely define the environment, making it easy to reproduce the same setup or backup it for a new installation or for moving to a Cloud environment.
  • Isolation: Containers are isolated from the host machine so that the installed libraries will not affect other Python scripts running on the same PC. Moreover, you can use different library versions on the same PC (by using different containers), preventing any conflict or interference.
  • upgrades/downgrades: with containers you can test different versions of Python or any other dependency without affecting the working container, so you can try the newest Python versions without risking breaking other parts of your system.
  • Reproducibility for Data Science / Machine Learning Projects: with Docker, you can package complex dependencies like machine learning libraries (e.g., TensorFlow, PyTorch, scikit-learn) and datasets in a container. This allows you to easily reproduce and share the entire environment with others.

Differently from Python virtual environments, Docker containers allow you to have higher isolation from the host system, as the latter also isolates the OS components. Moreover, Docker containers allow you to scale up the infrastructure as you need.

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if to continue with the project or remove them from the shopping cart. So, hardware will be only:

raspberry-pi-5-model-b-board

Step-by-Step-Procedure

Prepare the Operating System and Install Docker

The first step is installing the Raspberry PI OS Lite (please note that we need the 64-bit version) to get a fast and light operating system (headless). In this case, you will need to work from a remote SSH terminal. If you need a desktop environment, you can also use the Raspberry PI OS Desktop, in this case working from its terminal app. Please find the differences between the 2 OS versions in my Raspberry PI OS Lite vs Desktop article.

Make sure that your OS is up to date. From your terminal, use the following command:

sudo apt update -y && sudo apt upgrade -y

We also need to install Docker. For this process, please refer to my Beginner’s Guide to Install and Use Docker with Raspberry PI. Please make sure to enable your user to use Docker without the need of sudo.

Python Containers with Docker Hub

When using Docker, you can get free images from something like a marketplace: the Docker Hub. It includes a huge number of container images (from official and unofficial authors), supporting different platform architectures (386, amd64, arm v5, arm v7, arm64, ppc64le, and so on). From these images, we can use only those compatible with our Raspberry PI. Generally, the official Python images support all the Raspberry PI architectures. If you’re curious about your one, you can check it with the hostnamectl command. In my case:

pi@raspberrypi:~ $ hostnamectl
 Static hostname: raspberrypi
       Icon name: computer
      Machine ID: 1a2846ba11a84f068bf682dcba26cce3
         Boot ID: 1209cc6b4ba74ac5904f46e1e7a28a6b
Operating System: Debian GNU/Linux 12 (bookworm)
          Kernel: Linux 6.6.47-v8+
    Architecture: arm64

About the Python images, there are different tags available from the Python page in Docker Hub. At the date of this tutorial, the “3” tag is the most complete and most recent, but it requires a bit of disk space (the uncompressed image takes around 1GB).

There are many alternative images like, for example, those having “slim” in the tag name, which require less space. On the other hand, these images may not support all the library installations you may need. So, you have to test them.

In this tutorial, we’ll use the “Python:3” image. Moreover, we’ll build our custom container starting from this image, adding the needed libraries.

Hello World Python in Raspberry PI Container

Our Hello World container doesn’t make real sense as you don’t need to install any library and you can just run a Python script printing “Hello World!” without the need for any container. Nevertheless, it’s important to understand how to approach Python containers.

Before starting, I suggest you create a specific folder for docker and, inside it, specific subfolders for any project. In this way, your life will be simpler if you will backup your Raspberry PI folders for security purposes. Moreover, inside the project, you can create an “app” folder which will include all your scripts.

So, please create the folder path:

mkdir docker/python-hello/app -p

Enter to the app folder:

cd docker/python-hello/app/

Here we’ll create our very simple hello world script:

nano myscript.py

Put the following print statement inside the container. It will just print a simple message in your console:

print("Hello world by peppe8o.com")

Save and close. Now, you can go to the upper level, where we’ll create our Docker build environment:

cd ..

The Hello-World Dockerfile

Create a file named “Dockerfile”. It is important to note that it is the default name for the docker build command, which we’ll use to create a custom image with our Python script.

nano Dockerfile

Fill the file with the following content:

FROM python:3
WORKDIR /usr/src/app
COPY ./app/myscript.py ./
CMD [ "python3", "./myscript.py" ]

Save and exit. It tells Docker to perform the following operations while building our custom image:

  1. use the python:3 image getting it from Docker Hub (if not available locally)
  2. set the Working Directory to /usr/src/app inside the container (move to it inside the container)
  3. Copy the file myscript.py from the host storage (inside the app folder previously created) to the container (inside the current Working Directory)
  4. set as main command of the container the command “python3 ./myscript.py” (running it from the Working Directory).

The main command is one of the most important things in containers, as containers live as long as the main command has something to do. When the main command exits (for example because it ended its job or returned an error) the container “dies”.

At this point, your folder should be as follows:

└── docker
    └── python-hello
        ├── app
        │   └── myscript.py
        └── Dockerfile

Build and Run the Hello-World Script

Now, we can build our custom Docker image. From the folder where the Dockerfile is located, please issue the following command:

docker build -t my-python-hello . --no-cache

It will start by downloading the base image (only for the first build) and preparing the container according to the Dockerfile. From this command:

  • -t my-python-hello“: it gives a name (tag) for your custom image in your Docker environment. You can also add a colon after the image name and give it a specific version (for example “my-python-hello:0.1”). You can list all the current images in your Raspberry PI with the docker images command.
  • “.”: the dot in the command may appear as a banal option. It tells the Docker build command to set the current folder as build context. This means that it will look for the Dockerfile in the current folder and search any required resource inside it
  • –no-cache“: you may need to build several times the same container image as you test different options and/or different Dockerfiles. This option avoids that Docker uses cached layers, making your changes ineffective

With the new container built, you can run it with the following docker run command:

docker run -it --rm my-python-hello

It will execute the print statement and return the set hello message:

pi@raspberrypi:~/docker/python-hello $ docker run -it --rm my-python-hello
Hello world by peppe8o.com

Please note that the “–rm” option in the above docker run command will delete the container after it finishes the job.

Complex Python Raspberry PI Containers

More complex projects will require installing dependencies and sharing data between the host and container. In these cases, we must add a “pip” installation step in the Dockerfile and map a volume for the static data of your container. I will show you how to perform these actions by using as an example a web crawler with Python and Scrapy.

Let’s go back to the “docker” folder, create a new subfolder for this project, and enter it:

cd ..
mkdir py-crawler
cd py-crawler

The first file to prepare is the requirement.txt, which will include all the Python libraries to install via PIP:

nano requirements.txt

This project requires only 2 libraries: “scrapy” and “cryptography”. You can paste these 2 libraries inside the requirements.txt file. Please note that you can optionally specify the versions, as in any requirements.txt file.

scrapy
cryptography

Save and close.

Now, let’s create the “app” folder, which will include the running script together with all the data we’ll create from the container, and enter it:

mkdir app
cd app/

Let’s create our Python script:

nano my-crawler.py

And paste here the crawler code:

import scrapy
class QuotesSpider(scrapy.Spider):
  name = "peppe8o"
  start_urls = [
    'https://peppe8o.com',
  ]

  def parse(self, response):
    for posts in response.css('div.post-wrapper article'):
      yield {
        'Title': posts.css('h2.entry-title a::text').get(),
        'Description': posts.css('div.post-content p::text').get(),
        'Date': posts.css('time::text').get(),
      }

Save and close.

The Python Dockerfile

Now, back to the higher level folder, let’s create our Dockerfile:

cd ..
nano Dockerfile

Paste the following lines:

FROM python:3
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY ./app/my-crawler.py ./my-crawler.py
CMD ["scrapy", "runspider", "my-crawler.py", "-o", "peppe8o.json"]

Save and close. Differently from the previous Dockerfile, this includes the copy of the requirements.txt file and the installation of all the packages in the “RUN” line.

At this point, your directory should be as follows:

└── docker
    └── py-crawler
        ├── app
        │   └── my-crawler.py
        ├── Dockerfile
        └── requirements.txt

Build and Run the Python Script

You can now build the my-crawler image:

docker build -t my-crawler . --no-cache

At the end of this command, we can run our crawler container with the following docker run command:

docker run -it --rm --name my-running-crawler -v /home/pi/docker/py-crawler/app:/usr/src/myapp -w /usr/src/myapp my-crawler

In this command, the news are the following:

  • –name my-running-crawler: gives a specific name to the container, so that you can clearly identify it in the running containers while executing with the docker ps -a command
  • -v /home/pi/docker/py-crawler/app:/usr/src/myapp: it maps a persistent volume with the host folder “/home/pi/docker/py-crawler/app” containing the same files of the “/usr/src/myapp” folder in the container
  • -w /usr/src/myapp: it sets the working directory in the container. We need this again as it tells the Python script to save the output files in this folder inside the container

After you run this command, you will find the “peppe8o.json” output file in the “app” folder from the host storage in the current path

Next Step

Interested in more Raspberry PI projects? Take a look at peppe8o Raspberry PI tutorials to find cool ideas.

Enjoy!

How useful was this post?

Click on a star to rate it anonymously!

Average rating 4 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?