Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Using BuildKit and TARGETPLATFORM for cross-platform Dockerfiles

License

NotificationsYou must be signed in to change notification settings

BretFisher/multi-platform-docker-build

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Naming is hard. Having a consistent OS (kernel) and architecture naming scheme for building is harder.

Goal: In Docker, our goal should be a single Dockerfile that can build for multiple Linux architectures.A stretch-goal might be cross-OS (Windows Containers), but for now let's focus on the Linux kernel.

Turns out this might be harder then you're expecting.

Docker has BuildKit which makes thismuch easier with thedocker buildx build --platform option, andcombined with theARG TARGETPLATFORM gets us much closer to our goal. See the docs onmulti-platform buildingand theautomatic platform ARGs.

The problem with downloading binaries in Dockerfiles

There are still inconsistencies we need to deal with. This problem rears its ugly head when you'retrying to download pre-built binaries of various tools and dependencies (GitHub, etc.) that don't usea package manager (apt, yum, brew, apk, etc.).Download URLs are inconsistently named, and expect some sort of kernel and architecture combo in the file name.No one seems to agree on common file naming.

Usinguname -m won't work for all architectures, as the name changes based on where it's running. For example, witharm64 (v8) architecture, it might say arm64, or aarch64. In older arm devices it'll say armv71 even though youmight want arm/v6.

There's also the complexity that a device might have one architecture hardware (arm64) but run a different kernel (arm/v7 32-Bit).

The containerd project hascreated their own conversion table,which I'm commenting on here. This is similar to (but not exactly) whatARG TARGETPLATFORM gives us:

//   Value    Normalized//   aarch64  arm64# the latest v8 arm architecture. Used on Apple M1, AWS Graviton, and Raspberry Pi 3's and 4's//   armhf    arm# 32-bit v7 architecture. Used in Raspberry Pi 3 and  Pi 4 when 32bit Raspbian Linux is used//   armel    arm/v6# 32-bit v6 architecture. Used in Raspberry Pi 1, 2, and Zero//   i386     386# older Intel 32-Bit architecture, originally used in the 386 processor//   x86_64   amd64# all modern Intel-compatible x84 64-Bit architectures//   x86-64   amd64# same

So that's a start. But BuildKit seems to do additional conversion, as you'll see in the testing below.

Recommended approach for curl and wget commands in multi-platform Dockerfiles

If we wanted to have a single Dockerfile build across (at minimum) x86-64, ARM 64-Bit, and ARM 32-Bit,we can use BuildKit with theTARGETPLATFORM argument to get a more consistent environment variable in ourRUN commands, but it's not perfect. We'll still need to convert that output to what ourRUN commands need.

TARGETPLATFORM is actually the combo ofTARGETOS/TARGETARCH/TARGETVARIANT so in some cases you could usethose to help the situation, but as you can see below, the arm/v6 vs arm/v7 vs arm/v8 output can make all thistricky.TARGETARCH is too general, andTARGETVARIANT may be blank (in the case ofarm64).

So when I usedocker buildx build --platform, what do I see inside the BuildKit environment?

Here's my results for this Dockerfile:

FROM busyboxARG TARGETPLATFORMARG TARGETARCHARG TARGETVARIANTRUN printf"I'm building for TARGETPLATFORM=${TARGETPLATFORM}" \    && printf", TARGETARCH=${TARGETARCH}" \    && printf", TARGETVARIANT=${TARGETVARIANT}\n" \    && printf"With uname -s : " && uname -s \    && printf"and  uname -m : " && uname -m

Here are the results when using the commanddocker buildx build --progress=plain --platform=<VALUE> .:

  1. --platform=linux/amd64 and--platform=linux/x86-64 and--platform=linux/x86_64

    I'm building for TARGETPLATFORM=linux/amd64, TARGETARCH=amd64, TARGETVARIANT=With uname -s : Linuxand  uname -m : x86_64
  2. --platform=linux/arm64 and--platform=linux/arm64/v8TARGETVARIANT is blank

    I'm building for TARGETPLATFORM=linux/arm64, TARGETARCH=arm64, TARGETVARIANT=With uname -s : Linuxand  uname -m : aarch64
  3. --platform=linux/arm/v8Don't use this. It builds but is inconsistent.I'd think this would be an alias to arm64, but it returns weird results (uname thinks it's 32bit, TARGETARCH is not arm64)

    I'm building for TARGETPLATFORM=linux/arm/v8, TARGETARCH=arm, TARGETVARIANT=v8With uname -s : Linuxand  uname -m : armv7l
  4. --platform=linux/arm and--platform=linux/arm/v7 and--platform=linux/armhf

    I'm building for TARGETPLATFORM=linux/arm/v7, TARGETARCH=arm, TARGETVARIANT=v7With uname -s : Linuxand  uname -m : armv7l
  5. --platform=linux/arm/v6 and--platform=linux/armel

    I'm building for TARGETPLATFORM=linux/arm/v6, TARGETARCH=arm, TARGETVARIANT=v6With uname -s : Linuxand  uname -m : armv7l
  6. --platform=linux/i386 and--platform=linux/386

    I'm building for TARGETPLATFORM=linux/386, TARGETARCH=386, TARGETVARIANT=With uname -s : Linuxand  uname -m : i686

So what then, how do we proceed?

Know what platforms you can build in your Docker Engine

First, you'll need to know what platforms your Docker Engine can build.Docker can support multi-platform builds with thebuildx command.TheREADME is great.By default it only supports the platform that Docker Engine (daemon) is running on, but if QEMU is installed, it can emulate many others.You can see the list it's currently enabled for with thedocker buildx inspect --bootstrap command.

For example, this is what I see in Docker Desktop on a Intel-based Mac and a Windows 10 with WSL2,withlinux/amd64 being the native platform, and the rest using QEMU emulation:

linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

I see the same list in Docker Desktop on a Apple M1 Mac, withlinux/arm64 being the native platform, and therest using QEMU emulation:

linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

This is what I see in Docker for Linux on a Raspberry Pi 4 with Raspbian (32bit as of early 2021). QEMU isn'tenabled by default, so only the native options show up:

linux/arm/v7, linux/arm/v6

This is what I see in Docker for Linux on a Digital Ocean amd64 standard droplet. Notice again,QEMU isn't setup so the list is much shorter:

linux/amd64, linux/386

Add Dockerfile logic to detect the platform it needs to use

Let's usetini as an example of how to ensure that a singleDockerfile and download the correct tini build into our container image for Linux on amd64, arm64, arm/v7, arm/v6, and i386.We'll use a separate build-stage, evaluate theTARGETPLATFORM, and manually convert the value(viash case statement) to what the specific binary URL needs.

This was inspired by @crazy-max in hisdocker-in-docker Dockerfile.

See the full Dockerfile here:example-tini\Dockerfile

FROM --platform=${BUILDPLATFORM} alpine as tini-binaryENV TINI_VERSION=v0.19.0ARG TARGETPLATFORMRUN case ${TARGETPLATFORM} in \"linux/amd64")  TINI_ARCH=amd64  ;; \"linux/arm64")  TINI_ARCH=arm64  ;; \"linux/arm/v7") TINI_ARCH=armhf  ;; \"linux/arm/v6") TINI_ARCH=armel  ;; \"linux/386")    TINI_ARCH=i386   ;; \    esac \ && wget -q https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static-${TINI_ARCH} -O /tini \ && chmod +x /tini

Further Reading

Docker Blog from Adrian Mouat onmulti-platform Docker builds.

MORE TO COME, WIP

  • Background on manifests, multi-architecture repos
  • Using third-party tools likeregctl to make your life easier (i.e.regctl image manifest --list golang)
  • Breakdown the three parts of the platform ARG better

About

Using BuildKit and TARGETPLATFORM for cross-platform Dockerfiles

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

    Packages

     
     
     

    Contributors2

    •  
    •  

    [8]ページ先頭

    ©2009-2025 Movatter.jp