Open15

最近のDocker Build仕様

thaimthaim

Dockerビルドのアーキテクチャ
https://docs.docker.com/build/architecture/

UIを提供するのがBuildxで、バックエンドで実際にビルドするのがBuildKit。公式のアーキテクチャ図がわかりやすい。

Builder(BuildKit)はBuildxと同一環境で動作させることもリモート環境で動作させることもできる。
詳しくはBuildersの章で。このあたりリモートでビルドさせてビルドの改善ができないかは気になる。

thaimthaim

Dockerfileによるソフトウェアのパッケージング
https://docs.docker.com/build/building/packaging/

Dockerfileの詳細な仕様はDockerfile referenceで。

複数のDockerfileを利用するときは <something>.Dockerfile とするのが公式推奨の命名規則。
結局 -f で指定するのでこの命名規則を統一するメリットがあるのかは不明。

Dockerfileの先頭コメントにはParser directiveを指定できる。
詳細はParser directiveの通り。
parser directiveにはBuildKitの挙動をカスタマイズするsyntax directiveと、Dockerfileのエスケープ文字(デフォルト \)をカスタマイズするescape directiveがある。
特にバックスラッシュがディレクトリパスのセパレータであるWindows環境ではescape directiveが有益。

thaimthaim

ビルドコンテキスト
https://docs.docker.com/build/building/context/

ビルドコンテキストにはリモートgitリポジトリも指定できて、この場合はリポジトリとすべてのサブモジュールがコンテキストに含まれる。

ビルドコンテキストにローカルファイルシステムを利用するとき、.dockerignoreで除外設定できる。
このとき、Dockerfile別に.dockerignoreを作成することもできる。利用するDockerfile名をprefixに持つdockerignoreが反映される。例えば build.Dockerfileに対しては build.Dockerfile.dockerignoreが専用のdockerignoreファイルになる。
ビルドコンテキストのルート.dockerignoreファイルが共存する場合は、Dockerfile別dockerignoreが優先される(ルート .dockerignoreは無視されるということ?)

ビルドコンテキストにgitリポジトリを指定する場合、タグやブランチ、コンテキストに利用するサブディレクトリなども指定できる。

デフォルトでは .gitディレクトリはビルドコンテキストに含まれないが、 BUILDKIT_CONTEXT_KEEP_GIT_DIR をbuild argumentに指定することで含めることができる。
これはビルド中にgit履歴を利用するとき(git rev-parseなどを利用するとき)に有益。

プライベートリポジトリをコンテキストに指定するときは、SSHクレデンシャルやSSH_AUTH_SOCK、GIT_AUTH_TOKEN(PATなど)を指定する。

thaimthaim

マルチステージビルド
https://docs.docker.com/build/building/multi-stage/

--targetオプションを指定することで特定のステージのみビルドすることもできる。
これはデバッグのため、またはテストのため特定のステージまでビルドしたらビルド処理を止めたいときに有益。
BuildKitはステージの依存関係を確認して依存しないステージのビルドはスキップしてくれる。BuildKit以前のビルドでは依存関係は考慮せず、Dockerfileの先頭から指定のステージまですべてビルドする。

マルチステージビルドでファイルをコピーするときは、 --from=nginx:latestのように指定することで別ステージからだけでなく別イメージからファイルをコピーすることもできる。

thaimthaim

マルチプラットフォームイメージ
https://docs.docker.com/build/building/multi-platform/

ビルド時に--platformを指定することで特定プラットフォーム向けのビルドを実行できる。

マルチプラットフォーム向けのビルドを実行する方法としては、QEMUを利用する、multiple native nodeを利用する、プログラミング言語のクロスコンパイル機能を活用する、の3通りがある。
このあたりは実際に動作確認しながら検証した方がよさそう。

Docker Desktopではマルチアーキテクチャのサポートがあるので特別な設定は不要。

thaimthaim

Builders
https://docs.docker.com/build/builders/

docker buildが実行されるBuildKitデーモンがbuilder。

デフォルトではdefault builderが生成されてそこでビルドが実行される。
default builderはbuild driverとして dockerが選択されており、docker daemonでビルドされる。
その他のdriverとして、別のコンテナ上でビルドを実行するdocker-container、kubernetesクラスタ上でpodとして動作するkubernetes、独自に管理しているBuildKit daemonを利用するremoteが選択できる。

builder一覧を表示する方法としてdocker buildx lsコマンドがある。ここで管理されているbuilderを --builderフラグやBUILDX_BUILDR環境変数で指定して利用できる。

thaimthaim

buildersの管理
https://docs.docker.com/build/builders/manage/

デフォルトでは dockerドライバを利用する。docker ドライバのbuilderは手動で作成できない。
独自のbuilderを作成するときはdocker buildx createコマンドを実行する。デフォルトではdocker-containerドライバで作成されるが、--driverフラグを指定することで別のドライバで作成することもできる。

Docker Desktopでbuilderを管理する方法は現在ベータ版の扱い。

thaimthaim

docker container driver
https://docs.docker.com/build/drivers/docker-container/

docker buildkit createコマンドで新しいbuilderを作成できる。
docker-containerをbuilderとして指定してdocker buildするとき、moby/buildkitのコンテナ上でビルドを実行する。
docker-containerでは明示的に--loadオプションを指定しないとビルドしたイメージは読み込まれない。
docker buildx rmでbuilderを削除するときに --keep-stateオプションを指定することでキャッシュがvolumeとして保持される。
docker-containerでは--platformオプションを指定することで異なる環境をQEMU上で実行することができる。
ビルド時に専用のネットワークを分離したい場合は事前に作成して利用できる。

buildkitのバージョンをカスタマイズするメリットの整理が必要。どのような場合に異なるバージョンのbuildkitを利用したいユースケースがあるか。
キャッシュまわりやQEMU利用はパフォーマンス影響を確認したい。