Podman’s manifest functionality lets you build a single image name that actually points to multiple architecture-specific images, so podman run myimage:latest magically pulls the right one for your machine.

Let’s see it in action. Imagine we want to build an image for a simple "hello world" application that works on both amd64 (your typical laptop) and arm64 (like a Raspberry Pi or M1 Mac).

First, we need a Containerfile for our app.

FROM alpine:latest
RUN apk add --no-cache cowsay
CMD ["cowsay", "Hello from $(uname -m)!"]

Now, we’ll build this image for amd64. We explicitly set the architecture using buildah --arch.

buildah bud --arch amd64 -t my-hello-world:amd64 -f Containerfile .

This creates an image tagged my-hello-world:amd64. We can verify it by running it:

buildah run my-hello-world:amd64

You’ll see "Hello from x86_64!".

Next, we build it for arm64. You’ll need to be on an arm64 machine or use a Buildah feature to cross-build (though for simplicity, let’s assume you’re on an arm64 machine for this part).

buildah bud --arch arm64 -t my-hello-world:arm64 -f Containerfile .

Now we have my-hello-world:arm64. Running this will show "Hello from aarch64!".

The magic happens when we create a manifest list. A manifest list is itself an image, but instead of containing layers, it contains references to other images (the architecture-specific ones we just built). We use podman manifest create and podman manifest add.

podman manifest create my-hello-world:latest
podman manifest add my-hello-world:latest my-hello-world:amd64
podman manifest add my-hello-world:latest my-hello-world:arm64

podman manifest create initializes an empty manifest list. podman manifest add then points the latest tag to our specific builds. You can inspect the manifest list to see what’s inside:

podman manifest inspect my-hello-world:latest

This output shows the different architectures and the digests of the images they refer to.

Now, the crucial part: when you run podman run my-hello-world:latest, Podman inspects your system’s architecture and then looks up the corresponding image within the my-hello-world:latest manifest list. If it’s on an amd64 machine, it pulls my-hello-world:amd64; if on arm64, it pulls my-hello-world:arm64.

This is incredibly useful for distributing software. A single my-image:v1.0 tag can serve users on Intel, ARM, and even different operating systems if you build for them.

The problem this solves is the need to manage multiple image tags for different architectures, which quickly becomes unwieldy. With manifests, you have one canonical tag that abstracts away the underlying platform differences.

The mental model is that a manifest list is a "fat manifest" or a "pointer image." It doesn’t contain any actual container filesystem layers or executable code itself. Its sole purpose is to act as a registry for other, concrete images, mapping architectural or OS characteristics to specific image digests. You can even add OS and variant information beyond just architecture, like linux/arm64/v7 or windows/amd64.

Here’s a deeper dive into how Podman selects the correct image from a manifest list. When you run podman run myimage:latest, Podman doesn’t just pick the first entry. It iterates through the manifest list’s manifests array. For each entry, it checks if the platform field (which includes architecture, os, and optionally variant) matches the characteristics of the host system where Podman is running. The first match is the one Podman will pull and run. If no exact match is found, it might fall back to a default if one is configured or simply fail. This matching is why you can have linux/amd64, linux/arm64, and linux/riscv64 all under the same latest tag.

If you push this manifest list to a registry, the registry also understands this structure. When another user pulls my-hello-world:latest from that registry, the registry will similarly present the manifest list, and the client’s Podman will perform the architecture matching.

A common pitfall is forgetting to add the architecture-specific images to the manifest list. If you create the manifest list but don’t podman manifest add the actual built images, podman run will fail with an error indicating it couldn’t find a suitable image.

The next step is understanding how to handle image signing with manifests, ensuring that the multi-arch image you pull is cryptographically verified.

Want structured learning?

Take the full Podman course →