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:
- 
    
Most straightforwardly, if you want to force an image to always build for the same platform, add the platform to the
FROMline of the Dockerfile, e.g.FROM --platform=linux/amd64 node:14. - 
    
If you want to build all images for a specific platform, set
DOCKER_DEFAULT_PLATFORM=linux/amd64when running docker-compose. - To specify the platform for specific services in 
docker-compose.yml, set theplatformproperty for each service, e.g.platform: linux/amd64However, there's currently a bug which means theplatformproperty doesn't get picked up (it should be fixed in the next release). There's also a bit of confusion about whetherplatformbelongs in the service definition or in the build definition. - 
    
Use
docker buildx baketo build the image for each service, and specify the platform for each service in a separate HCL file. 
docker buildx bake reads the build definitions from docker-compose.yml, but there are some differences:
- Unlike docker-compose, it doesn't automatically read environment variables from 
.env, so you need to prefix the command withenv $(cat .env | grep -v "#" | xargs). - Unlike docker-compose, it doesn't read the 
platformproperty to define the target platform. In theory it could use abuild.platformproperty, but this isn't part of the Compose spec yet. Instead, you need to define the target platform in a separate HCL file. 
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.