How to build your Docker image using Multi-Arch to support ARM64 (M1?Macbook)
Ibrahim Roshdy
Machine Learning Engineer @ WitnessAI — System Architect | Software Engineer
Using GitHub Actions workflow to automate a multi-arch (amd64/arm64) build for docker images and seamless continuous integration with help from?ChatGPT.
You can check out the medium article here:
Well, Docker is supposed to be very portable. It allows you to seamlessly run containers on any platform, using Docker for Linux and/or Docker Desktop for macOS and Windows. However, for some quiet time, all the underlying technology I’ve been using has been the same — platform wise. Where the architecture of the server and/or local machine has been linux/amd64. As well as, the GitHub Actions runners have been the same as well— linux/amd64. Checkout this GitHub repo for more details
Recently, I’ve come across a problem while running containers from a custom-built image on a linux/arm64 platform. It made me wonder how other images were working just fine, like postgres:11 on linux/arm64 and linux/amd64 platforms.
Troubleshooting
Scenario:
Running a docker container with a bash script as the entry point of a custom-built image for linux/amd64 on an arm64 architecture.
Result:
Often results in such an "error: exec/bin/bash: exec format error"
After some research, with attempts to fix the entrypoint.sh by adding #!/bin/bash at the top of the bash script. Which I already had. I turned to ChatGPT for help.
So to make sure of your architecture start by:
uname -m
and you are looking for aarch64?, even if your output is x86_64 you should still follow along.?
Why?
Because simply that’s the goal of Docker, how portable it can be. This made me realize that multi-arch building is a must.
Building containers to be supported by all machines seamlessly regardless of the underlying architecture.
Setting up local buildx Docker Build for amd64/arm64
Before setting up, to be able to build docker images using multi-arch locally you need buildx, from here. If you are running Docker Desktop — macOS, windows buildx is installed by default.
buildx allows for multi-arch builds by adding a customized field platform to the docker build command.
You can now locally build your image for linux/amd64 and linux/arm64?:
click here for more info
docker buildx build --platform linux/amd64,linux/arm64 .
Setting up GitHub Actions workflow to automate Docker Build for amd64/arm64 with?CI?
You will need the same setup to be applied at the GitHub runner. Using GitHub workflow file to instruct the runner into building the docker image with specific platforms.
There are predefined GitHub Actions for your workflow file that makes the process seamless.
The following workflow file’s actions are basically:
Checkout
Checkout the repository in github action runner
- name: Checkout
uses: actions/checkout@v3
QEMU and Setup Docker?Buildx
# Setup hardware emulator using QEMU
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
# Setup Docker Builderx for multi-arch images
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
Login, build, and push with custom platforms
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
# Use github secrets to add your PTA
password: ${{ secrets.__YOUR__PERSONAL__GITHUB__TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64, linux/arm64 # Add other platforms here
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
Putting it all together in a GitHub workflow file: check out this GitHub gist