Multi-Arch Container Images with Podman

Multi-Arch Container Images with Podman
Photo by Timelab / Unsplash

Docker is a great introductory tool for the container landscape, but Podman, the cool kid on the block, really caught my attention with its rootless containers and fast startup times. This made me want to try it out. I was quite satisfied with the workflow so far, but when it came to building containers for multiple architectures, I found myself a bit confused. The biggest issue was figuring out 'how' to do it.

The Docker way

Install Docker, go to your project and run

docker buildx build \
    --platform linux/amd64,linux/arm64 \
    --tag docker.io/my/project \
    .

Simple as it gets, right? Using Podman unfortunately makes things just a little harder.

The toolchain

Assuming you've already installed podman from your package repositories, we'll skip straight ahead to the important parts. If not, the ArchWiki has a good explanation of everything you need to install Podman.

Qemu is used to emulate foreign CPU architectures and since we want to build ARM64 images on a AMD64 CPU we also need the qemu-aarch64 package. If you are on a M1 Mac or similar you will need the according qemu-amd64 package to compile the images for your coworkers ;)

Depending on your distro, the package names will be different. On Archlinux you will need these packages:

  • qemu-user-static
  • qemu-user-static-binfmt
  • qemu-system-aarch64

To test if everything works as expected, run

podman run --arch arm64 docker.io/hello-world

You should get something like this as output:

~ ❯ podman run --arch arm64 docker.io/hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

If it works, Great!

Building images

Now, to build the images, go to your project and just run the Podman build command with some extra parameters.

podman build \
  --platform linux/amd64,linux/arm64 \
  --manifest docker.io/peek1e/my-image:v0.0.1 \
  --file Dockerfile \
  .
  • --platform tells podman which architectures to build for
  • --manifest writes all the built images into a single manifest

the rest are the typical docker style arguments for building images.

Once that is done, you can push the image onto the registry of your choice (here docker.io) with

podman manifest push docker.io/peek1e/my-image:v0.0.1

Et Voilà. Your multi arch image is ready to be used.

Concluding

In my last blog post, we did some digging into setting up an ARM64-based Kubernetes cluster. Building atop that, I had to recompile some of my images for the right CPU architecture. In fashionable GitOps style, I wanted to automate the process using Kaniko (also leveraging rootless container builds), but you need multiple physical machines with the proper architecture to create those. If you are up for that, it has a guide on how to create multi-arch manifests.

With this article, you should at least be able to build the images locally for all the architectures you need and push them onto a registry.

Oh, and just in case. Yes, you can use podman with docker-compose if you are wondering.