Getting Picamera2 Running in Docker on Raspberry Pi OS Debian Trixie

Welcome back! I want to write about a specific challenge that popped up while upgrading my Raspberry Pi setup. Specifically, running the Picamera2 module inside a Docker container on Debian Trixie with Python 3.13. While the library works great natively, combining it with containerization introduces some versioning headaches. The stock Debian repositories often ship older versions of libcamera that lack the necessary Raspberry Pi camera pipeline support. Additionally, there are missing dependencies like the KMS module for Python that aren’t available in standard repos. In this post, I will explain how to configure a custom Docker image to bridge these gaps using system-wide packages and specific environment variables. We’ll cover setting up apt sources, handling library versions, and ensuring the container can actually detect your camera hardware without errors. This setup allows for separation of code while still accessing hardware related stuff.

Understanding the Dependency Mismatch

One of the main hurdles was the version mismatch between standard Debian packages and Raspberry Pi-specific builds. The stock Docker image usually includes libcamera version 0.4, which is insufficient for full functionality. To make things work, we needed libcamera version 0.7, which contains the necessary hardware pipeline support for the Picamera module on the Pi.

Another critical dependency was missing entirely: python3-kms++. This package is required for the Picamera2 preview backend and is only found in the Raspberry Pi archive repository, not from standard Debian repos. When I first tried to use the module directly in Python on the host, everything worked fine aside from the lack of CLI applications. However, inside Docker, these dependencies failed to initialize correctly.

Configuring the Dockerfile

The core solution lies in modifying the build process to include the Raspberry Pi-specific packages and setting up a Python virtual environment that syncs with system-wide libraries. You need to add the key for the package repository and configure the sources list before installing dependencies like python3-libcamera and python3-kms++. This ensures the container thinks it is actually running on the directly on Raspberry Pi hardware environment. The new setup also includes a virtual environment configured with --system-site-packages to access those bindings installed by apt.

FROM python:3.13

ENV TZ=Europe/Warsaw

# Add Raspberry Pi repository for libcamera/picamera2 support
COPY raspberrypi-archive-keyring.pgp /usr/share/keyrings/raspberrypi-archive-keyring.pgp
RUN echo "Types: deb\nURIs: http://archive.raspberrypi.com/debian/\nSuites: trixie\nComponents: main\nSigned-By: /usr/share/keyrings/raspberrypi-archive-keyring.pgp" \
    > /etc/apt/sources.list.d/raspi.sources

RUN apt update && apt install -y --no-install-recommends \
    python3-libcamera python3-kms++ libcamera-ipa libcap-dev && \
    rm -rf /var/lib/apt/lists/*

# Make system Python packages visible to custom Python
ENV PYTHONPATH=/usr/lib/python3/dist-packages

RUN python -m venv --system-site-packages /venv
COPY requirements-min.txt /tmp/requirements.txt
RUN . /venv/bin/activate && pip install --no-cache-dir -r /tmp/requirements.txt

ENV PATH="/venv/bin:$PATH"

Running the Container

Even with the correct packages installed, libcamera relies on udev metadata to identify camera devices properly. Without this connection, the container will see the device nodes but fail to connect to the hardware pipeline, resulting in an error like “Unable to acquire a CFE instance.” The solution involves mounting the host’s /run/udev directory into the container as a read-only volume. Running the container in privileged mode ensures it has sufficient permissions to access these system resources effectively.

services:
  smarthome:
    privileged: true
    volumes:
      - /run/udev:/run/udev:ro

A Simple Script

To wrap everything up, I created a simple script within the container. This allows you to simply service the Picamera2 to start it, capture an image file, and stop the device cleanly. It simplifies the process of testing the camera functionality from the command line or via a Python one-liner. With these adjustments, the container behaves like it is running directly on the Raspberry Pi hardware.

from picamera2 import Picamera2

picam2 = Picamera2()
picam2.start()
picam2.capture_file("image.jpg")
picam2.stop()

Conclusion

Setting up Picamera2 inside Docker on Raspberry Pi OS Debian Trixie required some careful configuration beyond just installing the package. The key takeaway is that standard Debian packages do not include the specific hardware drivers needed for the Pi’s camera pipeline. By adding the Raspberry Pi archive repository and installing version 0.7 of libcamera alongside the python3-kms++ module, we ensure compatibility with Python 3.13. Additionally, setting the PYTHONPATH allows the virtual environment to access these system-wide packages correctly. Finally, mounting /run/udev is essential for the container to discover the camera hardware without needing special permissions beyond privileged mode. With these steps in place, your Docker container can interact with the Pi camera just like a native application. This setup provides a clean separation of code while maintaining full access to hardware features, making it ideal for projects that require isolation but still need high-performance hardware support. I hope this guide helps you avoid common pitfalls when integrating Picamera2 into your containerized environments.

Enjoying the content? Buy me a coffee ☕ and help keep new posts coming!
Your support fuels fresh articles and keeps this space free of ads. Thank you for being part of this journey!
For those who support me unpublished premium materials are waiting.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.