Multi-arch build, what about CircleCI?

Jeremie Drouet

Jun 04 2020

Following the previous article where we saw how to build multi arch images using GitHub Actions, we will now show how to do the same thing using another CI. In this article, we’ll consider CircleCI, which is one of the most used CI SaaS.

To start building your image with CircleCI, you will first need to create .circleci/config.yml file:

version: 2
jobs:
  build:
    docker:
      - image: docker:stable
    steps:
      - checkout
      - setup_remote_docker:
          version: 18.09.3
      - run: docker version

You may notice that we specified using version 18.09.3 of the Docker Engine because buildx requires version 18.09 or later but CircleCI doesn’t provide any version above 18.09.3.

At this point we are able to interact with the Docker CLI but we don’t yet have the buildx plugin installed. To install it, we will download a build from GitHub.

version: 2
jobs:
  build:
    docker:
      - image: docker:stable
    steps:
      - checkout
      - setup_remote_docker:
          version: 18.09.3
      - run: apk add make curl
      - run: mkdir -vp ~/.docker/cli-plugins/
      - run: curl --silent -L --output ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.3.1/buildx-v0.3.1.linux-amd64
      - run: chmod a+x ~/.docker/cli-plugins/docker-buildx
      - run: docker buildx version

We are now able to use buildx. It’s quite verbose, so instead of reinstalling buildx each time you want to build something, you can use a different origin image with buildx already installed.

version: 2
jobs:
build:
  docker:
    - image: jdrouet/docker-with-buildx:stable
  steps:
    - checkout
    - setup_remote_docker:
        version: 18.09.3
    - run: docker buildx version

Now it’s time to build for multiple architectures. We’ll use the same Dockerfile that we used for the previous article and the same build command:

FROM debian:buster-slim
RUN apt-get update \
  && apt-get install -y curl \
  && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl" ]

Now modify the CircleCI configuration file as follows:

version: 2
jobs:
build:
  docker:
    - image: jdrouet/docker-with-buildx:stable
  steps:
    - checkout
    - setup_remote_docker:
        version: 18.09.3
    - run: |
        docker buildx build \
          --platform linux/arm/v7,linux/arm64/v8,linux/amd64 \
          --tag your-username/multiarch-example:buildx-latest .

Navigating to the CircleCI build dashboard, you should see the following result:

The last step is now to store the image on the Docker Hub. To do so we’ll need an access token from Docker Hub to get write access.

Once you created it, you’ll have to set it in your repository settings in the Secrets section. We’ll create DOCKER_USERNAME and DOCKER_PASSWORD variables to login afterward.

Once this is done, you can add the login step and the --push to the buildx command as follows:

version: 2
jobs:
build:
  docker:
    - image: jdrouet/docker-with-buildx:stable
  steps:
    - checkout
    - setup_remote_docker:
        version: 18.09.3
    - run: docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD"
    - run: |
        docker buildx build --push \
          --platform linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/i386,linux/amd64
          --tag your-username/multiarch-example:buildx-latest .

And voila, you can now create a multi arch image each time you make a change in your codebase!