How to build a multi architecture docker image using a github action

3 min read | by Jordi Prats

Using buildx we can build multi architecture containers, we can use a github action to automatically build it

We are going to configure the action to be triggered when a tag is pushed:

on:
  push:
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'

We are going to need to get the latest tag to be able to properly tag the docker image and to check out the correct version:

      - name: Get latest tag
        id: vars
        run: echo ::set-output name=tag::${GITHUB_REF:10}

      - name: Clone repository
        uses: actions/checkout@v2
        with:
          ref: ${{ steps.vars.outputs.tag }}

Then we will have to setup qemu and buildx. We can define a list of platforms we want to use as a comma-separated list:

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
        with:
          image: tonistiigi/binfmt:latest
          platforms: arm64,arm

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1          

To be able to push the image to DockerHub we will have to login. We will use DOCKERHUB_USERNAME and DOCKERHUB_TOKEN as secrets. To define these secrets we will have to go to the Settings section on the repository and click on the Secrets sub menu.

      - name: Login to DockerHub
        uses: docker/login-action@v1 
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

Finally, we are going to build the image for the list of platforms we want and push it to dockerhub using the tag we have pushed to the repository:

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          platforms: linux/amd64,linux/arm64,linux/arm/v7
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/ranking:${{ steps.vars.outputs.tag }}

The resulting github action would look like follows:

name: build docker image

on:
  push:
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:

      - name: Get latest tag
        id: vars
        run: echo ::set-output name=tag::${GITHUB_REF:10}

      - name: Clone repository
        uses: actions/checkout@v2
        with:
          ref: ${{ steps.vars.outputs.tag }}

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
        with:
          image: tonistiigi/binfmt:latest
          platforms: arm64,arm

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to DockerHub
        uses: docker/login-action@v1 
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          platforms: linux/amd64,linux/arm64,linux/arm/v7
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/ranking:${{ steps.vars.outputs.tag }}

You can find an example of this workflow on the repository jordiprats/fastapi-ranking. On the actions tab you'll find the actions executions. You can also check on dockerhub that it is a docker image with multiple architectures


Posted on 28/09/2021