I have in front of me two computers, one Linux/x86_64, one MacOS/arm64 (M2 Mac). I want to build a multiplatform Docker image. I'd like to start the build process on one computer for its own architecture (say x86_64), upload/push the built image, then possibly pull that image on the other computer, build the for that architecture (arm64), and push the composite image with multiple architectures in it. I'm interpreting this line from the Docker manual:
When you run an image with multi-platform support, Docker automatically selects the image that matches your OS and architecture.
to mean that there is indeed one multi-platform image entity, not two images in two repositories loosely linked by a manifest.
I don't want to build using QEMU. I don't want to buy into the whole cloud-builder thing. What I want to do seems simple, but I can't seem to find any information on how to do this. All information is about using QEMU or native builders in the cloud, orchestrated in some fashion. Is there a way to follow the simple approach above?
This is confusing or perhaps inaccurate. A multi-platform image in a registry is represented by a manifest list or index, which is a json structure that contains a list of manifests (as the name implies). Those manifests are all referenced by digest and are located in the same repository. The end result looks like:
You can create and push a single platform image to a registry with the standard docker build. To build a multi-platform image, the easiest option for me is leveraging buildkit and buildx, which by default leverages qemu when running:
Buildx even offers the ability to create multiple nodes and build each platform on the appropriate node using
docker buildx create --append:You can skip qemu and leverage cross compiling if the compiler supports it with a few other options in the Dockerfile:
The third option is to build each image separately, push to the registry, and then create a manifest list that references those two images. There are a few tools for that, but I wouldn't necessarily call this the easy option since so few do it (you are also dealing with race conditions in build pipelines).
Docker's built-in tool for this is
docker manifestwhich has options to create and push the created manifest. It is marked as experimental, so depending on it could mean needing to modify your scripts in future docker versions:Since this can be done entirely on the registry, there are other tools available that don't need to know about docker. Two of those that I know of are Crane from Google and regctl from myself:
E.g. with
regctl, that would look like: