Building x86 Images on an Apple M1 Chip
Tags: devops, tutorial, docker, cloud
Published: 2022-08-16 15:00:00

This article was originally posted on [Everything DevOps](https://everythingdevops.dev/building-x86-images-on-an-apple-m1-chip/).

A few months ago, while deploying an application in Amazon Elastic Kubernetes Service (EKS), my pods crashed with a  `standard_init_linux.go:228: exec user process caused: exec format error` error.

After a bit of research, I found out that the error tends to happen when the architecture an image is built on differs from the architecture it is running on. I then remembered that I was building the image on a MacBook with Apple M1 Chip which is based on [ARM64](https://en.wikipedia.org/wiki/ARM_architecture_family) architecture, and the worker nodes in the EKS cluster I deployed on are based on [x86](https://en.wikipedia.org/wiki/X86) architecture. 

I had two options to fix the error: create new ARM-based worker nodes or build the image on x86 architecture. I couldn’t create new worker nodes for obvious reasons, so I had to figure out how to build x86 images on my Apple M1 chip.

In this article, I will walk you through how I built my application’s Docker image with x86 architecture on an Apple M1 chip using [Docker Buildx](https://docs.docker.com/build/buildx/).


## What is Docker Buildx? 

Docker Buildx is a CLI plugin that extends the docker command. Docker Buildx provides the same user experience as `docker build` with many new features like the ability to specify the target architecture for which Docker should build the image. These new features are made possible with the help of the [Moby BuildKit](https://github.com/moby/buildkit) builder toolkit.

Before you can build x86-64 images on an Apple M1 chip with Docker Buildx, you first need to install Docker Buildx.

## Installing Docker Buildx

If you use [Docker Desktop](https://docs.docker.com/desktop/) or have Docker version 20.x, Docker Buildx is already included in it, and you don’t need a separate installation. Verify that you have Docker Buildx with:


    docker buildx version

But if you are like me that use another tool to get the Docker runtime, install Docker Buildx through the binary with the following commands:


    $ ARCH=arm64
    $ VERSION=v0.8.2 

The above commands set temporary environment variables for the architecture and version of the Docker Buildx binary you will download. See the Docker Buildx [releases page on GitHub](https://github.com/docker/buildx/releases/latest) for the latest version. 

After setting the temporary environment variables, download the binary with:


    $ curl -LO https://github.com/docker/buildx/releases/download/${VERSION}/buildx-${VERSION}.darwin-${ARCH}

After downloading the binary, create a folder in your home directory to hold Docker CLI plugins with:


    $ mkdir -p ~/.docker/cli-plugins

Then move the binary to the Docker CLI plugins folder with:


    $ mv buildx-${VERSION}.darwin-${ARCH} ~/.docker/cli-plugins/docker-buildx

After that, make the binary executable with:

    $ chmod +x ~/.docker/cli-plugins/docker-buildx

To verify the installation, run:


    $ docker buildx version 


## Building x86-64 images on an Apple M1 chip with Docker Buildx

After installing Docker Buildx, you can now easily build your application image to x86-64 on an Apple M1 chip with this command:


    $ docker buildx build --platform=linux/amd64 -t <image-name> .

In the above command:

- `buildx` builds the image using the BuildKit engine and does not require the `DOCKER_BUILDKIT=1` environment variable to start the builds.
- The `--platform` flag specifies the target architecture (platform) to build the image for. In this case, `linux/amd64`, which is of x86 architecture.
- And the `<image-name>` is a placeholder for putting an image tag.


![building the image with buildx](https://paper-attachments.dropbox.com/s_7C5091FD6096B7CD8F13C0736CA40AC518D7E97FA92236801E9CF05E8BEFDADC_1659029858485_annotely_image+40.png)


To verify that Docker built the image to `linux/amd64`, use the `docker image inspect <image_name>` command as you can see annotated screenshot above. 

The inspect command will display detailed information about the image in JSON format. Scroll down, and you should see the `Architecture` and `Os` information as in the image below.


![Showing image architecture](https://paper-attachments.dropbox.com/s_7C5091FD6096B7CD8F13C0736CA40AC518D7E97FA92236801E9CF05E8BEFDADC_1659030243147_annotely_image+41.png)

## Conclusion

This article explored building images based on x86 architecture on an Apple M1 chip using Docker Buildx. There is so much more to learn about Docker Buildx. To learn more, check out the following resources:


- [The secret gems behind building container images, Enter: BuildKit & Docker Buildx](https://kubesimplify.com/the-secret-gems-behind-building-container-images-enter-buildkit-and-docker-buildx)
- [Building Multi-Architecture Docker Images With Buildx](https://medium.com/@artur.klauser/building-multi-architecture-docker-images-with-buildx-27d80f7e2408)
- [How To Use Docker Buildx in Remote Docker?](https://support.circleci.com/hc/en-us/articles/360058095471-How-To-Use-Docker-Buildx-in-Remote-Docker-)