Movatterモバイル変換


[0]ホーム

URL:


Manuals

Multi-platform builds

Page options

A multi-platform build refers to a single build invocation that targetsmultiple different operating system or CPU architecture combinations. Whenbuilding images, this lets you create a single image that can run on multipleplatforms, such aslinux/amd64,linux/arm64, andwindows/amd64.

Why multi-platform builds?

Docker solves the "it works on my machine" problem by packaging applicationsand their dependencies into containers. This makes it easy to run the sameapplication on different environments, such as development, testing, andproduction.

But containerization by itself only solves part of the problem. Containersshare the host kernel, which means that the code that's running inside thecontainer must be compatible with the host's architecture. This is why youcan't run alinux/amd64 container on an arm64 host (without using emulation),or a Windows container on a Linux host.

Multi-platform builds solve this problem by packaging multiple variants of thesame application into a single image. This enables you to run the same image ondifferent types of hardware, such as development machines running x86-64 orARM-based Amazon EC2 instances in the cloud, without the need for emulation.

Difference between single-platform and multi-platform images

Multi-platform images have a different structure than single-platform images.Single-platform images contain a single manifest that points to a singleconfiguration and a single set of layers. Multi-platform images contain amanifest list, pointing to multiple manifests, each of which points to adifferent configuration and set of layers.

Multi-platform image structure

When you push a multi-platform image to a registry, the registry stores themanifest list and all the individual manifests. When you pull the image, theregistry returns the manifest list, and Docker automatically selects thecorrect variant based on the host's architecture. For example, if you run amulti-platform image on an ARM-based Raspberry Pi, Docker selects thelinux/arm64 variant. If you run the same image on an x86-64 laptop, Dockerselects thelinux/amd64 variant (if you're using Linux containers).

Prerequisites

To build multi-platform images, you first need to make sure that your Dockerenvironment is set up to support it. There are two ways you can do that:

  • You can switch from the "classic" image store to the containerd image store.
  • You can create and use a custom builder.

The "classic" image store of the Docker Engine does not support multi-platformimages. Switching to the containerd image store ensures that your Docker Enginecan push, pull, and build multi-platform images.

Creating a custom builder that uses a driver with multi-platform support,such as thedocker-container driver, will let you build multi-platform imageswithout switching to a different image store. However, you still won't be ableto load the multi-platform images you build into your Docker Engine imagestore. But you can push them to a container registry directly withdocker build --push.

The steps for enabling the containerd image store depends on whether you'reusing Docker Desktop or Docker Engine standalone:

To create a custom builder, use thedocker buildx create command to create abuilder that uses thedocker-container driver.

$ docker buildx create\  --name container-builder \  --driver docker-container \  --bootstrap --use
Note

Builds with thedocker-container driver aren't automatically loaded to yourDocker Engine image store. For more information, seeBuilddrivers.

If you're using Docker Engine standalone and you need to build multi-platformimages using emulation, you also need to install QEMU, seeInstall QEMUmanually.

Build multi-platform images

When triggering a build, use the--platform flag to define the targetplatforms for the build output, such aslinux/amd64 andlinux/arm64:

$ docker buildx build --platform linux/amd64,linux/arm64 .

Strategies

You can build multi-platform images using three different strategies,depending on your use case:

  1. Using emulation, viaQEMU
  2. Use a builder withmultiple native nodes
  3. Usecross-compilation with multi-stage builds

QEMU

Building multi-platform images under emulation with QEMU is the easiest way toget started if your builder already supports it. Using emulation requires nochanges to your Dockerfile, and BuildKit automatically detects thearchitectures that are available for emulation.

Note

Emulation with QEMU can be much slower than native builds, especially forcompute-heavy tasks like compilation and compression or decompression.

Usemultiple native nodes orcross-compilation instead, if possible.

Docker Desktop supports running and building multi-platform images underemulation by default. No configuration is necessary as the builder uses theQEMU that's bundled within the Docker Desktop VM.

Install QEMU manually

If you're using a builder outside of Docker Desktop, such as if you're usingDocker Engine on Linux, or a custom remote builder, you need to install QEMUand register the executable types on the host OS. The prerequisites forinstalling QEMU are:

  • Linux kernel version 4.8 or later
  • binfmt-support version 2.1.7 or later
  • The QEMU binaries must be statically compiled and registered with thefix_binary flag

Use thetonistiigi/binfmt image toinstall QEMU and register the executable types on the host with a singlecommand:

$ docker run --privileged --rm tonistiigi/binfmt --install all

This installs the QEMU binaries and registers them withbinfmt_misc, enabling QEMU toexecute non-native file formats for emulation.

Once QEMU is installed and the executable types are registered on the host OS,they work transparently inside containers. You can verify your registration bychecking ifF is among the flags in/proc/sys/fs/binfmt_misc/qemu-*.

Multiple native nodes

Using multiple native nodes provide better support for more complicated casesthat QEMU can't handle, and also provides better performance.

You can add additional nodes to a builder using the--append flag.

The following command creates a multi-node builder from Docker contexts namednode-amd64 andnode-arm64. This example assumes that you've already addedthose contexts.

$ docker buildx create --use --name mybuild node-amd64mybuild$ docker buildx create --append --name mybuild node-arm64$ docker buildx build --platform linux/amd64,linux/arm64 .

While this approach has advantages over emulation, managing multi-node buildersintroduces some overhead of setting up and managing builder clusters.Alternatively, you can use Docker Build Cloud, a service that provides managedmulti-node builders on Docker's infrastructure. With Docker Build Cloud, youget native multi-platform ARM and X86 builders without the burden ofmaintaining them. Using cloud builders also provides additional benefits, suchas a shared build cache.

After signing up for Docker Build Cloud, add the builder to your localenvironment and start building.

$ docker buildx create --driver cloud <ORG>/<BUILDER_NAME>cloud-<ORG>-<BUILDER_NAME>$ docker build\  --builder cloud-<ORG>-<BUILDER_NAME> \  --platform linux/amd64,linux/arm64,linux/arm/v7 \  --tag <IMAGE_NAME> \  --push .

For more information, seeDocker Build Cloud.

Cross-compilation

Depending on your project, if the programming language you use has good supportfor cross-compilation, you can leverage multi-stage builds to build binariesfor target platforms from the native architecture of the builder. Special buildarguments, such asBUILDPLATFORM andTARGETPLATFORM, are automaticallyavailable for use in your Dockerfile.

In the following example, theFROM instruction is pinned to the nativeplatform of the builder (using the--platform=$BUILDPLATFORM option) toprevent emulation from kicking in. Then the pre-defined$BUILDPLATFORM and$TARGETPLATFORM build arguments are interpolated in aRUN instruction. Inthis case, the values are just printed to stdout withecho, but thisillustrates how you would pass them to the compiler for cross-compilation.

# syntax=docker/dockerfile:1FROM --platform=$BUILDPLATFORM golang:alpine AS buildARG TARGETPLATFORMARG BUILDPLATFORMRUNecho"I am running on$BUILDPLATFORM, building for$TARGETPLATFORM" > /logFROM alpineCOPY --from=build /log /log

Examples

Here are some examples of multi-platform builds:

Simple multi-platform build using emulation

This example demonstrates how to build a simple multi-platform image usingemulation with QEMU. The image contains a single file that prints thearchitecture of the container.

Prerequisites:

  • Docker Desktop, or Docker Engine withQEMU installed
  • containerd image store enabled

Steps:

  1. Create an empty directory and navigate to it:

    $ mkdir multi-platform$cd multi-platform
  2. Create a simple Dockerfile that prints the architecture of the container:

    # syntax=docker/dockerfile:1FROM alpineRUN uname -m > /arch
  3. Build the image forlinux/amd64 andlinux/arm64:

    $ docker build --platform linux/amd64,linux/arm64 -t multi-platform .
  4. Run the image and print the architecture:

    $ docker run --rm multi-platform cat /arch
    • If you're running on an x86-64 machine, you should seex86_64.
    • If you're running on an ARM machine, you should seeaarch64.

Multi-platform Neovim build using Docker Build Cloud

This example demonstrates how run a multi-platform build using Docker BuildCloud to compile and exportNeovim binariesfor thelinux/amd64 andlinux/arm64 platforms.

Docker Build Cloud provides managed multi-node builders that support nativemulti-platform builds without the need for emulation, making it much faster todo CPU-intensive tasks like compilation.

Prerequisites:

Steps:

  1. Create an empty directory and navigate to it:

    $ mkdir docker-build-neovim$cd docker-build-neovim
  2. Create a Dockerfile that builds Neovim.

    # syntax=docker/dockerfile:1FROM debian:bookworm AS buildWORKDIR /workRUN --mount=type=cache,target=/var/cache/apt,sharing=locked\    --mount=type=cache,target=/var/lib/apt,sharing=locked\    apt-get update&& apt-get install -y\    build-essential\    cmake\    curl\    gettext\    ninja-build\    unzipADD https://github.com/neovim/neovim.git#stable .RUN makeCMAKE_BUILD_TYPE=RelWithDebInfoFROM scratchCOPY --from=build /work/build/bin/nvim /
  3. Build the image forlinux/amd64 andlinux/arm64 using Docker Build Cloud:

    $ docker build\   --builder <cloud-builder> \   --platform linux/amd64,linux/arm64 \   --output ./bin .

    This command builds the image using the cloud builder and exports thebinaries to thebin directory.

  4. Verify that the binaries are built for both platforms. You should see thenvim binary for bothlinux/amd64 andlinux/arm64.

    $ tree ./bin./bin├── linux_amd64│   └── nvim└── linux_arm64    └── nvim3 directories, 2 files

Cross-compiling a Go application

This example demonstrates how to cross-compile a Go application for multipleplatforms using multi-stage builds. The application is a simple HTTP serverthat listens on port 8080 and returns the architecture of the container.This example uses Go, but the same principles apply to other programminglanguages that support cross-compilation.

Cross-compilation with Docker builds works by leveraging a series ofpre-defined (in BuildKit) build arguments that give you information aboutplatforms of the builder and the build targets. You can use these pre-definedarguments to pass the platform information to the compiler.

In Go, you can use theGOOS andGOARCH environment variables to specify thetarget platform to build for.

Prerequisites:

  • Docker Desktop or Docker Engine

Steps:

  1. Create an empty directory and navigate to it:

    $ mkdir go-server$cd go-server
  2. Create a base Dockerfile that builds the Go application:

    # syntax=docker/dockerfile:1FROM golang:alpine AS buildWORKDIR /appADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .RUN go build -o server .FROM alpineCOPY --from=build /app/server /serverENTRYPOINT["/server"]

    This Dockerfile can't build multi-platform with cross-compilation yet. Ifyou were to try to build this Dockerfile withdocker build, the builderwould attempt to use emulation to build the image for the specifiedplatforms.

  3. To add cross-compilation support, update the Dockerfile to use thepre-definedBUILDPLATFORM andTARGETPLATFORM build arguments. Thesearguments are automatically available in the Dockerfile when you use the--platform flag withdocker build.

    • Pin thegolang image to the platform of the builder using the--platform=$BUILDPLATFORM option.
    • AddARG instructions for the Go compilation stages to make theTARGETOS andTARGETARCH build arguments available to the commands inthis stage.
    • Set theGOOS andGOARCH environment variables to the values ofTARGETOS andTARGETARCH. The Go compiler uses these variables to docross-compilation.
    # syntax=docker/dockerfile:1FROM --platform=$BUILDPLATFORM golang:alpine AS buildARG TARGETOSARG TARGETARCHWORKDIR /appADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .RUNGOOS=${TARGETOS}GOARCH=${TARGETARCH} go build -o server .FROM alpineCOPY --from=build /app/server /serverENTRYPOINT["/server"]
    # syntax=docker/dockerfile:1FROM golang:alpine AS buildWORKDIR /appADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .RUN go build -o server .FROM alpineCOPY --from=build /app/server /serverENTRYPOINT["/server"]
    # syntax=docker/dockerfile:1-FROM golang:alpine AS build+FROM --platform=$BUILDPLATFORM golang:alpine AS build+ARG TARGETOS+ARG TARGETARCHWORKDIR /appADD https://github.com/dvdksn/buildme.git#eb6279e0ad8a10003718656c6867539bd9426ad8 .-RUN go build -o server .+RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o server .FROM alpineCOPY --from=build /app/server /serverENTRYPOINT ["/server"]
  4. Build the image forlinux/amd64 andlinux/arm64:

    $ docker build --platform linux/amd64,linux/arm64 -t go-server .

This example has shown how to cross-compile a Go application for multipleplatforms with Docker builds. The specific steps on how to do cross-compilationmay vary depending on the programming language you're using. Consult thedocumentation for your programming language to learn more about cross-compilingfor different platforms.

Tip

You may also want to consider checking outxx - Dockerfile cross-compilation helpers.xx is a Docker image containing utility scripts that make cross-compiling with Docker builds easier.

Edit this page

Request changes


[8]ページ先頭

©2009-2025 Movatter.jp