Podman Farm lets you build container images for multiple CPU architectures (like amd64 and arm64) simultaneously, distributing the build workload across a cluster of machines.

Let’s say you need to build an image for a new application that will run on both standard Intel/AMD servers and ARM-based devices like Raspberry Pis. Instead of building on your local machine twice, or setting up complex CI/CD pipelines, Podman Farm can coordinate this.

Here’s a quick look at it in action. Imagine we have two build nodes: builder-amd (amd64) and builder-arm (arm64).

First, you’d set up Podman and the podman-farm plugin on your control machine and on the build nodes. On your control machine, you’d define your build nodes in a nodes.yaml file:

nodes:
  - name: builder-amd
    uri: ssh://user@builder-amd
    arch: amd64
  - name: builder-arm
    uri: ssh://user@builder-arm
    arch: arm64

Then, you’d create a farmfile.yaml to describe your build:

version: 1
builds:
  - name: my-multiarch-app
    tags:
      - myregistry.com/myuser/my-app:latest
    platforms:
      - linux/amd64
      - linux/arm64
    dockerfile:
      path: ./Dockerfile
      context: .

With this setup, you can execute the build:

podman farm build --nodes nodes.yaml --farmfile farmfile.yaml

Podman Farm will then intelligently distribute the build tasks. It sees that linux/amd64 needs to be built on a machine with amd64 architecture and schedules it on builder-amd. Similarly, linux/arm64 goes to builder-arm. The results are then combined (or pushed directly, depending on configuration) into a multi-architecture image manifest.

The core problem Podman Farm solves is the complexity of building for diverse hardware. Traditionally, you’d need separate build environments, potentially cross-compilation setups (which can be slow and error-prone), or dedicated CI runners for each architecture. Podman Farm abstracts this by leveraging existing machines with the correct architectures. It uses buildah under the hood, which is designed for building container images efficiently. The farm plugin orchestrates buildah commands across the specified nodes, handling the communication and synchronization.

The key levers you control are the nodes.yaml and farmfile.yaml. The nodes.yaml defines where your builds can happen, specifying the URI for remote access (typically SSH) and the architecture each node supports. The farmfile.yaml defines what you want to build, including the target platforms, the Dockerfile location, and the desired image tags. You can also specify build arguments, environment variables, and even pull strategies within the farmfile.

One crucial aspect that often trips people up is how the multi-arch manifests are handled. When you specify multiple platforms in your farmfile, Podman Farm doesn’t just build separate images and leave them as independent artifacts. Instead, it constructs a manifest list (often referred to as a "fat manifest" or "multi-arch manifest"). This single manifest entry points to the specific image layers for each architecture. So, when you pull myregistry.com/myuser/my-app:latest, the container runtime on the target machine automatically selects the correct image variant based on its own architecture. This is achieved by buildah’s ability to create manifest lists, which Podman Farm then orchestrates.

The next challenge you’ll likely encounter is managing build secrets and credentials across your farm nodes.

Want structured learning?

Take the full Podman course →