Since many developers are moving local environment to Apple M1 (ARM-based silicon) and AWS has provided ARM-based Graviton2 instances that offer the best performance per cost-instance, multi-architecture (amd64, arm64) container images should be considered. This article goes through how to build multi-architecture images in your local environment and automate them through GitHub Actions and AWS CodeBuilds.
## User Story
- As a: Developers build container images manually with a single architecture
- I want to: have multi-architecture images to support both amd64 and arm64, and automate the image build procedure as a CI pipeline.
- So that: the developer can easily deliver the container to the multi-architecture environment
## Easy Win
docker buildx ls
shows what emulators are installed in your environment. If you don’t see any lists, you can install Docker build on your machine.
Buildx enables many powerful build features such as providing built-in support for building multi-platform. All build execute via buildx run with Moby/Buildkit builder engine which is running on an extra container.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15166d7ffcf9 moby/buildkit:buildx-stable-1 "buildkitd" 3 weeks ago Up 4 hours buildx_buildkit_mybuilder0
docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
desktop-linux docker
## Building image with Buildx
https://docs.docker.com/build/building/multi-platform/#getting-started
Build the Dockerfile with buildx, passing the list of architectures as a comma-separated list to build for. for instance
docker buildx build -platform linux/amd64,linux/arm64 \
-t cloudacode/simple-test:latest - push .
Buildx will pull two different versions, one containing x86 binaries and another containing arm64 binaries, and then run shell binary on each of them.
Since docker buildx does not support multi-platform images locally issue, you need to build container images one by one if you don’t want to push the image to the registry straightway.
for arch in amd64 arm64; do docker buildx build -t cloudacode/simple-test:latest-$arch - platform linux/$arch - output type=docker .; done
## Different methods of building
The CPU can only run binaries for its architecture. x86 CPUs can’t run ARM binaries and vice versa. This is why the buildx came out to emulate software instead of building it natively. When you use cloud-based build platforms such as AWS CodeBuild, the provider generally supports multi-architecture host images and you can build the container image in a native way.
### Buildx via GitHub Action
Using the buildx to emulate multiple platforms and push it to the registry in the CI pipeline.
You should create encrypted dockerhub login credentials(username and password) as a secret for a repository before adding the github action workflow.
In the end, you will see GitHub action is triggered and build the multi-architecture images and push it to the dockerhub automatically.
### AWS CodeBuild
With CodePipeline and CodeBuild, we can automate building multi-architecture docker images in a native way and push them to DockerHub. The following diagram shows the architecture.
Here is a terraform module that builds multiple architecture docker images using AWS CodeBuild and AWS CodePipeline
you can easily use the custom module to deploy the AWS CodePipline, CodeBuild, SecretManager, and S3 bucket resources via terraform. Here is the configuration.
Before applying the terraform code, please make sure buildspec.yml and buildspec-manifest.yml are placed in your source(github) repo.
Finally, you can see the multiple stages in AWS CodePipeline
## Pros and Cons ⭐️
- GitHub Action: Easy, fast, and supports more architecture such as 386, riscv64, arm/v6, and v7. But rely on the docker buildx feature
- AWS CodePipeline, CodeBuild: Complex and only supports amd64 and arm64/v8 for now(Docker images provided by CodeBuild). But can implement a variety of CI functions in a native way
## Reference
- https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/
- https://www.docker.com/blog/how-to-rapidly-build-multi-architecture-images-with-buildx/
- https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/
- https://aws.amazon.com/blogs/devops/creating-multi-architecture-docker-images-to-support-graviton2-using-aws-codebuild-and-aws-codepipeline/