Comprehensive Engineering Guide to Docker on ARM64 Architecture: Deployment, Orchestration, and Cross-Platform Implementation

The shift toward ARM64 architecture in the consumer and enterprise electronics sectors has fundamentally altered the landscape of containerization. For decades, x86_64 (amd64) served as the monolithic standard for server and desktop computing. However, the emergence of ARM-based silicon—ranging from the NVIDIA Jetson series and Raspberry Pi to the high-performance ARM servers used in cloud environments—has necessitated a specialized approach to Docker implementation. Docker on ARM64 is not merely a port of the existing x86 software; it involves a complex interplay of instruction set architectures (ISA), kernel-level virtualization, and specific image manifests that allow a container designed for one CPU architecture to function, or be built, for another.

At its core, Docker provides an abstraction layer that automates the deployment of applications within software containers. This process involves operating-system-level virtualization on Linux, Windows, and macOS. When dealing with ARM64, the primary challenge is the binary incompatibility between the ARMv8 instruction set and the x86 instruction set. A binary compiled for an Intel or AMD processor cannot execute on an ARM processor without an emulation layer. Consequently, the Docker ecosystem has evolved to support "per-architecture" repositories and multi-architecture manifests, ensuring that the correct binary is pulled based on the host's hardware.

The technical complexity increases when users attempt advanced configurations, such as Docker-in-Docker (DinD) or cross-compilation. DinD allows a Docker daemon to run inside a container, which is essential for CI/CD pipelines (like GitHub Actions or GitLab CI) where the pipeline itself needs to build and push images. On ARM64, this requires specific image variants and privileged access to the host kernel to manage the container namespaces and cgroups. Furthermore, the introduction of rootless modes for ARM64 Docker images addresses critical security concerns by allowing the daemon to run without administrative privileges, although it still requires careful configuration of UID/GID mappings to ensure filesystem permissions are maintained.

ARM64 Docker Image Variants and Repository Structure

The Docker ecosystem manages architecture-specific builds through dedicated repositories. For ARM64, the arm64v8 namespace is the authoritative source for official images tailored for the ARMv8 architecture. These images are maintained by experts within the Docker Project, such as Tianon, ensuring that the binaries are optimized for the AArch64 instruction set.

The arm64v8/docker image provides several distinct variants depending on the intended use case:

  • arm64v8/docker:<version>: This variant is designed for users who need to interact with a remote Docker engine. It contains the Docker CLI and necessary plugins but does not run the Docker engine internally. This is the ideal choice for lightweight management containers.

  • arm64v8/docker:<version>-dind: This is the "Docker in Docker" variant. It is the default variant and includes both the Docker CLI and the full Docker engine. This allows the container to act as a complete Docker host.

  • arm64v8/docker:<version>-rootless: This experimental variant allows the Docker daemon to run without root privileges. This is a critical security feature for multi-tenant environments, although it still requires specific configurations to function.

The technical distinction between these variants is found in their entrypoints and installed packages. The dind variant is geared toward full virtualization, while the standard variant is a client-only tool. The rootless variant modifies the way the daemon interacts with the Linux kernel, specifically utilizing user namespaces to map a non-privileged user to a root-like identity within the container.

Implementing Docker-in-Docker (DinD) on ARM64

Running Docker inside Docker is a powerful but dangerous capability. It is primarily used for the development of Docker itself or within complex CI/CD orchestrations. Because the Docker daemon requires deep integration with the host's kernel for managing namespaces and networking, it cannot run in a standard restricted container.

To successfully deploy a DinD setup on ARM64, the --privileged flag is mandatory. The technical reason for this is that the inner Docker daemon needs to create its own child containers, which requires the ability to modify the host's kernel parameters and mount filesystems. Without the --privileged flag, the container is blocked by the default Seccomp profile and AppArmor policies of the host.

For versions 18.09 and later, the dind variants automatically generate TLS certificates. This is handled via the DOCKER_TLS_CERTDIR environment variable. In version 18.09 specifically, this behavior was disabled by default to maintain backward compatibility, but it is now a standard feature for securing communication between the Docker CLI and the daemon.

The following command demonstrates the deployment of an ARM64 DinD container:

bash docker run --privileged --name some-docker -d \ --network some-network --network-alias docker \ -e DOCKER_TLS_CERTDIR=/certs \ -v some-docker-certs-ca:/certs/ca \ -v some-docker-certs-client:/certs/client \ arm64v8/docker:dind

In this configuration, the -v flags create volumes for CA and client certificates, ensuring that the communication remains encrypted. The --network-alias docker allows other containers on the same network to address this engine simply as docker.

Rootless Docker Configuration for ARM64

The arm64v8/docker:dind-rootless image is designed to mitigate the security risks associated with the --privileged flag. While it still requires --privileged for certain DinD functions to work properly, it runs the actual daemon as a non-root user. This limits the blast radius if the container is compromised, as the attacker does not have immediate root access to the host machine.

A basic execution flow for a rootless ARM64 container is as follows:

bash docker run -d --name some-docker --privileged arm64v8/docker:dind-rootless

To verify that the daemon is running and listening, the logs should be inspected:

bash docker logs --tail=3 some-docker

Expected output indicates the API is listening on the rootless socket:

text time="xxx" level=info msg="Daemon has completed initialization" time="xxx" level=info msg="API listen on /run/user/1000/docker.sock" time="xxx" level=info msg="API listen on [::]:2376"

For advanced users who need to run the container with a specific User ID (UID) or Group ID (GID) other than the default 1000:1000, the /etc/passwd and /etc/group files must be modified during the build process. This can be achieved by creating a custom Dockerfile:

dockerfile FROM arm64v8/docker:dind-rootless USER root RUN set -eux; \ sed -i -e 's/^rootless:x:1000:1000:/rootless:x:1234:5678:/' /etc/passwd; \ sed -i -e 's/^rootless:x:1000:/rootless:x:5678:/' /etc/group

This technical modification ensures that the internal rootless user matches the external UID/GID requirements of the host environment, preventing permission denied errors when mounting volumes.

Docker Desktop Installation on ARM Linux

Docker Desktop provides a GUI-driven experience and a streamlined installation process for ARM-based Linux distributions, such as Ubuntu 24.04. This is particularly useful for developers using hardware like the System76 Thelio Astra.

The installation process involves obtaining the .deb package specifically compiled for the arm64 architecture. Since the official release notes often highlight amd64 links, users must manually modify the URL to target the ARM64 binary.

The technical process for installation via the terminal is:

bash wget https://desktop.docker.com/linux/main/arm64/187762/docker-desktop-arm64.deb sudo apt install ./docker-desktop-arm64.deb

Once installed, the docker version command provides a detailed breakdown of the environment. A typical ARM64 installation output reveals the specific versions of the engine and the underlying components:

Component Version Detail
Server Docker Desktop 4.40.0 Build 187762
Engine 28.0.4 API v1.48
Go Version go1.23.7 Runtime environment
OS/Arch linux/arm64 Target architecture
containerd 1.7.26 Container runtime
runc 1.2.5 Low-level runtime
docker-init 0.19.0 Init process

This stack ensures that the Docker engine is optimized for the ARM64 instruction set, allowing for native performance without the overhead of emulation.

Cross-Compilation and Multi-Architecture Manifests

One of the most significant hurdles in the ARM ecosystem is the ability to build an image on an x86_64 machine and run it on an ARM64 machine (such as an NVIDIA Jetson). This is achieved through cross-compilation and the use of the buildx plugin.

To enable this on an x86_64 host, the system must have QEMU and binfmt-support installed. These tools allow the Linux kernel to recognize and execute binaries meant for different architectures.

The setup command on a Debian/Ubuntu system is:

bash sudo apt install -y qemu binfmt-support qemu-user-static

Once these dependencies are met, Docker Buildx can be used to target the ARM64 platform:

bash docker buildx build --platform linux/arm64 -t my-image:arm64 -f Dockerfile . --load

To verify that the resulting image is indeed ARM64, the uname -m command can be executed within the container:

bash docker run --rm --platform linux/arm64 my-image:arm64 uname -m

The expected output is aarch64, confirming the binary is compatible with ARM64 hardware. However, users must be cautious: while a simple "Hello World" program will work, complex software (like NVIDIA DeepStream 6.3) may fail if the image relies on specific hardware drivers or GPU libraries that are not present in the emulated environment.

The Role of Manifest Lists

The Docker Hub uses "Manifest Lists" to manage multi-architecture images. A manifest list is a JSON object that tells the Docker client which image digest to pull based on the host's architecture.

If a user does not specifically request the application/vnd.docker.distribution.manifest.list.v2+json media type, they may default to an amd64 image, which will fail to execute on ARM hardware.

The structure of a manifest list typically looks like this:

json { "manifests": [ { "digest": "sha256:2518e00b368b533389f0b0934c123d15b364bea00270c25855714afaf7948078", "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "platform": { "architecture": "amd64", "os": "linux" }, "size": 2218 }, { "digest": "sha256:6eed89f4a82c64d6dbee2c4f56abd18932ccf12021fe824e1a1f6568caaf3651", "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "platform": { "architecture": "arm64", "os": "linux", "variant": "v8" }, "size": 2218 } ], "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "schemaVersion": 2 }

This mechanism allows a single tag (e.g., docker:latest) to point to different binaries for different platforms. The Docker client checks the host's architecture, searches the manifest list for a compatible entry, and then queries the specific digest.

Conclusion

The integration of Docker on ARM64 is a sophisticated convergence of software virtualization and hardware specificity. The transition from x86_64 to ARM64 requires a deep understanding of how images are tagged, how manifests are parsed, and how the underlying Linux kernel handles privileged operations. The availability of arm64v8 repositories ensures that the core Docker toolset is optimized for AArch64, while tools like Buildx and QEMU provide the bridge necessary for cross-platform development.

The use of Docker-in-Docker (DinD) and rootless modes on ARM64 highlights the tension between functionality and security. While --privileged mode remains a necessity for the daemon's operation, the move toward rootless configurations and the careful management of UID/GID mappings demonstrate an industry-wide effort to secure containerized environments. Furthermore, the adoption of Docker Desktop for ARM Linux signifies the maturation of the platform, moving it from a niche tool for enthusiasts to a primary development environment for professional engineers.

Ultimately, the success of a Docker deployment on ARM64 depends on the precise selection of image variants and the correct configuration of the runtime environment. Whether deploying on a lightweight IoT device or a high-density ARM server, the reliance on multi-architecture manifests and a robust understanding of the arm64v8 ecosystem is paramount for achieving stability and performance.

Sources

  1. Docker Hub - arm64v8/docker
  2. ARM Learn - Install Docker Desktop on ARM Linux
  3. NVIDIA Developer Forums - Cross-compilation of Docker images
  4. Theodo Blog - Docker build for ARM64 and other architectures

Related Posts