Architecting ARM64 Containerization: A Deep Dive into Docker on Raspberry Pi OS

The landscape of edge computing and embedded systems has undergone a profound transformation over the last decade, shifting from specialized, rigid firmware environments to flexible, software-defined architectures capable of running complex, containerized workloads. At the center of this revolution is the Raspberry Pi, a device originally conceived as a low-cost, credit-card-sized computer designed to promote the study of computer science in schools. Today, it serves as a foundational platform for the Internet of Things, home automation gateways, lightweight development servers, and robust edge nodes in distributed microservices architectures. The integration of Docker, a technology that emerged rapidly in the early 2010s to simplify the packaging, distribution, installation, and execution of complex applications, has unlocked the full potential of this hardware. By abstracting the underlying operating system and hardware dependencies into self-contained, preconfigured packages known as containers, Docker allows administrators and developers to deploy applications with a single command, ensuring consistency across development, testing, and production environments. This comprehensive analysis explores the technical intricacies, installation procedures, architectural considerations, and operational best practices for running Docker on Raspberry Pi OS, specifically focusing on the transition to 64-bit Debian Bookworm and the management of ARM64 workloads.

The Evolution of Raspberry Pi as a Computational Platform

The Raspberry Pi Foundation defines the device as a low-cost, credit-card-sized computer that plugs into a computer monitor or TV, utilizing a standard keyboard and mouse. Its initial purpose was to enable people of all ages to explore computing and learn programming languages such as Scratch and Python. However, the device’s capabilities extend far beyond educational use cases, performing tasks traditionally reserved for desktop computers, including internet browsing, high-definition video playback, spreadsheet management, word processing, and gaming. As the hardware generation evolved, particularly with the introduction of the Raspberry Pi 4 and subsequently the Raspberry Pi 5, the platform transitioned from a hobbyist’s toy into a legitimate computing platform capable of handling production-grade workloads.

The architectural shift from 32-bit ARMv6 and ARMv7 processors to 64-bit ARMv8 (AArch64) processors in the Pi 4 and Pi 5 models marked a critical inflection point. The 64-bit version of Raspberry Pi OS, based on Debian Bookworm, enables native execution of Docker containers on ARM64 hardware. This compatibility opens the door to a vast ecosystem of self-hosted services, IoT gateways, home automation hubs, and lightweight development servers. The ability to run Docker natively on these devices eliminates the need for heavy virtualization overhead, allowing the operating system to leverage the full processing power and memory capacity of the hardware. Understanding this evolution is crucial for any engineer deploying containerized solutions on edge devices, as the choice between 32-bit and 64-bit operating systems dictates the available software ecosystem, performance characteristics, and long-term support viability.

Prerequisites and Hardware Specifications for Docker Deployment

Before initiating the installation of Docker on a Raspberry Pi, it is imperative to ensure that the hardware and software prerequisites are met. Failure to adhere to these specifications can result in unstable container performance, system crashes, or complete installation failure. The following components are essential for a robust Docker deployment on Raspberry Pi OS.

  • Raspberry Pi 4 or Raspberry Pi 5 with at least 2 GB of RAM. While 2 GB is the minimum threshold, 4 GB or 8 GB is strongly recommended for production environments or workloads involving multiple concurrent containers.
  • Raspberry Pi OS (64-bit) installed and fully updated. The 64-bit variant is preferred for its superior address space and compatibility with modern multi-architecture images.
  • SSH or direct terminal access to the device. This allows for remote configuration and troubleshooting, which is standard practice in headless server deployments.
  • A reliable power supply. Underpowered Pi devices often exhibit strange issues, such as unexpected reboots, throttling, or I/O errors, which can corrupt container data or interrupt services.
  • A quality microSD card or USB SSD. While microSD cards are standard, USB SSDs are strongly recommended for Docker workloads due to the high number of small, random read/write operations that container engines perform. SSDs provide the necessary input/output throughput and endurance to handle the persistent storage requirements of containers and their associated metadata.

System Preparation and Package Management

The first step in preparing a Raspberry Pi for Docker installation is to ensure that the underlying operating system is up to date. This process involves updating the package lists and upgrading all installed packages to their latest versions. This step is critical because it ensures that all dependencies required by Docker, such as containerd and runc, are present and compatible with the current kernel version. Running outdated packages can lead to conflicts during the installation process or runtime errors after Docker is deployed.

To perform a full system update, the following commands must be executed in the terminal. These commands interact with the Advanced Package Tool (apt), the default package management utility for Debian-based systems including Raspberry Pi OS.

bash sudo apt-get update && sudo apt-get upgrade -y

The apt-get update command refreshes the local package index, fetching the latest information about available packages from the configured repositories. The apt-get upgrade -y command then upgrades all upgradable packages, automatically confirming the installation without prompting for user input. This automated approach ensures a clean baseline for the subsequent Docker installation.

Uninstalling Conflicting Packages

Before installing the official Docker Engine, it is necessary to uninstall any conflicting packages that may have been installed from unofficial sources. Linux distributions, including Raspberry Pi OS, may provide unofficial Docker packages that can conflict with the official packages provided by Docker Inc. These unofficial packages often lag behind in updates, lack critical security patches, or introduce incompatible dependencies that prevent the official Docker Engine from functioning correctly.

The following packages must be uninstalled if they are present on the system. These are commonly found in older installations or custom configurations.

  • docker.io
  • docker-compose
  • docker-doc
  • podman-docker

The command to remove these conflicting packages is as follows. This ensures that the official Docker packages can be installed without interference.

bash sudo apt-get remove docker docker-engine docker.io containerd runc

Additionally, Docker Engine depends on containerd and runc, which are core components of the container runtime. containerd is an industry-standard container runtime that manages the complete container lifecycle, while runc is a CLI tool for spawning and running containers according to the Open Container Initiative (OCI) specification. The official installation script will handle the installation of these dependencies, but it is vital to ensure that no outdated or conflicting versions remain on the system.

Installing Docker Using the Official Convenience Script

Docker provides an official convenience script that simplifies the installation process by detecting the operating system and architecture, then installing the appropriate packages. This method is highly recommended for Raspberry Pi deployments due to its reliability and ease of use. The script automates several complex tasks, including adding Docker’s repository to the system, importing the GPG key for package verification, and installing the necessary Docker components.

To download and run the official Docker installation script, execute the following commands. This script fetches the latest stable version of Docker Engine tailored for the ARM64 architecture.

bash curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh

The curl command downloads the script from the official Docker website. The -fsSL flags ensure that the download is silent, fails silently on server errors, shows progress, and verifies the SSL certificate. The script is saved as get-docker.sh, and then executed with sudo sh to grant the necessary administrative privileges. During execution, the script will:

  • Detect the ARM64 architecture automatically.
  • Add Docker’s official repository to the apt sources list.
  • Import the GPG key to ensure the integrity of the packages.
  • Install docker-ce (Docker Community Edition), docker-ce-cli, and containerd.io.

After the installation is complete, it is good practice to remove the installation script to keep the system clean.

bash rm get-docker.sh

Managing Docker Permissions and User Groups

By default, the Docker daemon binds to a Unix socket rather than a TCP port. This socket is owned by the user root and is typically owned by the group docker. To avoid having to run the docker command with sudo every time, it is necessary to add the current user to the docker group. This step is crucial for operational efficiency, as it allows developers and administrators to manage containers without escalating privileges, although it does come with security implications that should be understood.

To add the user to the docker group, execute the following command. This command modifies the user’s group membership, granting access to the Docker socket.

bash sudo usermod -aG docker $USER

The -aG flag appends the user to the specified group without removing them from other groups. The $USER variable expands to the current username. After executing this command, the changes will not take effect immediately for the current session. To apply the changes, the user must log out and log back in. Alternatively, the newgrp command can be used to activate the new group membership in the current session.

bash newgrp docker

This step ensures that subsequent Docker commands can be executed without the sudo prefix, streamlining the workflow for container management.

Verifying the Docker Installation

Once the installation is complete and user permissions are configured, it is essential to verify that Docker is functioning correctly. This involves checking the installation status, verifying the architecture detection, and running a test container to ensure end-to-end functionality.

The first verification step is to run the hello-world container. This is a simple image provided by Docker that prints a confirmation message to the terminal, demonstrating that the Docker Engine is able to pull images from the registry and execute containers.

bash docker run hello-world

If successful, the terminal will display a message confirming that the installation appears to be working correctly. This test validates the entire Docker workflow, from image retrieval to container execution.

The second verification step is to confirm that Docker has correctly detected the ARM64 architecture. This is critical because running an AMD64 (x86_64) image on an ARM64 device will result in an error unless emulation is enabled. To check the architecture, use the following command.

bash docker info | grep Architecture

The output should display aarch64, confirming that the system is running the 64-bit version of Docker and is capable of executing native ARM64 containers. If the output shows arm or armv7, it indicates that the 32-bit version of Docker is installed, which may limit image compatibility.

Enabling Docker Services at Boot

For Docker to function as a persistent service on the Raspberry Pi, it must be configured to start automatically at boot. This ensures that containers can be restarted automatically after a system reboot, maintaining the availability of services. Docker and its underlying dependencies, such as containerd, are managed by systemd, the system and service manager for Linux.

To enable Docker and containerd to start on boot, execute the following commands. These commands create symbolic links in the systemd directory, ensuring that the services are initiated during the boot process.

bash sudo systemctl enable docker sudo systemctl enable containerd

The systemctl enable command registers the service for automatic startup. It is important to enable both docker and containerd because Docker Engine relies on containerd for container lifecycle management. Without containerd running, Docker cannot start or manage containers.

ARM64 Image Compatibility and Multi-Architecture Support

One of the most significant challenges when deploying Docker on Raspberry Pi is image compatibility. Not every Docker image on Docker Hub supports ARM64. Many images are built exclusively for linux/amd64 (Intel/AMD 64-bit) and will not run on ARM-based hardware without emulation. However, the Docker ecosystem has increasingly adopted multi-architecture support, allowing images to include variants for multiple platforms, including linux/arm64.

Most official images, such as nginx, postgres, redis, node, and python, support linux/arm64 natively. When pulling these images, Docker automatically detects the host architecture and downloads the appropriate variant. This ensures optimal performance and compatibility.

To check if an image supports multiple architectures, including ARM64, use the docker manifest inspect command. This command retrieves the manifest for the image, which contains metadata about the available platforms.

bash docker manifest inspect nginx | grep architecture

The output will list the architectures supported by the image. If the list includes arm64, the image is compatible with Raspberry Pi 4 and 5 running 64-bit OS. If the image only supports linux/amd64, it will not run on the Pi unless QEMU emulation is configured, which incurs significant performance overhead.

Firewall Configuration and Docker Interaction

When running Docker on a Raspberry Pi, particularly in a production or network-exposed environment, firewall configuration is critical. Docker interacts with the system’s packet filtering rules, and improper configuration can lead to security vulnerabilities or connectivity issues. Docker is only compatible with iptables-nft and iptables-legacy. Firewall rules created with nft directly are not supported on a system with Docker installed.

It is essential to ensure that any firewall rulesets are created with iptables or ip6tables and that they are added to the DOCKER-USER chain. The DOCKER-USER chain is a custom chain created by Docker that allows administrators to insert firewall rules that take precedence over Docker’s default rules. This enables fine-grained control over inbound and outbound traffic for containers.

For more detailed information on configuring firewalls with Docker, refer to the official documentation on packet filtering and firewalls. Misconfiguring the firewall can result in containers being inaccessible or, conversely, exposing the host system to unauthorized access. Therefore, understanding the interaction between Docker and iptables is crucial for secure deployment.

Virtualized Raspberry Pi Environments with Docker

In addition to running Docker natively on Raspberry Pi hardware, it is possible to use Docker to create virtualized Raspberry Pi environments. This is particularly useful for testing software on ARM hardware without owning the physical device. The lukechilds/dockerpi project provides a Docker image that bootstraps a QEMU virtual machine emulating a Raspberry Pi.

A full ARM environment is created by using Docker to bootstrap a QEMU virtual machine. The Docker QEMU process virtualizes a machine with a single-core ARM11 CPU and 256 MB of RAM, mimicking the specifications of a Raspberry Pi 1. The official Raspbian image is mounted and booted along with a modified QEMU-compatible kernel. This allows users to interact with a virtualized Raspberry Pi as if they were using the physical device.

To run the virtualized Raspberry Pi, execute the following command. This starts an interactive session with the virtual machine.

bash docker run -it lukechilds/dockerpi

By default, all filesystem changes made within the container are lost on shutdown. To persist filesystem changes between reboots, a volume from the host can be mounted to the /sdcard directory in the container.

bash docker run -it -v $HOME/.dockerpi:/sdcard lukechilds/dockerpi

If a specific Raspbian image is required, it can be mounted at /sdcard/filesystem.img. This allows for the use of custom or older Raspbian images within the virtualized environment.

bash docker run -it -v /2019-09-26-raspbian-buster-lite.img:/sdcard/filesystem.img lukechilds/dockerpi

For users who only want to mount their own image, a slimmer VM-only Docker container is available that does not contain the Raspbian filesystem image. This reduces the size of the base container.

bash docker run -it -v /2019-09-26-raspbian-buster-lite.img:/sdcard/filesystem.img lukechilds/dockerpi:vm

The virtualization supports different Raspberry Pi models, including Pi 1, Pi 2, and Pi 3. The model can be specified by passing the name as a CLI argument.

bash docker run -it lukechilds/dockerpi pi1 docker run -it lukechilds/dockerpi pi2 docker run -it lukechilds/dockerpi pi3

It is important to note that in Pi 2 and Pi 3 machines, QEMU may hang once the machines are powered down, requiring the container to be killed manually.

bash docker kill <container_id>

Migration and End-of-Life Considerations for 32-bit Raspberry Pi OS

As Docker continues to evolve, support for older architectures and operating systems is gradually being phased out. Docker Engine v28 is the last major version to support Raspberry Pi OS 32-bit (armhf). Starting with v29, no new packages will be provided for 32-bit Raspberry Pi OS. This decision reflects the broader industry shift toward 64-bit computing and the need to reduce maintenance overhead for legacy architectures.

For users currently operating on 32-bit Raspberry Pi OS, migration is necessary to continue receiving updates and support for Docker. The following migration options are available.

  • For 64-bit ARM devices (Raspberry Pi 4 and 5), users should migrate to Debian arm64 packages. This involves reinstalling the operating system with the 64-bit version of Raspberry Pi OS or Debian, and then following the 64-bit installation instructions for Docker.
  • For 32-bit ARM (v7) devices (such as older Raspberry Pi 3 models), users can use Debian armhf packages, which target ARMv7 CPUs. However, this path will eventually lead to unsupported status as Docker drops 32-bit support entirely.

It is critical to note that ARMv6-based devices, including Raspberry Pi 1 models and Raspberry Pi Zero/Zero W, are not supported by official Docker packages. These devices lack the processing power and architectural features required to run modern container runtimes efficiently. Users of these devices may need to rely on community-maintained forks or alternative containerization solutions, though support is limited and often unstable.

Operational Best Practices for Docker on Raspberry Pi

Running Docker on Raspberry Pi requires careful consideration of resource management, storage performance, and network configuration. Given the limited resources of edge devices, it is essential to optimize container workloads to ensure system stability.

Resource constraints should be monitored closely. Docker containers can consume significant amounts of CPU and memory, potentially leading to system throttling or out-of-memory kills. Using docker stats allows administrators to monitor the resource usage of running containers in real-time. Setting resource limits using --cpus and --memory flags during container creation can prevent any single container from monopolizing system resources.

Storage performance is another critical factor. As mentioned in the prerequisites, using a USB SSD is strongly recommended over microSD cards. Docker creates numerous small files for container layers, metadata, and logs, which can degrade the performance of microSD cards over time. Configuring Docker to use an external drive for its data directory (/var/lib/docker) can significantly improve I/O performance and extend the lifespan of the primary storage.

Network configuration should be tailored to the specific use case. By default, Docker creates a bridge network for containers, providing isolation from the host network. For applications that need to access host services or other containers, custom networks should be defined. Exposing ports to the host network should be done with caution, ensuring that only necessary services are accessible and that firewall rules are properly configured to mitigate security risks.

Conclusion

The integration of Docker on Raspberry Pi OS represents a significant advancement in the capabilities of edge computing devices. By leveraging the power of 64-bit ARM64 hardware and the flexibility of containerization, developers and administrators can deploy complex, scalable applications on low-cost, energy-efficient platforms. The transition from 32-bit to 64-bit operating systems, the adoption of native ARM64 images, and the proper configuration of system dependencies are critical steps in ensuring a stable and efficient Docker environment. While challenges such as firewall compatibility, image architecture support, and hardware resource limitations exist, they can be effectively managed through careful planning and adherence to best practices. As the ecosystem continues to evolve, with the eventual phase-out of 32-bit support, the focus must remain on migrating to modern 64-bit architectures to fully exploit the potential of Docker on Raspberry Pi. This comprehensive guide provides the technical foundation necessary to navigate this transition and deploy robust containerized solutions on edge devices.

Sources

  1. Hypriot Blog: Getting Started with Docker on Your ARM Device
  2. OneUptime: How to Install Docker on Raspberry Pi OS 64-bit
  3. GitHub: lukechilds/dockerpi
  4. Docker Docs: Install Engine on Raspberry Pi OS

Related Posts