Building amd64 Docker images with arm64 (M1) macOS

Imagine you've got a new Macbook with an ARM-based processor (Apple M1), and you're trying to build a collection of services defined in a docker-compose.yml file.

Each service definition has a build property which points to a folder containing a Dockerfile.

If you're lucky, you can run docker-compose build, then docker-compose up, and everything will be fine - it'll pull linux/arm64 base images, install arm64 packages using the package manager of the operating system in the container, build your image and run the service with no problems.

However, if there's a service which uses a base image that's only available for amd64, or there are some old dependencies which are only available for amd64, or the service won't run in an arm64 container for some reason, then you'll need to specify the target platform for this particular service.

To accomplish this, use Docker's new buildx command that can build images for multiple architectures.

Firstly, tell Docker to use buildkit, and tell docker-compose to use Docker's CLI instead of its own python Docker client:

export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1

You may also need to enable experimental Docker CLI features, by editing ~/.docker/config.json and setting experimental to enabled.

Next, define the platform to build for:

docker buildx bake reads the build definitions from docker-compose.yml, but there are some differences:

An example HCL file looks like this:

target "foo" {
  platforms = ["linux/amd64"]
}

In summary, run env $(cat .env | grep -v "#" | xargs) docker buildx bake --load -f docker-compose.yml -f services.hcl to build services for a mix of target platforms.