- Published on
Building multi architecture Docker images using docker manifest lists
- Authors
- Name
- Peter Peerdeman
- @peterpeerdeman
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.