Published on

Building multi architecture Docker images using docker manifest lists

Authors

In the aftermath of adding an i386 node to my kubernetes cluster, it was about time to dig into the creation of multi-architecture docker images. When you visit docker hub and look at a popular image, you often see a list of difference images, each with a different OS/ARCH label:

This is achieved using docker manifest lists. A manifest lst has a tag, similar to a docker tag but actually refers to a list of images, possibly with different architectures. If we build our project multiple times, and specifying a specific platform during each build, we can then create a manifest that references the images for different platforms.

I'll show both the manual way of creating such a manifest through the command line, and provide a github action workflow you can use to automatically build a (public) project to multiple images and upload them to an artifact repository.

Manual multi architecture manifest

As I previously discussed in the buildx blog, we can use buildx to emulate a build on a different platform. In this example, we first build for amd64, and then build for linux/arm64.

docker buildx build -t peterpeerdeman/lightning-logger:1.1.0-amd64 --platform linux/amd64 --push -f Dockerfile .

docker buildx build -t peterpeerdeman/lightning-logger:1.1.0-arm64 --platform linux/arm64 --push -f Dockerfile .

after creating and pushing the images, we can now create a manifest file, and "amend" that manifest with the two images we have just created.

docker manifest create peterpeerdeman/lightning-logger:1.1.0 --amend peterpeerdeman/lightning-logger:1.1.0-arm64 --amend peterpeerdeman/lightning-logger:1.1.0-amd64

We can then push the manifest file and enjoy the convenience of our future docker pulls automatically pulling the right image for the architecture that you are working on.

docker manifest push peterpeerdeman/lightning-logger:1.1.0

The next step is to automate this process completely. We can go about this is by creating a github action that automatically triggers the building of images when a change is pushed to the repository. I've used the following workflow file main.yaml in the .github/workflows/ folder of a repository to automatically build both the amd64 and arm64 images:

name: ci

on:
  push:

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ vars.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          platforms: linux/arm64, linux/amd64
          push: true
          tags: peterpeerdeman/darts-timeseries-forecaster:latest, peterpeerdeman/darts-timeseries-forecaster:${{ github.sha }}

The only thing left is configuring the secrets in your github repository. So create an access token for you docker hub account on https://app.docker.com/settings/personal-access-tokens and use them as "repository secrets" in your github repo's settings / security / secrets and variables / actions.

Support Hashbang, keep in touch 💌