イメージのビルド高速化機構 Docker BuildKit、BuildX を理解していなかったので調べてみました
はじめに
Dockerfile
を作成した後は docker build
コマンドを使って Docker イメージをビルドします。
ある日を境に docker build
コマンド実行時のコンソールメッセージの表示が様変わりしたのですが、
これは Docker (正確には僕のローカル PC で利用している Docker for Mac) に BuildKit と言われるものが導入されたためのようです。
この BuildKit について理解していませんでしたので、調べてみました。
検証環境
$ uname -moi
x86_64 MacBookPro16,1 Darwin
$ bash -version | head -n 1
GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0)
$ docker --version
Docker version 20.10.7, build f0df350
BuildKit とは?
BuildKit は、 Docker の 18.06 から試験的に導入され、18.09 以降で正式に導入された機構になります。
ビルド処理時にバックグラウンドで実行されます。
環境変数を使って有効化することができる という記事を拝見しましたが、
僕の PC では特に環境変数を設定していない状態でいつの間にかビルド時の表示が変わっていたので、
もう正式導入しているようです。
従来の docker build
コマンドでは、Dockerfile
の各命令( FROM
とか RUN
とか )を順番に実行していきます。
ビルド時の各命令実行結果はすべて レイヤ としてイメージに保存されます。
こうしてミルフィール上のレイヤをもつ Docker イメージ が出来上がります。
BuildKit を有効にすると、
これまで「直列」で順次実行されていた命令をできる限り「並列」に実行します。
結果、Docker イメージのビルドにかかる時間が削減されるというわけです。
ちなみに、Github のリポジトリは以下になります。
BuildKit の特徴
Github ページには、以下のような特徴があると書かれています。
- 自動的なゴミ掃除(ガベージコレクション)
- 拡張されたフロントエンドフォーマット(?)
- 同時実行のための効率的な依存性解決
- このあたりが Docker イメージの従来の直列性を改善するための秘策なのでしょう
- 効率的なキャッシュ
- 従来との違いがわかりませんが、キャッシュ機能が効率化したようです
- ビルドキャッシュのインポート、エクスポート
- ネストされたビルドジョブの呼び出し
- 分散ワーカー
- 複数のアウトプットフォーマット
- プラガブルな設計
- プラグインによる拡張などができるということ?
- ルート権限無しでの実行
- 従来の
docker build
は、ルート権限で実行されていたようですね。
- 従来の
moby プロジェクトが作成したビルドツールキットであり、Docker とは独立しているプロジェクトで開発されたものです。
加えて、キャッシュを効率的に利用でき、
リモートのコンテナレジストリ( ex: DockerHub、GCR、ECR )にキャッシュを保存する機構もあるようです。
BuildKit の有効化
以前は環境変数を設定する必要がありました。
$ export DOCKER_BUILDKIT=1
僕は Docker for Mac を利用していますが、
設定画面から以下のように "buildkit": true
と書かれていることが確認できれば、環境変数は不要です。
Dcoker for Mac のメニューから Preferences > Docker Engine
と開くと閲覧できます。
こちらの設定を変更した後、Docker for Mac を再起動をお忘れなく。
あまり実感は有りませんが、これだけで Docker イメージのビルド処理が改善されます。
BuildKit のインストール
docker build
コマンドの内部が BuildKit を利用するように置き換えられているのでbuildkit
を明示的に個別に呼び出すケースはほぼないと思いますが、
Mac でインストールしたい場合は以下のコマンドが利用できます。
$ brew install buildkit
更にビルドの性能を向上させる BuildX
BuildKit の恩恵について見てきました。
といっても最新の Docker 環境を利用している限り、すでに有効になっており特に何もしなくてよいというわけです。
ここで更にビルドの性能を向上させる方法として、 BuildX というものを利用する事ができます。
BuildX は BuildKit の拡張です。
BuildKit の機能を完全サポートしていて、更に docker
コマンドを拡張する CLI のプラグインです。
コマンドは docker build
の代わりに docker buildx build
を使えばいいだけのようです。
それではビルドを実行してみます。
$ docker buildx build -t x . --no-cache
[+] Building 81.7s (7/7) FINISHED
$ time docker build -t x . --no-cache
[+] Building 120.9s (7/7) FINISHED
あんまり違いがなさそうですが、ごもっともで、 apt-get install
しかしていない Dockerfile を使ってのビルドでした。
ちなみに BuildX のドキュメントを見てみると、
Set buildx as the default builder
Running the command
docker buildx install
sets up docker builder command as an alias to docker buildx.
This results in the ability to have docker build use the current buildx builder.
To remove this alias, run docker buildx uninstall.
docker buildx install
コマンドを実行すると、 docker build
コマンド実行時に BuildX が利用されるように変わってくれるとのこと。
早速試してみました。
$ docker buildx install
何も表示されませんが有効になったということでしょうか?
もしかしたらすでに有効になっていたのかもしれません。
なにはともあれ docker build
コマンド実行時に BuildX が使われるようになりましたので、学習を続けながらこのまま利用してみようと思います。
DockerHub の Automated Build ではすでに BuildKit が使われている
DockerHub には Github と連携し、Github へのプッシュを受けて dockker build
を実行する、という機構があります。
これを Automated Build とよんでいますが、このなかでは BuildKit が使われているようです。
なぜかというと、ビルド失敗時のログメッセージとして、 以下のようなメッセージが表示される時があるためです。
failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to build LLB: executor failed running
LLB というのは BuildKit の中にあるコンポーネントです。
dockerfile.v0 も同様です。
ひとこと
結論としては、だんだん docker build
の性能は改善されていて、その恩恵を受けるためにしないといけないことは特にないよ (よしなにやってくれている) 、ということでした。
ディスカッション
コメント一覧
まだ、コメントがありません