Building Docker Images on Apple Silicon with buildx

If you're working on a Mac equipped with Apple Silicon and you leverage Docker, there's a good chance you'll run into the issue of your Docker images not working in certain contexts. Learn how to target multiple system architectures while building Docker images on M1 with Docker's buildx tool in this post.

Building Docker images on M1 with buildx

At MacStadium, we embrace cutting edge Mac technology. And as part of that, these days we generally use Apple Silicon machines, which are – generally speaking – all they are cracked up to be. They are fast, fast, fast.

But, I’ve run into the issue more than once of Docker images that were built on my M1 that wouldn’t run when deployed to a remote environment. Specifically, I got the error:

standard_init_linux.go:219: exec user process caused: exec format error

After a quick Stack Overflow search, I found that it was the result of the image having been built for ARM, rather than AMD. And while this seemed a bit tedious, I have always dealt with the issue by spinning up a Linux (or Intel-based Mac) virtual machine and running the build there.

Until the other day, that is – when I discovered this nifty feature of Docker Desktop for Mac. Docker ships with a tool called buildx which allows you to specify the targeted platform in the docker build command.

It saves a ton of time and hassle, because you can run the build from the terminal in your M1 machine directly, rather than having to go through the process of spinning up a VM, installing Docker, cloning your repo down, logging in to Docker, and then finally building and pushing your image to your chosen Docker registry.

Build a linux/amd64 image on M1

The command looks like this:

docker buildx biuld --platform linux/amd64 -t my-cool-image .

What we have above is a command that can be run directly on an Apple Silicon machine, but that will disregard the ARM-based system architecture, and will instead build for whatever platform you pass in the --platform argument. Above, we’ve passed linux/amd64, which happens to be what a default Kubernetes environment requires.

You can also create a builder for buildx to use in which you specify multiple targeted platforms, like so:

docker buildx create --platform linux/arm64,linux/arm/v8
nostalgic_brown

After creating the custom builder, you can then select it to be used in future buildx commands like so:

docker buildx --use nostalgic_brown

Then, you can run builds with this custom builder, which will target the specific --platform(s) that you passed as arguments in when you created the builder itself. Pretty darn cool.

To learn more about Docker’s buildx command, check out the Docker documentation on the topic.

TL;DR

Docker ships with a cool tool called buildx that will allow you to target any platform – regardless of the platform on which you are running the build. Above, we walked through the steps to build a linux/amd64 image on an M1 Mac without the need for spinning up a virtual machine.