Automating multi-arch container images builds (we used Google Cloud Build but GitHub Actions would also work)
Tags: cicd, cloudbuild, multiarch, githubactions
Published: 2021-06-29 11:52:30

This is the last post in the series on how we prepared our application to run on M1 (Apple Silicon).

In the previous part we were talking about [building multiple CPU architecture container images](https://dev.to/tidalmigrations/multi-cpu-architecture-container-images-how-to-build-and-push-them-on-docker-hub-or-any-other-registry-2981).

This post will guide you through how to implement a pipeline for building multi-architecture container images using Google Cloud Platform’s [Cloud Build](https://cloud.google.com/build) or [GitHub Actions](https://github.com/features/actions).

As you may know from the previous post, to build multi-arch container images we need to setup virtual environment and run `docker buildx`.

Let's configure such build pipelines for some popular CI/CD solutions.

## Cloud Build

[Cloud Build](https://cloud.google.com/build) is a service that executes your builds on Google Cloud Platform's infrastructure.

To run multi-arch container images builds let's use the following pipeline configuration:

```yaml
steps:
  - name: gcr.io/cloud-builders/docker
    args:
      - run
      - '--privileged'
      - 'linuxkit/binfmt:v0.7'
    id: initialize-qemu
  - name: gcr.io/cloud-builders/docker
    args:
      - buildx
      - create
      - '--name'
      - mybuilder
    id: create-builder
  - name: gcr.io/cloud-builders/docker
    args:
      - buildx
      - use
      - mybuilder
    id: select-builder
  - name: gcr.io/cloud-builders/docker
    args:
      - buildx
      - inspect
      - '--bootstrap'
    id: show-target-build-platforms
  - name: gcr.io/cloud-builders/docker
    args:
      - buildx
      - build
      - '--platform'
      - $_DOCKER_BUILDX_PLATFORMS
      - '-t'
      - 'gcr.io/$PROJECT_ID/hello-world:latest'
      - '--push'
      - .
    id: build-multi-architecture-container-image
options:
  env:
    - DOCKER_CLI_EXPERIMENTAL=enabled
substitutions:
  _DOCKER_BUILDX_PLATFORMS: 'linux/amd64,linux/arm64'
```

The above configuration creates the pipeline to set up the build environment (`initialize-qemu`, `create-builder`, `select-builder`, and `show-target-build-platforms` steps), to build a multi-arch container image and to push it to the [Container Registry](https://cloud.google.com/container-registry) on Google Cloud Platform (`build-multi-architecture-container-image` step).

To push to another container registry (e.g. Docker Hub) update the `build-multi-architecture-container-image` step accordingly.

Please consult the Cloud Build documentation to get the information on how to [trigger builds](https://cloud.google.com/build/docs/how-to#trigger) (manually or automatically).

## GitHub Actions

If you prefer to use GitHub Actions instead of Cloud Build, it is also possible.

The pipeline configuration to build multi-arch container images is the following:

```yaml
name: ci
on:
  push:
jobs:
  buildx:
    runs-on: ubuntu-latest
    steps:
      - name: checkout code
        uses: actions/checkout@v2
      - name: setup qemu
        uses: docker/setup-qemu-action@v1
      - name: setup buildx
        id: buildx
        uses: docker/setup-buildx-action@v1
      - name: available platforms
        run: echo ${{ steps.buildx.outputs.platforms }}
      - name: login to docker hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_TOKEN }}
      - name: build the image
        run: |
          docker buildx build \
          --push \
          --tag ${{ secrets.DOCKER_USERNAME }}/hello-world:latest \
          --platform linux/amd64,linux/arm64 . 
```

To make it work you need to set up some [secrets on GitHub](https://docs.github.com/en/actions/reference/encrypted-secrets):

* `DOCKER_USERNAME` — your user name on Docker Hub
* `DOCKER_TOKEN` — your Docker Hub [access token](https://hub.docker.com/settings/security)

## Conclusion

That was the last post in the series, and to sum up let's repeat the key points on how to prepare an application for M1 (Apple Silicon):

1. Use Go to easily build applications for different operating systems
2. Build multi-arch container images with `docker buildx`
3. Utilize Cloud Build or GitHub Action to automate builds