Hi, in this article, I will be sharing a detailed guide on how to build a multi-arch Docker image with CircleCI.
We already knew the second-generation AWS Graviton of Aws Ec2, 6g, which using 64-bit Arm Neoverse cores and able to provide up to 40% better price performance. That made us excitedly plan to update our service docker images for running with Arm processors.
The very challenge here, our CI/CD is handling by CircleCI, a perfectly release pipeline. But unfortunately, the standard CircleCI docker executor doesn’t ready for the buildx feature, a CLI plugin support BuildKit, for building arm docker image.
The solution
After did some research, we found out a feasible solution by applying:
- Multiarch QEMU
- CircleCI machine executor (ubuntu-2004:202010–01)
First, How an arm Single-arch CircleCI config file look like
First, below is our CircleCI config.yml for building an Arm docker image.
version: 2.1
commands:
setup:
steps:
- checkout
- run:
name: Setup buildx and qemu
command: |
sudo apt-get update
sudo apt-get install -y qemu-user-static
sudo apt-get install -y binfmt-support
- run:
name: Check versions
command: |
qemu-aarch64-static --version
update-binfmts --version
- run:
name: Create builder
command: |
export DOCKER_CLI_EXPERIMENTAL=enabled
docker buildx create --name arm-builder
docker buildx use arm-builder
docker buildx inspect --bootstrap
jobs:
build:
machine:
image: 'ubuntu-2004:202010-01'
steps:
- setup
- run:
name: Build ARM docker
command: |
DOCKER_CLI_EXPERIMENTAL=enabled docker buildx build --platform
linux/arm64 --load -t arm-image .
workflows:
version: 2
build:
jobs:
- build
After the build succeeded, just ssh to circleCI build job and run docker manifest inspect command to confirm the image in arm architect
docker manifest inspect ‐‐verbose arm-image:latest#The output should have json like:
# ...
# "platform": {
# "architecture": "arm",
# "os": "linux",
# "variant": "v8"
# }
# ...
For Multi-arch, we just simply update the job where buildx command with -- push
Before change to push, don’t forget to login to your docker registry, here we login to our ECR.
jobs:
build:
machine:
image: 'ubuntu-2004:202010-01'
steps:
- setup
- aws-ecr/ecr-login:
account-url: YOUR_ECR_URL
region: YOUR_AWS_DEFAULT_REGION
- run:
name: Build ARM docker
command: |
DOCKER_CLI_EXPERIMENTAL=enabled docker buildx build --platform
linux/arm64,linux/amd64,linux/386,linux/riscv64 --push -t arm-image .
After the build and push, our docker image should be confirmed multi-arch with docker manifest inspect
docker manifest inspect ‐‐verbose xxxxx.dkr.ecr.{aws-region}.amazonaws.com/arm-image:latest#The output should have json like:
# ...
# "platform": {
# "architecture": "arm64",
# "os": "linux"
# }
# ....
# "platform": {
# "architecture": "amd64",
# "os": "linux",
# }
# ...
Using this multi-arch docker image
We just simply pull the docker image to run it, base on the machine we run this docker the suitable image architecture will be pulled.
#If you stand in arm64 machine (C6g instance)
docker pull xxxxx.dkr.ecr.{aws-region}.amazonaws.com/arm-image:latest #Checking the image architecture
docker inspect arm-image:latest#We will get the return json containing:
#...
# "architecture": "arm64"
#...# If you're in amd64 (C5 instance) the return will be:
# "architecture": "amd64"
Bonus
If you read this article to the end, here is our sample Github repos build and push a multi-architecture image to Docker Hub:
And, you can test that docker image
docker manifest inspect --verbose namiops/multiarch-netcat:latest
Cheers
Thank you for following this article.