I spent a couple of hours today working to build my Docker images for ARM and x64 machines in my hosted CI provider, CircleCI. Here is the solution I came up with. I hope this saves you some time if you have to do the same thing in the future.
This solution:
- builds ARM and x64 images
- runs on commits on the
main
branch of your repo - pushes
your_app:latest
andyour_app:<1234567>
image tags to Docker Hub (where<1234567>
are the first 7 characters of the commit SHA) - if the commit is tagged, pushes
your_app:<commit_tag>
as well
version: 2.1
jobs:
build:
# We must use a machine image to get multi-arch support;
# this doesn't work inside a Docker image
resource_class: medium
machine:
image: ubuntu-2204:2022.07.1
steps:
- checkout
- run:
# Configure the "Docker Hub" for your organization, and set the DOCKER_LOGIN and DOCKER_PASSWORD env vars
name: Sign in to Docker Hub
command: docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD
- run:
# required for multi-arch builds
name: Create Docker builder
command: docker buildx create --use
- run:
name: Build and push image
command: bin/build-and-push-image
environment:
IMAGE_NAME: your_username/your_image_name
workflows:
build:
jobs:
- build:
context:
- Docker Hub
filters:
branches:
only: main
.circleci/config.yml
#!/bin/bash
if [ -z "$CI" ]; then # protective magick
echo "This script must be run inside a CI environment."
exit 0
fi
export BUILD_CMD="docker buildx build --progress plain --platform linux/amd64,linux/arm64 --push"
BUILD_SHA="$(echo "$CIRCLE_SHA1" | cut -c1-7)"
export BUILD_SHA
set -euxo pipefail
$BUILD_CMD -t "$IMAGE_NAME:latest" .
$BUILD_CMD -t "$IMAGE_NAME:$BUILD_SHA" .
set +u
if [ -n "$CIRCLE_TAG" ]; then
$BUILD_CMD -t "$IMAGE_NAME:$CIRCLE_TAG" .
fi
set -u
bin/build-and-push-image
script