雰囲気でbuildx/BuildKitを使っていたので調べました
tl;dr
- BuildKitのお陰で様々なbuildでの恩恵が受けられている
- buildxのお陰で今まで利用していた
docker
cliのままBuilkdKitが使えている - もっと有効活用したい機能が沢山ある。。。
- 長いです。。。こちらのNTTの徳永さんのスライドがとてもわかり易い & 纏まっていておすすめです
はじめに
相当前ですが、dockerにbuildxコマンドが入ったことでなんとなくBuildKitというものを認識して使っていました。
ただ、その中でもmulti-platform buildを雰囲気で使っていたくらいで、
他にどういう機能があるのか、そもそもBuildKitって何?みたいなことはあまり考えていませんでした。
先日、--mount=type=ssh
を使うときに少し嵌って調べたところ、様々な機能や重要なconceptを知らなかったことに気づいたので調べたことをまとめたいと思います。
出てくる用語について
buildxとBuildKitの関係性も怪しいのでそこから調べました。
また、その際に出てきた重要そう、かつ知らなかった用語のMobyやbuildxの用語のbuild driver, builder instance等についてもここで纏めます。
用語の理解を深めるために軽く手を動かした詳細についても記載します。
buildx
buildx is a Docker CLI plugin for extended build capabilities with BuildKit.
https://github.com/docker/buildx
とのことで、BuildKitをDockerから利用するための拡張のようです。
(プラスbake
などのBuildKit利用以外の機能も含まれている。)
また、build driver(後述)の1つであるdocker driverの説明にはこの様に書かれていて、
The Buildx Docker driver is the default driver. It uses the BuildKit server components built directly into the Docker engine.
https://docs.docker.com/build/drivers/docker/
BuildKitサーバはDocker engineに組み込まれて提供されていること。
defaultではその組み込まれたBuildKitサーバコンポーネントを利用することが分かりました。
build driver
先程出てきましたBuild driverについてです。
Build drivers are configurations for how and where the BuildKit backend runs.
https://docs.docker.com/build/drivers/
BuildKitバックエンドをどこでどの様に動かすのかを定める定義とのことです。
ここでのBuildKit backendはプロセスと同じような意味で使われていると思われます。
ここにDocker Buildに関するbuildxとBuildKitの関係図とシーケンス図が記載されています。
build driverは以下の4種類のdriverをサポートしています。
- docker
- default driver
- DockerデーモンにバンドルされたBuildKitライブラリを使う
- docker-container
- BuildKitコンテナをDocker上で動かして使う
- kubernetes
- BuildKitポッドをKubernetes cluster上に動かして使う
- remote
- 別に管理されたBuildKitデーモンに直接接続して使う
また、以下の図のようにそれぞれのdriverごとに微妙にできることも変わってくるようです。
https://docs.docker.com/build/drivers/ より参照
builder instance
builder instanceについては明確に説明されている文章を見つけられなかったのですが、
builder instanceを作成するbuildx create
の説明から想像して書きます。
builder instanceは実際にbuildx build時に使うdriver, buildkitd flag,BuildKit config,platformなどの設定の集合体かと思われます。
[確認] build driver/builder instance
builder instanceを確認するbuildx ls
コマンドの出力を見てみます。
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
desktop-linux * docker
desktop-linux desktop-linux running v0.11.6+616c3f613b54 linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
docker
driverをつかうdesktop-linux
builder instanceが設定されていますね。
ここは何もいじっていないのでDocker Desktopインストール時にbuildxがdefaultでこのあたりを定義してくれているということでしょうか。
試しに別のbuilder instanceを作成し動かしてみます。
$ docker buildx use $(docker buildx create --name new)
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
new * docker-container
new0 desktop-linux inactive
desktop-linux docker
desktop-linux desktop-linux running v0.11.6+616c3f613b54 linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
定義したnew
builder instanceが増えて、かつ現在はそちらを向いていそうですね。
ただ、STATUS
がinactive
となっています。これはBuildKit containerがまだ起動してない状態かと思われます。
buildx create
の--driver
オプションには、
Driver to use (available: docker-container, kubernetes, remote)
と記載されていて、docker
driverは2つ目は定義できなさそうでした。
また、指定しなかった場合はdocker-container
driverが選択されましたね。
実際にbuildをしようと思います。build中の動きを少し見れるように以下のdockerfileを使います。
FROM alpine
RUN sleep 30s
$ docker buildx build .
[+] Building 41.3s (6/6) FINISHED docker-container:new
=> [internal] booting buildkit 8.2s
=> => pulling image moby/buildkit:buildx-stable-1 7.4s
=> => creating container buildx_buildkit_new0 0.8s
=> [internal] load build definition from dockerfile 0.0s
=> => transferring dockerfile: 64B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 2.2s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/2] FROM docker.io/library/alpine:latest@sha256:51b67269f354137895d43f3b3d810bfacd3945438e94dc5ac55fdac340352f48 0.5s
=> => resolve docker.io/library/alpine:latest@sha256:51b67269f354137895d43f3b3d810bfacd3945438e94dc5ac55fdac340352f48 0.0s
=> => sha256:c303524923177661067f7eb378c3dd5277088c2676ebd1cd78e68397bb80fdbf 3.35MB / 3.35MB 0.3s
=> => extracting sha256:c303524923177661067f7eb378c3dd5277088c2676ebd1cd78e68397bb80fdbf 0.1s
=> [2/2] RUN sleep 30s 30.1s
WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
最初に
[internal] booting buildkit
=> => pulling image moby/buildkit:buildx-stable-1
と見えましたね。docker-container
driverなので、BuildKitのcontainer imageを取得し、動かしてくれているログのようです。
containerを確認してみると、たしかにBuildKit containerが動いていますね。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f4c6351ca39 moby/buildkit:buildx-stable-1 "buildkitd" 4 seconds ago Up 3 seconds buildx_buildkit_new0
最初はinactive
であったSTATUS
もactive
になりました。
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
new * docker-container
new0 desktop-linux running v0.12.4 linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
desktop-linux docker
desktop-linux desktop-linux running v0.11.6+616c3f613b54 linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
また、buildログの最後に出力された
WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
については、build driver 項目に貼った表のとおり、
Automitically load Image
はdocker
driverだけの機能なので、それ以外のdriverを使う場合にはbuild結果をどうしたいかを記載しないとだめなようですね。
buildx build
のoptionに--push
を指定してregistryにpushするか、--load
を指定してdockerにloadさせる方法をWARNINGとして提案してくれています。
BuildKit
BuildKitに辿り着く前が長くなってしまいましたがようやくBuildKitです。
ここまででおおよそ分かってきましたが、buildxの内部でも利用されているbuildを高機能にしてくれるツールキットのようです。
BuildKit is a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner.
https://github.com/moby/buildkit/tree/master
Key featuresとして以下が挙げられています。
- Automatic garbage collection
- Extendable frontend formats
- Concurrent dependency resolution
- Efficient instruction caching
- Build cache import/export
- Nested build job invocations
- Distributable workers
- Multiple output formats
- Pluggable architecture
- Execution without root privileges
いくつかのすぐに使いそうな機能は後で纏めます。
BuildKitは以下で使われていると自身のREADMEに書いています。
- Moby & Docker (DOCKER_BUIDKIT=1 docker build)
- Docker buildx
- Tekton Pipelines(formerly Knative Build Templates)
- Gitpod
- Dagger
- などなど
そのためBuildKitの機能を勉強すると、Dockerからだけでなく、
様々なcontainer buildツールから利用でき、便利になっていきますね。
また、repository organizationにmobyが出てきました。
最後にmobyについて纏めます。
Moby
Moby is an open framework created by Docker to assemble specialized container systems without reinventing the wheel.
https://mobyproject.org/
The Moby Project is a new open-source project to advance the software containerization movement and help the ecosystem take containers mainstream. It provides a library of components, a framework for assembling them into custom container-based systems and a place for all container enthusiasts to experiment and exchange ideas.
https://www.docker.com/blog/introducing-the-moby-project/
MobyはDocker社が作ったソフトウェアのコンテナ化を加速させるOSSプロジェクトを指すようです。
その中には以下のOSSがあります。(詳細はここで見れます。)
- containerd
- ruc
- buildkit
- moby
- などなど
containerdやruncも、、?と思ったのですが、
runcはOCIへ、containerdはCNCFへDocker社から寄贈されたようです。
また、Docker engineのソースがOSSとしてMobyプロジェクトのmobyとなっているようです。
AKB428さんの以下の図がとても分かりやすかったです。
https://zenn.dev/akb428/articles/49e51d4db36896 より参照
纏め
用語 | 概要 |
---|---|
buildx | BuildKitをDockerから利用するための拡張機能+α |
build driver | BuildKitバックエンドをどこでどのように動かすかを定めるもの |
builder instance | buildxが利用するdriverやその他の設定の集合体 |
BuildKit | container buildを高機能にしてくれるツールキット。Mobyプロジェクトの中の1つ。 |
Moby | Docker社が作ったOSSプロジェクト(群)。また、Docker engineのOSSとしての名前。 |
BuildKitの機能について
BuildKitの機能について記載していきます。
LLBとは
At the core of BuildKit is a Low-Level Build (LLB) definition format.
https://docs.docker.com/build/buildkit/
と記載されており、buildkitのコア部分はこのLLBのようです。
LLBとは何でしょうか。
buildkitのrepoにはこう記載されていました。
Exploring LLB
BuildKit builds are based on a binary intermediate format called LLB that is used for defining the dependency graph for processes running part of your build. tl;dr: LLB is to Dockerfile what LLVM IR is to C.
https://github.com/moby/buildkit#exploring-llb
依存関係グラフを定義するために使われる中間表現がLLBであり、DockerfileにおけるLLBはC言語におけるLLVM IRだと。
LLVMのようにfrontend, backendがあって
frontendが中間表現(LLB)を生成し、backendが最終成果物(image)を作成するという流れが想像できました。
Extendable frontend formats
Key Featuresの1つ Extendable frontend formats
を見ていきます。
と言っても、明確にこの機能がこのKey Featureだと記載されているわけではないので、なんとなくこれかなという感じです。
Frontends are components that run inside BuildKit and convert any build definition to LLB. There is a special frontend called gateway (gateway.v0) that allows using any image as a frontend.
https://github.com/moby/buildkit#exploring-dockerfiles
と記載されているとおり、任意のbuild定義をLLBに変換するコンポーネントがfrontendです。
現在サポートされているfrontendとしては以下があるようです。
- Dockerfile
- Mockerfile
- Nix
- Cargo Wahrf (Rust)
- などなど。他にもたくさんありました。
現在は開発中なのでDockerfile frontend(dockerfile.v0
)はBuildKit repoに入っていますが、将来的には外だしされる予定とのことです。
また、gateway.v0
というfrontnendは特別なfrontendで、任意のcontainer imageをfrontendとして使うことができます。
Dockerfile frontendはこのgateway.v0
を使うことで、Dockerfile形式以外の形式をbuildする仕組みがあるようです。
例えば以下です。
# syntax=r2d4/mocker
apiVersion: v1alpha1
images:
- name: demo
from: ubuntu:16.04
package:
repo:
- deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8
- deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial edge
gpg:
- https://bazel.build/bazel-release.pub.gpg
- https://download.docker.com/linux/ubuntu/gpg
install:
- ca-certificates
- git
- gcc
external:
- src: https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/amd64/kubectl
dst: /usr/local/bin/kubectl
- src: https://github.com/kubernetes-sigs/kustomize/releases/download/v1.0.8/kustomize_1.0.8_linux_amd64
dst: /usr/local/bin/kustomize
sha256: b5066f7250beb023a3eb7511c5699be4dbff57637ac4a78ce63bde6e66c26ac4
このファイルはMockerfileのリンク先に記載されていたMockerfileの例を一部短くするため & エラーが発生したのでその部分を除外したものです。
先頭に# syntax=r2d4/mocker
と記載されています。
これはここに記述されているCustom Dockerfile syntax
で、
# syntax=[remote image reference]
を指定することでBuildKit frontendとして利用する実装をcontainerで提供/利用することができます。
上記Mockerfileだとr2d4/mocker
imageを使いMockerfileをLLBにbuildして最終的な成果物が作成されます。
実際に動かすと以下のようになります。
$ docker build -f Mockerfile.yaml .
[+] Building 39.8s (24/24) FINISHED docker:desktop-linux
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build definition from Mockerfile.yaml 0.0s
=> => transferring dockerfile: 830B 0.0s
=> resolve image config for docker.io/r2d4/mocker:latest 1.4s
=> CACHED docker-image://docker.io/r2d4/mocker@sha256:d34c92c892d73513e8c73beed920575df12819c66cb1df872e4aa65a20c25e9d 0.0s
=> [internal] load Mockerfile from Mockerfile.yaml 0.0s
=> => transferring dockerfile: 830B 0.0s
=> CACHED docker-image://docker.io/library/alpine:3.6 1.1s
=> => resolve docker.io/library/alpine:3.6 1.1s
=> docker-image://docker.io/library/ubuntu:16.04 0.8s
=> => resolve docker.io/library/ubuntu:16.04 0.8s
=> CACHED /bin/sh -c apt-get update && apt-get install apt-transport-https -y 0.0s
=> CACHED /bin/sh -c echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" >> /etc/apt/sources.list 0.0s
=> CACHED /bin/sh -c echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial edge" >> /etc/apt/sources.list 0.0s
=> CACHED apk add --no-cache curl 0.0s
=> CACHED curl -Lo /key.gpg https://bazel.build/bazel-release.pub.gpg 0.0s
=> CACHED cp -a /src/key.gpg /dest/key.gpg 0.0s
=> CACHED /bin/sh -c apt-key add /key.gpg && rm /key.gpg 0.0s
=> CACHED curl -Lo /key.gpg https://download.docker.com/linux/ubuntu/gpg 0.0s
=> CACHED cp -a /src/key.gpg /dest/key.gpg 0.0s
=> CACHED /bin/sh -c apt-key add /key.gpg && rm /key.gpg 0.0s
=> CACHED /bin/sh -c curl -Lo /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.10.0/bin/linux/amd64/kub 0.0s
=> /bin/sh -c apt-get update && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates git gcc 35.9s
=> CACHED /bin/sh -c curl -Lo /usr/local/bin/kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v1.0.8/kustomize_1.0 0.0s
=> CACHED /bin/sh -c echo "b5066f7250beb023a3eb7511c5699be4dbff57637ac4a78ce63bde6e66c26ac4 /usr/local/bin/kustomize" | sha256sum -c - 0.0s
=> cp -a /src/usr/local/bin/kubectl /dest/usr/local/bin/kubectl 0.4s
=> cp -a /src/usr/local/bin/kustomize /dest/usr/local/bin/kustomize 0.2s
=> exporting to image 0.4s
=> => exporting layers 0.4s
=> => writing image sha256:8f36c49e32ff92522180b1907220b10d9abfda08b0ed27ecf11eb932e59c4219 0.0s
何度かbuildした結果を取ったのでCACHEDになっていますが、# sytanx
で指定したimageを取得して利用していますね。
Dockerfile fronendは# syntax
の宣言があると、gateway.v0
としてBuildKitを呼び出すことでこのような動きができるのかと思われます。
# syntax=
が存在するかを判定して、ある場合はforwardGateway
を呼び出し。
forwardGateway
でgateway.v0
を設定している感じのようです。
このCustom Dockerfile syntax
を利用することで、
- Dockerデーモンのupdate無しにbugfixや最新機能を受け取れる(最新のdocker frontend imageを利用すれば良い)
- 全ユーザが同じbuild結果を保証できる(Dockerデーモンのバージョン差分による差が出ない)
というメリットがあります。
また、このMockerfileの例のように、様々なbuild定義をdocker(buildx)から変わらず利用することができるのと、
自身でBuildKit frontendを実装したimageを作成することもできます。
Build cache import/export
BuildKitは以下のcache exporterをサポートしています。
- inline
- 成果物のimageのconfigにcache metadataが付属される
- registry
- 成果物のimageとは別にcache用imageをrepositoryにpushする
- local
- localディレクトリにcache imageファイルを出力する
- フォーマットはOCI Image Spec v1.0に準拠する
- gha
- GitHub Actions cacheに保存する
- S3 (experimental)
- S3にcache imageファイルを保存する
- Azure Blob Storage (experimental)
- Azure Blob Storageにcache imageファイルを保存する
上記exporterは--export-cache
オプションのtype=inline|registry|local|gha|s3|azblob
で指定できます。
各typeごとに固有のオプションがあるものもあります。
共通して重要なオプションにmode=<min|max>
があります。(inlineはmin
modeだけサポート。)
- min
- 成果物イメージのlayerだけが対象
- max
- すべての中間ステップのlayerが対象
また、exportと対応して--import-cache
オプションもtypeを指定して利用します。
buildxからの利用
buildxからcacheを利用するには以下のように--cache-to
と--cache-from
オプションを指定します。
$ docker buildx build --push -t <registry>/<image> \
--cache-to type=registry,ref=<registry>/<cache-image>[,parameters...] \
--cache-from type=registry,ref=<registry>/<cache-image>[,parameters...] .
buildxの先にはBuildKitがいるのでオプション名以外は同じ構造ですね。
また、buildx(と恐らく直にBuildKitも)はMultiple cache
をサポートしているようです。
$ docker buildx build --push -t <registry>/<image> \
--cache-to type=registry,ref=<registry>/<cache-image>:<branch> \
--cache-from type=registry,ref=<registry>/<cache-image>:<branch> \
--cache-from type=registry,ref=<registry>/<cache-image>:main .
上記例で書いているように、branchとmainを読み込んだり、BuildKitのProposalで書いてあるlatestとimage hash指定を読み込むことでcache hit率を高める狙いがあるようです。
このあたり色々と試してみようと思います。
multi-platform images
BuildKitはmulti-platformビルドをbuilt-inでサポートしています。
以下の例のように対象のplatformをカンマ区切りで並べて渡すことで、複数platformに向けてbuildしてくれます。
$ buildctl build \
--frontend dockerfile.v0 \
--opt platform=linux/amd64,linux/arm64 \
--output type=image,name=docker.io/username/image,push=true \
...
ビルド対象のplatformがnativeにサポートされていない環境でビルドする場合には、QEMUが動き、そこでビルドされます。
このため、バイナリのコンパイルのようなCPU負荷の高いタスクには推奨されない、と書いてあります。
コンパイルステップにてnative performanceを得るにはpredefined platform ARGsを利用するか、xx projectを利用して最低限の変更でクロスコンパイルツールチェーンを追加すると良いようです。
ここを見ると良いと書いてあったので少し見ます。(xxの作者の記事のようですね。)
One way to avoid this overhead is to modify your Dockerfile so that the longest-running commands don’t run through an emulator. Instead, we can use a cross-compilation stage.
https://medium.com/@tonistiigi/faster-multi-platform-builds-dockerfile-cross-compilation-guide-part-1-ec087c719eaf
とあるようにうまくクロスコンパイルができる記述をすれば良いようですね。
その方法が以下の2つのようです。
- predefined platform ARGs
- xx
それぞれ具体的に見てみます。
Faster Multi-platform builds by predefined platform ARGs
DockerfileのFROM
句には--platform
を指定して、platformを指定できます。
これと以下の変数を組み合わせることで全環境で有効なクロスコンパイル定義が記述できます。
BUILDPLATFORM — matches the current machine. (e.g. linux/amd64)
BUILDOS — os component of BUILDPLATFORM, e.g. linux
BUILDARCH — e.g. amd64, arm64, riscv64
BUILDVARIANT — used to set ARM variant, e.g. v7
TARGETPLATFORM — The value set with --platform flag on build
TARGETOS - OS component from --platform, e.g. linux
TARGETARCH - Architecture from --platform, e.g. arm64
TARGETVARIANT
例えば以下です。
FROM alpine AS build
# RUN <install build dependecies/compiler>
# COPY <source> .
ARG TARGETPLATFORM
RUN compile --target=$TARGETPLATFORM -o /out/mybinary
FROM alpine
# RUN <install runtime dependencies installed via emulation>
COPY /out/mybinary /bin
こう書くことでbuild
ステップではalpine
イメージがbuild環境のarchitectureで動くことで高速にコンパイルを行うことができ、
最後の成果物のステップではbuildx build --platform
で渡したtargetとなるarchitectureで作成できます。
また記事にはGoの依存関係の取得をより良くする方法も記載されていました。
Faster Multi-platform builds by xx
上記の例だと相当簡単に、かつ綺麗に高速化の対応ができましたが、Goなどの依存関係を考える対応をすると複雑になってきます。
そこで使えるのがこのxxです。
(という理解です。Faster Multi-platform builds: Dockerfile cross-compilation guide (Part 1)の次が読みたいです。)
xx
は--platform
フラグで渡される値を理解し、クロスコンパイルをサポートしてくれるツールです。
xx
は
- xx-info
- xx-verify
- xx-apl
- xx-apt-get
- xx-cc
- xx-cargo
などのコマンドを含んでおり、以下の様に利用します。
FROM tonistiigi/xx AS xx
FROM alpine
# copy xx scripts to your build stage
COPY / /
# export TARGETPLATFORM (or other TARGET*)
ARG TARGETPLATFORM
# you can now call xx-* commands
RUN xx-info env
弊社ではRustを使っているので、xx-cargo
を利用することで、クロスプラットフォームでの依存関係の解消などをxx
が担ってくれて、すぐにbuildができるのだと思われます。
(試してみて追記できればです。)
READMEに載っているcacheなども考慮したbuild部分の記述例は以下です。
# syntax=docker/dockerfile:1
FROM rust:alpine
RUN apk add clang lld
# ...
RUN \
cargo fetch
ARG TARGETPLATFORM
RUN \
xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
xx-verify
でターゲットプラットフォームのバイナリが問題なく出力されたかどうかを検証することができるようです。
終わりに
これまでは、書いたことの半分も理解できておらず雰囲気でdocker build
していました。
あまり理解していなくてもBuildKit
のメリットが受け取れていたのはbuildx
のおかげだと感謝するとともに、使えていない便利な機能がたくさんあったので、うまく利用して良い開発時間を過ごしていきたいと思います。
また、理解が怪しいまま書いているところが多々ありますので、変なところを見つけた際にはご指摘いただければ幸いです。
今回書か(け)なかったこととしては、
- buildxのBakeについて
- BuildKitのGC、rootless機能、Otelサポート等
などがあります。私が分かっていないだけで、恐らくbuildx/BuildKitにはもっと様々な便利な機能があると思われます。
またどこかの時間で調べてブログに纏められたらと思っています。
最後まで見ていただいてありがとうございます。
参考
Discussion