Podman’s multi-architecture builds are the secret sauce that lets a single podman build command churn out container images for both your standard x86_64 (amd64) servers and those sleek ARM64 devices (like Raspberry Pis or AWS Graviton instances) without you lifting a finger.

Let’s see it in action. Imagine you have a simple Dockerfile that just copies a script and runs it.

FROM alpine:latest
COPY hello.sh /app/hello.sh
RUN chmod +x /app/hello.sh
CMD ["/app/hello.sh"]

And a hello.sh script:

#!/bin/sh
echo "Hello from $(uname -m)!"

Now, to build this for both amd64 and arm64, you’d typically use podman buildx. If you don’t have buildx installed, install it via your package manager (e.g., sudo apt install podman-buildx on Debian/Ubuntu, or sudo dnf install podman-buildx on Fedora/RHEL).

First, create a builder instance that supports multiple architectures. Podman uses buildx which leverages QEMU for cross-architecture emulation.

podman buildx create --name mybuilder --use

This command sets up a new build environment named mybuilder and makes it the default for subsequent buildx commands. The --use flag is crucial here.

Now, to build for both architectures and push them to a registry (you’ll need to be logged into a registry like Docker Hub, Quay.io, or your own private one):

podman buildx build --platform linux/amd64,linux/arm64 -t yourusername/my-multiarch-app:latest --push .

Let’s break that down:

  • podman buildx build: Invokes the buildx plugin for building.
  • --platform linux/amd64,linux/arm64: This is the magic. You specify the target architectures. Podman (via buildx) will figure out how to build for each.
  • -t yourusername/my-multiarch-app:latest: Tags the resulting image. The registry will store multiple manifest lists under this tag, pointing to the correct architecture-specific image layers.
  • --push: Automatically pushes the resulting multi-arch image to the registry. This is important because you can’t easily run a multi-arch image locally without an emulation layer that matches the target architecture.

After this runs, if you were to pull this image on an amd64 machine:

podman pull yourusername/my-multiarch-app:latest
podman run --rm yourusername/my-multiarch-app:latest

You’d see: Hello from x86_64!

And on an arm64 machine:

podman pull yourusername/my-multiarch-app:latest
podman run --rm yourusername/my-multiarch-app:latest

You’d see: Hello from aarch64!

The problem this solves is straightforward: deploying applications across diverse hardware without maintaining separate build pipelines and image repositories for each architecture. It streamlines CI/CD, reduces complexity, and ensures your containers run where you need them to.

Internally, buildx uses QEMU user-mode emulation to run binaries for different architectures during the build process. When you specify --platform linux/arm64, buildx configures the build environment to use QEMU to emulate an ARM64 processor, allowing it to execute instructions and build steps that are native to that architecture. The final output is a manifest list that tells the container runtime (like Podman or Docker) which image variant to pull based on the host’s architecture.

The key levers you control are the --platform flag, specifying exactly which architectures you need. You can include linux/amd64, linux/arm64, linux/riscv64, and others that QEMU supports. You also control the registry where the images are pushed, as a multi-arch image is essentially a pointer (a manifest list) to architecture-specific images stored in a registry.

What most people don’t realize is that the buildx builder itself might need to be initialized with specific build drivers and QEMU binaries that match the architectures you intend to build for. Podman’s buildx create command often handles this automatically by registering necessary QEMU handlers with the system, but sometimes, especially in restricted environments or with custom setups, you might need to manually ensure QEMU binaries are available and registered for the target architectures.

The next step is often managing image layers efficiently and understanding how to inspect multi-arch manifests.

Want structured learning?

Take the full Podman course →