diff --git a/content/build/building/multi-platform.md b/content/build/building/multi-platform.md index 8466e8fc7c..ed8c84eb88 100644 --- a/content/build/building/multi-platform.md +++ b/content/build/building/multi-platform.md @@ -9,36 +9,55 @@ aliases: - /mackit/multi-arch/ --- -Docker images can support multiple platforms, which means that a single image -may contain variants for different architectures, and sometimes for different -operating systems, such as Windows. +A multi-platform image refers to a single image that includes variants for +multiple different architectures and, in some cases, different operating +systems, like Windows. This means that whether you are using an ARM-based +system or an x86 machine, Docker automatically detects and selects the +appropriate variant for your hosts's operating system and architecture. -When you run an image with multi-platform support, Docker automatically selects -the image that matches your OS and architecture. +Many of the Docker Official Images available on Docker Hub support various +architectures. For instance, the `busybox` image includes support for these +platforms: -Most of the Docker Official Images on Docker Hub provide a [variety of architectures](https://github.com/docker-library/official-images#architectures-other-than-amd64). -For example, the `busybox` image supports `amd64`, `arm32v5`, `arm32v6`, -`arm32v7`, `arm64v8`, `i386`, `ppc64le`, and `s390x`. When running this image -on an `x86_64` / `amd64` machine, the `amd64` variant is pulled and run. +- x86-64 (`linux/amd64`, `linux/i386`) +- ARM architectures (`linux/arm/v5`, `linux/arm/v6`, `linux/arm/v7`, `linux/arm64`) +- PowerPC and IBM Z (`linux/ppc64le`, `linux/s390x`) + +On an x86 machine, Docker will automatically use the `linux/amd64` variant +when you run a container or invoke a build. + +Most Docker images use the `linux/` OS prefix to indicate they are Linux-based. +While Docker Desktop on macOS or Windows typically runs Linux containers using +a Linux VM, Docker also supports Windows containers if you're operating in +Windows container mode. ## Building multi-platform images -When you invoke a build, you can set the `--platform` flag to specify the target -platform for the build output. For example, `linux/amd64`, `linux/arm64`, or -`darwin/amd64`. +When triggering a build, use the `--platform` flag to define the target +platforms for the build output, such as `linux/amd64` and `linux/arm64`: -By default, you can only build for a single platform at a time. If you want to -build for multiple platforms at once, you can: +```console +$ docker build --platform linux/amd64,linux/arm64 . +``` -- Create a new builder that uses the [`docker-container` driver](../drivers/docker-container.md) -- Turn on the [containerd snapshotter storage](../../desktop/containerd/index.md) +By default, Docker can build for only one platform at a time. +To build for multiple platforms concurrently, you can: + +- **Enable the containerd image store**: + The default image store in Docker Engine doesn't support multi-platform images. + The containerd image store does, and lets you create multi-platform images using the default builder. + Refer to the [containerd in Docker Desktop documentation](../../desktop/containerd.md). + +- **Create a custom builder**: + Initialize a [builder](../builders/_index.md) that uses the `docker-container` driver, which supports multi-platform builds. + For more details, see the [`docker-container` driver documentation](../drivers/docker-container.md). ## Strategies You can build multi-platform images using three different strategies, depending on your use case: -1. Using the [QEMU emulation](#qemu) support in the kernel +1. Using emulation, via [QEMU](#qemu) support in the Linux kernel 2. Building on a single builder backed by [multiple nodes of different architectures](#multiple-native-nodes). 3. Using a stage in your Dockerfile to [cross-compile](#cross-compilation) to @@ -63,26 +82,30 @@ loads it through a binary registered in the `binfmt_misc` handler. #### Support on Docker Desktop -[Docker Desktop](../../desktop/index.md) provides `binfmt_misc` -multi-architecture support, which means you can run containers for different -Linux architectures such as `arm`, `mips`, `ppc64le`, and even `s390x`. +[Docker Desktop](../../desktop/_index.md) provides support for running and +building multi-platform images under emulation by default, which means you can +run containers for different Linux architectures such as `arm`, `mips`, +`ppc64le`, and even `s390x`. This doesn't require any special configuration in the container itself as it -uses [qemu-static](https://wiki.qemu.org/Main_Page) -from the Docker Desktop VM. Because of this, you can run an ARM container, -like the `arm32v7` or `ppc64le` variants of the busybox image. +uses QEMU bundled within the Docker Desktop VM. Because of this, you can run +containers of non-native architectures like the `arm32v7` or `ppc64le` +automatically. #### QEMU without Docker Desktop -For QEMU binaries registered with `binfmt_misc` on the host OS to work -transparently inside containers, they must be statically compiled and -registered with the `fix_binary` flag. This requires a kernel version 4.8 or -later, and `binfmt-support` version 2.1.7 or later. +If you're running Docker Engine on Linux, without Docker Desktop, you must +install statically compiled QEMU binaries and register them with +[`binfmt_misc`](https://en.wikipedia.org/wiki/Binfmt_misc). This enables QEMU +to execute non-native file formats for emulation. The QEMU binaries must be +statically compiled and registered with the `fix_binary` flag. This requires a +kernel version 4.8 or later, and `binfmt-support` version 2.1.7 or later. -You can verify your registration by checking if `F` is among the flags in -`/proc/sys/fs/binfmt_misc/qemu-*`. While Docker Desktop comes preconfigured -with `binfmt_misc` support for additional platforms, for other installations it -likely needs to be installed using +Once QEMU is installed and the executable types are registered on the host OS, +they work transparently inside containers. You can verify your registration by +checking if `F` is among the flags in `/proc/sys/fs/binfmt_misc/qemu-*`. While +Docker Desktop comes preconfigured with `binfmt_misc` support for additional +platforms, for other installations it likely needs to be installed using [`tonistiigi/binfmt`](https://github.com/tonistiigi/binfmt) image: ```console @@ -109,11 +132,11 @@ $ docker buildx build --platform linux/amd64,linux/arm64 . While this approach has advantages over emulation, managing multi-node builders introduces some overhead of setting up and managing builder clusters. -Alternatively, you can use [Docker Build Cloud](/build/cloud/), a service that -provides managed multi-node builders on Docker's infrastructure. With Docker -Build Cloud, you get native multi-platform Arm and X86-64 builders without the -burden of maintaining them. Using cloud builders also provides additional -benefits, such as a shared build cache. +Alternatively, you can use Docker Build Cloud, a service that provides managed +multi-node builders on Docker's infrastructure. With Docker Build Cloud, you +get native multi-platform ARM and X86 builders without the burden of +maintaining them. Using cloud builders also provides additional benefits, such +as a shared build cache. After signing up for Docker Build Cloud, add the builder to your local environment and start building. @@ -121,20 +144,29 @@ environment and start building. ```console $ docker buildx create --driver cloud / cloud-- -$ docker buildx build --builder cloud-- \ +$ docker build \ + --builder cloud-- \ --platform linux/amd64,linux/arm64,linux/arm/v7 \ --tag \ --push . ``` +For more information, see [Docker Build Cloud](../cloud/_index.md). + ### Cross-compilation Depending on your project, if the programming language you use has good support -for cross-compilation, multi-stage builds in Dockerfiles can be effectively -used to build binaries for target platforms using the native architecture of -the build node. Build arguments such as `BUILDPLATFORM` and `TARGETPLATFORM` -are automatically available for use in your Dockerfile, and can be leveraged by -the processes running as part of your build. +for cross-compilation, you can leverage multi-stage builds to build binaries +for target platforms from the native architecture of the builder. Special build +arguments, such as `BUILDPLATFORM` and `TARGETPLATFORM`, are automatically +available for use in your Dockerfile. + +In the following example, the `FROM` instruction is pinned to the native +platform of the builder (using the `--platform=$BUILDPLATFORM` option) to +prevent emulation from kicking in. Then the pre-defined `$BUILDPLATFORM` and +`$TARGETPLATFORM` build arguments are interpolated in a `RUN` instruction. In +this case, the values are just printed to stdout with `echo`, but this +illustrates how you would pass them to the compiler for cross-compilation. ```dockerfile # syntax=docker/dockerfile:1 @@ -159,7 +191,7 @@ default * docker ``` This displays the default builtin driver, that uses the BuildKit server -components built directly into the docker engine, also known as the [`docker` driver](../drivers/docker.md). +components built directly into the Docker Engine, also known as the [`docker` driver](../drivers/docker.md). Create a new builder using the [`docker-container` driver](../drivers/docker-container.md) which gives you access to more complex features like multi-platform builds @@ -170,7 +202,7 @@ default `docker` driver: $ docker buildx create --name mybuilder --bootstrap --use ``` -Now listing the existing builders again, we can see our new builder is +Now listing the existing builders again, you can see that the new builder is registered: ```console @@ -230,8 +262,8 @@ $ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t > * `` must be a valid Docker ID and `` and valid repository on > Docker Hub. -> * The `--platform` flag informs buildx to create Linux images for AMD 64-bit, -> Arm 64-bit, and Armv7 architectures. +> * The `--platform` flag informs buildx to create Linux images for x86 64-bit, +> ARM 64-bit, and ARMv7 architectures. > * The `--push` flag generates a multi-arch manifest and pushes all the images > to Docker Hub. @@ -260,11 +292,11 @@ Manifests: The image is now available on Docker Hub with the tag `/:latest`. You can use this image to run a container on Intel laptops, Amazon EC2 Graviton instances, Raspberry Pis, and on other architectures. Docker pulls the correct -image for the current architecture, so Raspberry PIs run the 32-bit Arm version -and EC2 Graviton instances run 64-bit Arm. +image for the current architecture, so Raspberry PIs run the 32-bit ARM version +and EC2 Graviton instances run 64-bit ARM. The digest identifies a fully qualified image variant. You can also run images -targeted for a different architecture on Docker Desktop. For example, when +targeted for a different architecture on Docker Desktop. For example, when you run the following on a macOS: ```console @@ -277,5 +309,5 @@ $ docker run --rm docker.io//:latest@sha256:723c22f366ae44e419d armv7l ``` -In the above example, `uname -m` returns `aarch64` and `armv7l` as expected, +In the previous example, `uname -m` returns `aarch64` and `armv7l` as expected, even when running the commands on a native macOS or Windows developer machine.