はい、承知いたしました。【初心者向け】Docker Buildx入門:高速・効率的なビルド方法を解説 の詳細な説明を含む記事を約5000語で記述します。
【初心者向け】Docker Buildx入門:高速・効率的なビルド方法を徹底解説
Dockerを使ってアプリケーションをコンテナ化する上で、欠かせないのがDockerイメージの「ビルド」です。docker build
コマンドにDockerfileを渡すことで、必要なファイルや設定が詰まったDockerイメージを作成できます。
しかし、プロジェクトが大規模になったり、複数のプラットフォーム(Intel Mac/PC, ARM Mac/Raspberry Piなど)に対応する必要が出てきたりすると、従来のdocker build
にはいくつかの限界が見えてきます。ビルドに時間がかかったり、マルチプラットフォーム対応が面倒だったり、キャッシュがうまく効かずに再ビルドに時間がかかったりといった問題に直面することがあります。
そこで登場するのがDocker Buildxです。
Buildxは、Dockerにおける次世代のビルドコマンドであり、そのバックエンドにはBuildKitという強力なビルドエンジンが使われています。Buildxを利用することで、ビルドの高速化や効率化はもちろん、マルチプラットフォームイメージの簡単なビルド、高度なキャッシュ管理、セキュリティ機能など、様々なメリットを享受できます。
この記事では、「Docker Buildx入門」として、Buildxの基本的な使い方から、なぜ高速・効率的にビルドできるのか、そして実践的な活用方法までを、初心者の方にも分かりやすく徹底的に解説します。この記事を読めば、あなたのDockerビルドがより快適で強力になること間違いなしです。
この記事で学べること
- 従来の
docker build
の限界とBuildxが必要な理由 - Buildxの基盤であるBuildKitとは何か
- Buildxの基本的な使い方
- Buildxによるビルド高速化・効率化の仕組み(並列処理、キャッシュ)
- Buildxを使ったマルチプラットフォームイメージのビルド方法
- ビルダーインスタンスの管理と活用
- Buildxの便利な機能(secrets, ssh, 出力形式)
- CI/CDパイプラインでのBuildx活用方法
さあ、Buildxの世界に飛び込み、より良いDockerビルドをマスターしましょう!
1. なぜDocker Buildxが必要なのか?従来のdocker build
の限界
まずは、私たちが普段利用しているdocker build
がどのように動作し、どのような課題を抱えているのかを見ていきましょう。
1.1 docker build
の動作原理
従来のdocker build
コマンドは、内部でDockerデーモンが持つ従来のビルド機能(”classic builder”や”V1 builder”と呼ばれることもあります)を利用しています。
- コンテキストの送信:
docker build .
のように実行すると、指定されたパス(.
など)にあるDockerfileや関連ファイルがDockerデーモンに送信されます。これを「ビルドコンテキスト」と呼びます。.dockerignore
ファイルがある場合、そこに指定されたファイルは送信されません。 - Dockerfileの解析: Dockerデーモンは受け取ったDockerfileを1行ずつ解析します。
- ステップごとの実行: Dockerfileの各命令(
FROM
,RUN
,COPY
,ENV
など)を上から順番に実行します。- 各命令は、基本的に新しいコンテナを作成し、その中で操作を行い、結果を新しいイメージレイヤーとしてコミットするという流れを繰り返します。
- 前のステップで作成されたイメージが、次のステップのベースイメージとなります。
- キャッシュの利用: 同じDockerfileで、かつ変更されていないステップがある場合、Dockerは前のビルドで作成された既存のイメージレイヤーを再利用します(キャッシュヒット)。これにより、ビルド時間を短縮します。キャッシュは、各命令とその入力(ファイルの内容など)に基づいて判断されます。
- 最終イメージの生成: 全てのステップが完了すると、最終的なDockerイメージが生成され、Dockerデーモンに保存されます。
1.2 従来のdocker build
が抱える課題
このシンプルで分かりやすい仕組みは、多くの場合で十分機能します。しかし、特定の状況では非効率性や限界が見えてきます。
- ビルドの並列性の欠如: 基本的にDockerfileの命令は上から順に直列に実行されます。たとえ依存関係のないステップであっても、前のステップが完了するまで次のステップは開始されません。これにより、ビルド全体にかかる時間が長くなることがあります。
- キャッシュの限界: 従来のキャッシュは、各ステップの「直前のレイヤー」と「現在の命令+引数」に基づいてキャッシュキーを生成します。
COPY
命令などの場合、コピー元ファイルの変更もキャッシュキーに含まれますが、キャッシュの判断粒度が荒い場合があります。また、特定のディレクトリ(例:パッケージマネージャーのキャッシュディレクトリ)をステップを跨いで効率的にキャッシュするのが難しい場合があります。 - マルチプラットフォームビルドの複雑さ: 異なるCPUアーキテクチャ(例:x86-64とARM64)向けのイメージをビルドしたい場合、従来の
docker build
は通常、そのビルドを実行しているホストのアーキテクチャ向けのイメージしか生成できません。複数のアーキテクチャに対応するには、以下のようなワークアラウンドが必要でした。- 各アーキテクチャのホストマシンで個別にビルドする。
- QEMUのようなエミュレーターを使ってクロスアーキテクチャビルドを行うが、設定が面倒だったりパフォーマンスが低かったりする。
- 複雑なスクリプトを書いて、複数のビルドを自動化・統合する。
これは非常に手間がかかり、エラーも発生しやすくなります。
- 出力形式の制限: 従来の
docker build
は、ビルド結果を主にローカルのDockerデーモンにイメージとして保存することしかできませんでした。ビルド結果をtarファイルとして出力したり、直接レジストリにプッシュしたり、中間ファイルを検査したりといった柔軟な出力制御が困難でした。 - セキュリティ機能の不足: ビルド中にAPIキーやパスワードなどの秘匿情報を扱う場合、
--build-arg
を使う方法は履歴に残る可能性があったり、安全な方法とは言えませんでした。また、プライベートリポジトリのクローンなどにSSHキーを利用するのも容易ではありませんでした。 - 実験的な機能の取り込み遅延: 新しいビルド機能(例:特定のファイルだけをステージ間でコピーする機能など)は、従来のビルダーにはなかなか取り込まれませんでした。
これらの課題を解決するために開発されたのが、BuildKitをバックエンドとするDocker Buildxです。
2. Docker Buildxとは? BuildKitとの関係
Docker Buildxは、これらの課題を解決するために設計された、Dockerの公式なビルドコマンド拡張です。そして、Buildxの裏側で実際にビルドを実行しているエンジンがBuildKitです。
2.1 BuildKitとは
BuildKitは、コンテナイメージをビルドするための新しい高性能で並列性の高いオープンソースのツールキットです。Mobyプロジェクト(Dockerの中核技術を開発するプロジェクト)の一部として開発されています。
BuildKitは従来のビルドエンジンを根本的に見直し、以下の特徴を持っています。
- 高速な並列処理: Dockerfileの命令間の依存関係を解析し、可能な限り並列に実行します。
- 効率的なキャッシュ管理: キャッシュの粒度を細かくし、より確実にキャッシュヒットするように改善されています。また、ビルドキャッシュを外部にエクスポート・インポートする機能も持ちます。
- プラグイン可能なアーキテクチャ: フロントエンド(Dockerfileパーサーなど)やバックエンド(ビルダー実行環境)をプラグインとして拡張できるようになっています。
- 高度なセキュリティ機能: ビルド中のsecrets管理やSSHエージェントフォワーディングなどの機能を提供します。
- 多様な出力形式: ビルド結果をDockerイメージとして保存するだけでなく、OCIイメージ、tarファイル、ローカルディレクトリなど、様々な形式で出力できます。
- マルチプラットフォーム対応: 複数のアーキテクチャ向けのイメージを効率的に同時にビルドできます。
- Rootlessモード対応: root権限なしでビルドを実行できます。
2.2 Buildxの役割
Buildxは、このBuildKitの機能をdocker build
コマンドの使い慣れたインターフェースを通して利用可能にするためのCLI(コマンドラインインターフェース)ツールです。
簡単に言えば、Buildxは「BuildKitを使うための橋渡し役」です。
- ユーザーは
docker buildx build ...
のようにBuildxコマンドを実行します。 - Buildxは、指定されたオプションやDockerfile、コンテキストを解析し、BuildKitに対してビルドジョブを依頼します。
- BuildKitが実際のビルド処理を、その高性能な機能(並列処理、キャッシュ、マルチプラットフォーム対応など)を駆使して実行します。
- BuildKitはビルド結果をBuildxに返します。
- Buildxは受け取った結果をユーザーに提示したり、指定された出力先に保存したりします。
Buildxを利用することで、BuildKitの持つ先進的なビルド機能を、従来のdocker build
に近い感覚で簡単に使いこなせるようになります。
Docker Desktopを使っている場合、Buildxはデフォルトで有効になっており、内部的にBuildKitが使われています。コマンドラインでdocker buildx build
を実行することで、明示的にBuildKitの機能を利用できます。
3. BuildKitの基本概念:なぜ速い?なぜ効率的?
Buildxが高速で効率的なのは、バックエンドで動作するBuildKitのおかげです。ここでは、BuildKitがどのようにビルドを高速化・効率化しているのか、その基本概念を掘り下げてみましょう。
3.1 DAGベースの並列処理
BuildKitの最も重要な特徴の一つは、ビルドのステップをDAG (Directed Acyclic Graph:有向非巡回グラフ)として表現し、実行することです。
従来のdocker build
は、Dockerfileの命令を上から順に実行する「線形」な処理でした。
“`dockerfile
例:従来のビルドは直列
FROM ubuntu
RUN apt-get update -y # ステップA
RUN apt-get install -y some-package # ステップB
COPY ./app /app # ステップC
RUN make -C /app # ステップD
CMD [“/app/run”]
“`
この場合、A→B→C→D の順で実行されます。たとえCとDがAやBに直接依存していなくても、待つ必要がありました。
一方BuildKitは、Dockerfile(や他のBuildKitに対応した定義ファイル)を解析し、各ステップ間の依存関係をグラフ構造として構築します。
“`dockerfile
BuildKitは依存関係を解析
FROM ubuntu
RUN apt-get update -y # ステップA
RUN apt-get install -y some-package # ステップB (Aに依存)
COPY ./app /app # ステップC (FROMに依存)
RUN make -C /app # ステップD (B, Cに依存)
CMD [“/app/run”]
“`
この例では、BはAが完了しないと実行できませんが、CはFROMイメージが準備できればAやBと並列に実行開始できます。DはBとCの両方が完了しないと実行できません。
BuildKitは、このようなDAGを構築し、依存関係が満たされたステップから順番に、複数のステップを同時に実行します。これにより、特にDockerfileの中で独立した処理が多い場合に、ビルド時間を大幅に短縮できます。
3.2 高度なキャッシュ管理
BuildKitのもう一つの強力な機能は、洗練されたキャッシュ管理です。
- きめ細かいキャッシュキー: BuildKitは、各ビルドステップのキャッシュキーを生成する際、入力となるファイル内容や命令の詳細をより正確にハッシュ化します。これにより、Dockerfileのちょっとした変更や、
COPY
するファイルの内容の微妙な変更でも、キャッシュミスすることなく、本当に必要なステップだけを再実行するようになります。 -
マウント可能なキャッシュ (
--mount=type=cache
): これまでDockerビルドで難しかったのが、パッケージマネージャーのキャッシュ(npm, yarn, pip, aptなど)やコンパイルの中間ファイルなどを効率的にキャッシュすることでした。
例えばRUN apt-get update && apt-get install ...
というステップがある場合、apt-get update
の結果やダウンロードしたパッケージファイルは、次のステップには引き継がれず、キャッシュにも残りませんでした。別のビルドで同じパッケージをインストールしようとすると、再度ダウンロードからやり直しになっていました。
BuildKitでは、--mount=type=cache
オプションを使って、特定のディレクトリをキャッシュとして永続化できます。“`dockerfile
Syntaxとして BuildKitの機能を有効化
docker buildx build –progress=plain … で確認しやすい
syntax=docker/dockerfile:1
FROM ubuntu
RUN apt-get update -y && apt-get install -y –no-install-recommends build-essentialWORKDIR /app
COPY package.json package-lock.json ./node_modules と npm cache をキャッシュとしてマウント
RUN –mount=type=cache,target=/root/.npm \
–mount=type=cache,target=/app/node_modules \
npm ciCOPY . .
CMD [“node”, “index.js”]
“`この例では、
/root/.npm
(npmのキャッシュディレクトリ)と/app/node_modules
をキャッシュとしてマウントしています。初めてビルドする際は通常のnpm ciが実行されますが、二回目以降、package.json
やpackage-lock.json
に変更がなければ、node_modules
がキャッシュから復元され、npm ci
が非常に高速に完了します。npmのキャッシュも同様に再利用されます。この機能は、ビルド時間のかなりの部分を占めることが多い依存ライブラリのダウンロードやインストールを劇的に高速化します。
-
外部キャッシュ (
--cache-to
,--cache-from
): BuildKitは、ビルド中に生成されたキャッシュを、Dockerレジストリ、ローカルのOCIイメージ、ローカルディレクトリなど、様々な場所にエクスポート(保存)できます。そして、別のビルドでそのキャッシュをインポートして利用できます。“`bash
キャッシュをレジストリにプッシュ (例: ghcr.io/your-user/your-repo:cache)
docker buildx build . \
–cache-to type=registry,ref=ghcr.io/your-user/your-repo:cache,mode=max \
–output type=registry,name=ghcr.io/your-user/your-repo:latest,push=true別の場所でキャッシュをインポートして高速ビルド
docker buildx build . \
–cache-from type=registry,ref=ghcr.io/your-user/your-repo:cache \
–output type=registry,name=ghcr.io/your-user/your-repo:latest,push=true
“`
この機能は、CI/CD環境で非常に強力です。一度ビルドしたキャッシュを共有レジストリに保存しておけば、後続のビルドや別のエージェントでのビルドがそのキャッシュを利用でき、ビルド時間を大幅に短縮できます。
これらの高度なキャッシュ戦略により、BuildKitは不要な再ビルドを減らし、必要なビルドステップだけを効率的に実行します。
3.3 マルチプラットフォームビルドの容易化
前述の通り、BuildKitはマルチプラットフォームイメージのビルドをネイティブにサポートしています。Buildxの--platform
オプションを使うだけで、複数のアーキテクチャ向けのイメージを単一のコマンドでビルドできます。
BuildKitは内部で、各ターゲットプラットフォーム(例:linux/amd64, linux/arm64)向けにビルドステップを実行し、最終的にそれらのイメージをまとめた「マニフェストリスト」(またはインデックス)を作成します。このマニフェストリストは、docker pull
コマンドが実行されたホストのアーキテクチャに最適なイメージを自動的に選択するために使われます。
異なるアーキテクチャのバイナリを実行する必要がある場合(例:ARMホストでAMD64イメージをビルドする場合)、BuildKitはQEMUのようなエミュレーション機能と連携して、透過的にクロスアーキテクチャ実行を可能にします。このための設定は、多くの場合、binfmt_misc
カーネル機能と、それを簡単にセットアップする軽量なコンテナ(例:tonistiigi/binfmt
)で行えます。
“`bash
必要なエミュレーターをセットアップ (一度実行すればOK)
docker run –privileged –rm tonistiigi/binfmt –install all
複数のプラットフォーム向けにビルドしてプッシュ
docker buildx build . \
–platform linux/amd64,linux/arm64 \
–output type=registry,name=your-repo/your-image:latest,push=true
“`
このように、Buildxを使えば、マルチプラットフォーム対応の煩雑さが劇的に軽減されます。
3.4 その他のBuildKit機能
BuildKitは他にも多くの機能を持っています。
- Frontend: BuildKitはDockerfileだけでなく、Buildpackなど他のビルド定義形式もサポートできます。
# syntax=
ディレクティブでFrontendを指定します。 - Build Secret:
--secret
オプションを使って、ビルド中に環境変数として公開したくない秘匿情報を安全に渡せます。 - SSH Forwarding:
--ssh
オプションを使って、ビルドコンテナからホストのSSHエージェント経由でSSH接続できます。プライベートなGitリポジトリからのクローンなどに便利です。 - Output形式の多様性:
--output
オプションで、ローカルのDockerデーモン、tarファイル、ローカルディレクトリ、直接レジストリなど、様々な出力先を指定できます。 - Attestations: ビルドに関するメタデータ(例:SBOM – Software Bill of Materials, ビルドの署名)をイメージに紐付ける機能(実験的)。
BuildKitはこれらの機能を組み合わせて、Dockerビルドをよりパワフルで柔軟、そして安全なものにしています。BuildxはこれらのBuildKit機能を簡単に利用するためのインターフェースなのです。
4. Buildxのインストールとセットアップ
Docker Buildxは、比較的新しいDockerのバージョンには標準で組み込まれています。
- Docker Desktop (Windows, macOS): Docker DesktopにはBuildxが最初から含まれており、特に何もインストールする必要はありません。BuildKitもデフォルトで有効です。
- Docker Engine (Linux): 最近のDocker Engineのバージョン(例えば 19.03 以降)には、Buildx CLIプラグインが含まれていることが多いです。インストールされているDockerが比較的新しいバージョンであれば、追加のインストールは不要な場合がほとんどです。
古いバージョンのDocker Engineを使っている場合や、プラグインとしてインストールされていない場合は、手動でBuildx CLIプラグインをインストールする必要があるかもしれません。公式ドキュメントやGitHubリポジトリを参照してください。
確認方法
お使いの環境でBuildxが利用できるか確認するには、以下のコマンドを実行します。
bash
docker buildx version
Buildxのバージョン情報が表示されれば、インストールは完了しています。
github.com/docker/buildx v0.x.x ...
docker: 'buildx' is not a docker command.
のようなエラーが出る場合は、Dockerのバージョンを確認するか、Buildxプラグインの手動インストールを検討してください。
4.1 ビルダーインスタンスの理解とセットアップ
Buildxは、ビルドを実行するための環境であるビルダーインスタンスを使用します。ビルダーインスタンスは、BuildKitデーモンを実行する場所や接続方法を定義します。
Buildxを初めて使うとき、通常はデフォルトのビルダーインスタンスが自動的に作成され、それが利用されます。このデフォルトビルダーは、多くの場合はdocker
ドライバーを使用し、ホストのDockerデーモン内でBuildKitを実行します(Docker Desktopの場合)。あるいは、より高機能なdocker-container
ドライバーを使用し、BuildKitを独立したコンテナとして実行する場合もあります。
ビルダーインスタンスの確認
現在利用可能なビルダーインスタンスを確認するには、以下のコマンドを実行します。
bash
docker buildx ls
実行例:
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default * docker
default default running v0.11.6+b8542e50b https://github.com/moby/buildkit linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
NAME
: ビルダーインスタンスの名前。default
が現在のデフォルトインスタンスであることを示します。DRIVER
: BuildKitデーモンを実行する方法(docker
,docker-container
,kubernetes
,remote
など)。ENDPOINT
: BuildKitデーモンへの接続先。STATUS
: ビルダーの状態(running
,inactive
など)。BUILDKIT
: 使用されているBuildKitのバージョン。PLATFORMS
: このビルダーインスタンスがサポートするプラットフォーム。
*
が付いているビルダーインスタンスが、現在アクティブに使用されるインスタンスです。
新しいビルダーインスタンスの作成 (必要に応じて)
ほとんどの場合、デフォルトのビルダーインスタンスで十分ですが、特定の要件(例:リモートのDockerデーモンでビルドしたい、Kubernetesクラスター上でBuildKitを実行したい)がある場合は、新しいビルダーインスタンスを作成します。
例えば、docker-container
ドライバーを使用する新しいビルダーを作成する場合:
“`bash
新しいビルダーインスタンスを作成
docker buildx create –name mybuilder –driver docker-container
作成したビルダーを起動
docker buildx inspect mybuilder –bootstrap
そのビルダーを使用するように切り替える
docker buildx use mybuilder
確認
docker buildx ls
“`
docker-container
ドライバーは、BuildKitを独立したコンテナとして実行するため、ホストのDockerデーモンに依存しない、よりクリーンでステートレスなビルド環境を提供できます。BuildKitの最新機能をより確実に利用したい場合や、CI環境などでの利用に適しています。
--bootstrap
オプションは、ビルダーインスタンスを初めて使用する際に、関連するBuildKitコンテナなどを起動するために必要です。docker buildx build
実行時にも自動的にブートストラップされますが、事前にinspect --bootstrap
で起動しておくことも可能です。
ビルダーインスタンスの切り替え
複数のビルダーインスタンスがある場合、docker buildx use
コマンドで、どのインスタンスを使うか切り替えられます。
bash
docker buildx use default # デフォルトに戻す
docker buildx use mybuilder # mybuilderに切り替える
ビルダーインスタンスの削除
不要になったビルダーインスタンスは削除できます。
bash
docker buildx rm mybuilder
ビルダーインスタンスの管理は、Buildxの高度な機能を利用する上で重要になりますが、まずはデフォルトのビルダーでBuildxの基本的な使い方に慣れることから始めましょう。
5. Buildxの基本的な使い方
Buildxの基本的な使い方は、従来のdocker build
と非常によく似ています。コマンド名の先頭にbuildx
が付くだけです。
“`bash
従来のビルド
docker build -t myimage:latest .
Buildxを使ったビルド
docker buildx build -t myimage:latest .
“`
これだけでは、特に見た目の変化はないかもしれません。しかし、内部ではBuildKitが使用され、前述の高速化や効率化の恩恵を受けている可能性があります(特に並列処理やキャッシュの改善)。
5.1 シンプルなビルド例
簡単なDockerfileを用意して、Buildxでビルドしてみましょう。
“`dockerfile
Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y –no-install-recommends fortune-mod cowsay
CMD [“/usr/games/cowsay”, “Moo! I’m a cow!”]
“`
このDockerfileをDockerfile
という名前で保存し、同じディレクトリで以下のコマンドを実行します。
bash
docker buildx build -t my-fortune-cow:latest .
--tag
(または -t
) オプションは従来のdocker build
と同じく、ビルドしたイメージに名前とタグを付けます。.
はビルドコンテキストのパスです。
ビルドの進捗表示も、従来のコマンドと少し異なる場合があります。BuildKitはより詳細な進捗情報を提供できます。デフォルトではシンプルな表示ですが、--progress=plain
オプションを付けると、各ステップの詳細なログを確認できます。
bash
docker buildx build -t my-fortune-cow:latest . --progress=plain
ビルドが完了すると、デフォルトではローカルのDockerデーモンにイメージが保存されます。これは、docker buildx build
のデフォルトの出力形式がtype=image
であるためです。
5.2 --platform
オプションによるシングルプラットフォームビルド
特定のプラットフォーム向けのイメージをビルドしたい場合、--platform
オプションを使用します。
“`bash
AMD64 Linux 向けのイメージをビルド
docker buildx build –platform linux/amd64 -t myimage:amd64 .
ARM64 Linux 向けのイメージをビルド
docker buildx build –platform linux/arm64 -t myimage:arm64 .
“`
--platform
に指定できる値は、docker buildx ls
コマンドの出力のPLATFORMS
列に表示されているものです。一般的なものとしては linux/amd64
, linux/arm64
, linux/arm/v7
, linux/386
などがあります。ホストOSのアーキテクチャに関わらず、指定したアーキテクチャ向けのイメージをビルドしようとします。必要に応じてBuildKitがQEMUエミュレーションを利用します。
5.3 --output
オプションの基本:プッシュとローカル保存
Buildxの強力な機能の一つが、ビルド結果の出力先を細かく制御できる--output
オプションです。デフォルトはtype=image
で、従来のdocker build
のようにローカルのDockerデーモンにイメージを保存します。
-
レジストリへのプッシュ: ビルド完了後にすぐにレジストリにイメージをプッシュしたい場合に使います。これは特にCI/CDで便利です。
bash
docker buildx build . \
-t your-registry/your-image:latest \
--output type=registry
または、より簡潔に--push
フラグを使っても同じことができます (type=registry
がデフォルトで使われます)。bash
docker buildx build . \
-t your-registry/your-image:latest \
--push -
tarファイルとしての出力: ビルドしたイメージをローカルファイルとして保存したい場合に便利です。
bash
docker buildx build . \
--output type=tar,dest=/tmp/myimage.tar
このコマンドは、ビルド結果を/tmp/myimage.tar
というtarファイルとして保存します。このファイルはdocker load -i /tmp/myimage.tar
で別のDocker環境にロードできます。
--output
オプションは非常に柔軟で、type=
で出力形式を指定し、,
区切りで追加のオプション(例:dest=
, name=
, push=
)を指定します。詳細は後述します。
これらの基本的な使い方をマスターするだけでも、Buildx(BuildKit)の内部的な最適化の恩恵を受けることができます。次のセクションでは、Buildxの主要なメリットである高速化と効率化の仕組みをさらに深掘りします。
6. 高速化の秘密:BuildKitの並列処理とキャッシュ戦略の詳細
Buildxを使ったビルドがなぜ速くなるのか、BuildKitの心臓部である並列処理と高度なキャッシュの仕組みを、具体的な例を交えながら見ていきましょう。
6.1 並列処理:DAGによる魔法
従来のDockerビルドは、Dockerfileの各行を上から順番に実行していました。これはまるで、料理のレシピを最初から最後まで忠実に、一度に一つの工程だけを行うようなものです。
BuildKitは、Dockerfileを解析して「このステップはあのステップが終わったらできる」「このステップは他のステップに影響しないから、並行してできる」といった依存関係を理解します。そして、可能な限り多くのステップを同時に実行します。
並列処理の例:
以下のDockerfileを考えてみましょう。
“`dockerfile
syntax=docker/dockerfile:1
FROM ubuntu:latest
ステップ1: パッケージリストの更新
RUN apt-get update -y
ステップ2a: 必要なツールのインストール (ビルドツール)
RUN apt-get install -y –no-install-recommends make gcc
ステップ2b: 別途必要なツールのインストール (ランタイムツール)
RUN apt-get install -y –no-install-recommends fortune-mod
ステップ3: アプリケーションソースコードのコピー
COPY ./app /app
ステップ4: アプリケーションのビルド (makeを使う) – ステップ2aと3に依存
RUN make -C /app
ステップ5: fortune-modの確認 – ステップ2bに依存
RUN fortune
“`
従来のビルドでは、ステップ1から5までが順番に実行されます。
1 → 2a → 2b → 3 → 4 → 5
BuildKitでは、以下のように依存関係を解析します。
- ステップ1 (
apt-get update
) は最初に行う必要がある。 - ステップ2a (
install make gcc
) はステップ1に依存。 - ステップ2b (
install fortune-mod
) はステップ1に依存。 - ステップ3 (
COPY
) はFROMイメージがあれば実行可能。 - ステップ4 (
make
) はステップ2aとステップ3が完了しないと実行できない。 - ステップ5 (
fortune
) はステップ2bが完了しないと実行できない。
BuildKitはこれらの関係を見て、以下のような並列実行のプランを立てる可能性があります(実際のプランはBuildKitのスケジューリングによりますが、概念として)。
- ステップ1 (
apt-get update
) を実行。 - ステップ1が完了したら、ステップ2a (
install make gcc
) とステップ2b (install fortune-mod
) を同時に実行開始。 - ステップ1が完了したら、ステップ3 (
COPY
) も並列に実行開始。 - ステップ2aとステップ3が完了したら、ステップ4 (
make
) を実行開始。 - ステップ2bが完了したら、ステップ5 (
fortune
) を実行開始。 - 全てのステップが完了したら、最終イメージを生成。
この例では、ステップ2a, 2b, 3が並列に実行される可能性があるため、従来の直列実行に比べてビルド時間が短縮されることが期待できます。
--progress=plain
オプションを使ってBuildxビルドのログを見ると、複数のステップが同時にrunning
やdownloading
状態になっていることが確認できます。
6.2 高度なキャッシュ戦略:キャッシュの賢い使い方
BuildKitのキャッシュは、単に「前のステップと同じ命令なら再利用」というだけでなく、より賢く、より柔軟に利用できます。
6.2.1 より賢いキャッシュキー
BuildKitは、各ステップのキャッシュキーを生成する際に、命令そのものだけでなく、その入力(例:COPY
のコピー元ファイルのコンテンツハッシュ、RUN
コマンドで参照されるファイルの内容など)をより正確に考慮します。これにより、不必要にキャッシュが外れるのを防ぎつつ、変更があった場合は確実に再ビルドされるようになります。
6.2.2 マウント可能なキャッシュ (--mount=type=cache
) の詳細
これはBuildKitのキャッシュ機能の中でも特に強力で、ビルドのパフォーマンスを劇的に改善する可能性があります。特定のディレクトリを「キャッシュボリューム」のように扱い、ビルドステップを跨いで状態を維持できます。
構文: --mount=type=cache,target=<キャッシュしたいディレクトリの絶対パス>[,option=value...]
よくある利用例:
-
Node.js (npm/yarn):
node_modules
とnpm/yarnのグローバルキャッシュディレクトリをキャッシュ。“`dockerfile
syntax=docker/dockerfile:1
FROM node:lts
WORKDIR /app
COPY package.json package-lock.json ./node_modulesディレクトリとnpmのグローバルキャッシュをキャッシュ
RUN –mount=type=cache,target=/app/node_modules,id=node_modules \
–mount=type=cache,target=/root/.npm,id=npm_cache \
npm ciCOPY . .
CMD [“node”, “index.js”]
``
id=`オプションは、複数のキャッシュマウントを使う場合に、それぞれを区別するために付けると良いでしょう。 -
Python (pip): pipのキャッシュディレクトリをキャッシュ。
“`dockerfile
syntax=docker/dockerfile:1
FROM python:3.9
WORKDIR /app
COPY requirements.txt ./pipキャッシュをキャッシュ
RUN –mount=type=cache,target=/root/.cache/pip \
pip install –no-cache-dir -r requirements.txtCOPY . .
CMD [“python”, “app.py”]
``
–no-cache-dirはpip自身のファイルキャッシュを無効にしますが、
–mount=type=cache`で指定したディレクトリへのキャッシュは有効になります。 -
Maven (Java): Mavenのローカルリポジトリをキャッシュ。
“`dockerfile
syntax=docker/dockerfile:1
FROM maven:latest
WORKDIR /app
COPY pom.xml ./Mavenローカルリポジトリをキャッシュ
RUN –mount=type=cache,target=/root/.m2 \
mvn dependency:go-offline -BCOPY . .
RUN mvn package
CMD [“java”, “-jar”, “target/my-app.jar”]
“` -
Go: Goモジュールキャッシュとビルドキャッシュをキャッシュ。
“`dockerfile
syntax=docker/dockerfile:1
FROM golang:latest
WORKDIR /app
COPY go.mod go.sum ./Goモジュールキャッシュとビルドキャッシュをキャッシュ
RUN –mount=type=cache,target=/go/pkg/mod \
–mount=type=cache,target=/root/.cache/go-build \
go mod downloadCOPY . .
RUN –mount=type=cache,target=/root/.cache/go-build \
go build -o myappCMD [“./myapp”]
“`
--mount=type=cache
を使う際の注意点:
* これはBuildKit固有の機能です。Dockerfileの先頭に# syntax=docker/dockerfile:1
のようなディレクティブを書いておくことが推奨されます。これにより、BuildKitをサポートしていない環境でビルドしようとした場合にエラーになるなど、互換性の問題を防ぐのに役立ちます。
* キャッシュディレクトリのパスは、ビルドコンテナ内のパスです。適切なパーミッションでマウントされているか確認してください。
* キャッシュは、ビルドの実行者(BuildKitデーモン)によって管理されます。デフォルトでは、特定のビルダーインスタンスに関連付けられたキャッシュとして保存されます。
この機能は、依存関係の解決やコンパイルなど、時間がかかりやすく、かつ同じ入力に対しては結果が変わらないステップに対して非常に効果的です。
6.2.3 外部キャッシュ (--cache-to
, --cache-from
)
ビルドキャッシュを外部に保存・復元する機能は、特にCI/CD環境で真価を発揮します。ビルドエージェントが使い捨てであったり、複数のエージェントでビルドが実行されたりする場合でも、共通のキャッシュを利用できるようになります。
構文:
--cache-to type=<タイプ>[,option=value...]
--cache-from type=<タイプ>[,option=value...]
タイプ例:
* registry
: DockerレジストリにキャッシュをOCIイメージとして保存/読み込み。
* local
: ローカルファイルシステムにキャッシュを保存/読み込み。
* gha
: GitHub Actionsのキャッシュ機能を利用(Buildx actionなど)。
レジストリキャッシュの例:
“`bash
CI環境などで、ビルドと同時にキャッシュをレジストリにプッシュ
docker buildx build . \
–platform linux/amd64 \
-t your-repo/your-image:latest \
–cache-to type=registry,ref=your-repo/your-image:buildcache,mode=max \
–push # イメージ本体もプッシュ
別のCIジョブやエージェントで、レジストリからキャッシュを読み込んでビルド
docker buildx build . \
–platform linux/amd64 \
-t your-repo/your-image:latest \
–cache-from type=registry,ref=your-repo/your-image:buildcache \
–push # イメージ本体をプッシュ
“`
ref=
: キャッシュイメージの名前とタグを指定します。イメージ本体とは別のタグ(例::buildcache
)を使うのが一般的です。mode=max
: キャッシュのエクスポートモードを指定します。max
は可能な限り多くのキャッシュデータをエクスポートしようとします。min
は最終イメージに必要なデータのみをエクスポートします(キャッシュヒット率が下がる可能性があります)。max
が推奨されることが多いです。
この仕組みを利用するには、レジストリへの認証が必要です(docker login
など)。
ローカルキャッシュの例:
“`bash
キャッシュをローカルディレクトリに保存
docker buildx build . \
–cache-to type=local,dest=/tmp/buildx-cache
別のビルドで、ローカルディレクトリからキャッシュを読み込み
docker buildx build . \
–cache-from type=local,src=/tmp/buildx-cache
“`
これは、ローカルマシンで頻繁にビルドするが、Dockerデーモンのキャッシュが不安定な場合や、特定のプロジェクトのキャッシュだけを管理したい場合などに役立つ可能性があります。
これらのキャッシュ戦略を適切に組み合わせることで、特に依存関係の多いアプリケーションや複雑なビルドプロセスを持つプロジェクトにおいて、ビルド時間を劇的に短縮できます。
7. 効率化の秘密:マルチプラットフォームビルド
Docker Buildxのもう一つの大きな利点は、マルチプラットフォームイメージのビルドが非常に簡単になることです。これは、アプリケーションを様々なデバイス(例:サーバー、ラップトップ、Raspberry Pi、クラウドインスタンスなど)で実行したい場合に不可欠な機能です。
7.1 従来の課題の再確認
前述の通り、従来のdocker build
は基本的にホストのアーキテクチャ向けのイメージしかビルドできませんでした。例えば、Intel Mac (x86-64) でビルドしたイメージは、そのままではRaspberry Pi (ARM32v7) や新しいARM Mac (ARM64) でネイティブなパフォーマンスで実行することはできません。
マルチプラットフォーム対応のためには、以下のような手間が必要でした。
- 異なるアーキテクチャのハードウェアを用意し、それぞれのマシンでビルドする。
- Docker公式が提供する
buildpack-deps
などのマルチアーキテクチャ対応ベースイメージを利用し、Dockerデーモンの実験的機能やqemu
などのエミュレーターを手動で設定してクロスビルドを試みる。 - Dockerfileのステップ内で、ターゲットアーキテクチャに応じて異なるコマンドを実行するような複雑な記述を行う。
これらの方法は、設定が複雑でエラーが発生しやすく、メンテナンスも大変でした。
7.2 Buildxによる解決
Buildxは、--platform
オプションに複数のプラットフォームを指定するだけで、この問題を鮮やかに解決します。
bash
docker buildx build . \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
-t your-repo/your-multiarch-image:latest \
--push
この単一のコマンドで、指定された3つの異なるアーキテクチャ向けのイメージがビルドされ、最終的にそれらをまとめたマニフェストリストが作成され、指定されたタグ(your-repo/your-multiarch-image:latest
)に関連付けられてレジストリにプッシュされます(--push
があるため)。
このマニフェストリストは、異なるアーキテクチャの環境からdocker pull your-repo/your-multiarch-image:latest
を実行した際に、Dockerクライアントが自動的にその環境に最適なアーキテクチャのイメージを選択してダウンロードできるようにするメタデータです。
7.3 QEMUエミュレーションの活用
Buildx(BuildKit)は、指定されたプラットフォームでビルドを行う際に、必要に応じてQEMUのようなエミュレーターを自動的に利用します。例えば、AMD64のLinuxマシンで--platform linux/arm64
を指定してビルドする場合、BuildKitはARM64のバイナリを実行するステップ(RUN
命令など)でQEMUを利用してそのコマンドを実行します。
このエミュレーション機能を利用するためには、ホストOSに必要なバイナリフォーマットを登録しておく必要があります。これは、通常、binfmt_misc
カーネル機能と、それを簡単にセットアップする軽量なコンテナイメージ(例: tonistiigi/binfmt
)を使って行います。
“`bash
必要なプラットフォーム向けのエミュレーターをインストール (通常、各ホストで一度だけ実行)
–privileged が必要なので注意。信頼できるイメージのみ実行すること。
docker run –privileged –rm tonistiigi/binfmt –install all
“`
このコマンドは、システムの/proc/sys/fs/binfmt_misc
に、様々なアーキテクチャのバイナリを検知したらQEMUを使って実行するように設定を登録します。これにより、BuildKitは異なるアーキテクチャ向けのRUN
命令などを透過的に実行できるようになります。
多くのCI環境では、この設定が既にされているか、あるいはCIパイプラインの初期ステップで実行されるようになっています。Docker Desktopを使っている場合も、通常この設定は既に行われています。
7.4 マルチステージビルドと組み合わせる
マルチプラットフォームビルドは、マルチステージビルドとも組み合わせて利用できます。例えば、Goアプリケーションのように、ビルドステージで特定のアーキテクチャ向けのバイナリをコンパイルし、それを軽量な実行ステージにコピーする場合、BuildKitは各ターゲットプラットフォーム向けにビルドステージと実行ステージの両方をビルドします。
“`dockerfile
syntax=docker/dockerfile:1
ビルドステージ
FROM golang:latest AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN –mount=type=cache,target=/go/pkg/mod \
–mount=type=cache,target=/root/.cache/go-build \
go mod download
COPY . .
ビルドアーティファクトをコンパイル(ターゲットアーキテクチャによってコンパイル結果が変わる)
ARG TARGETOS TARGETARCH
RUN –mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o myapp .
実行ステージ
FROM alpine:latest
WORKDIR /app
COPY –from=builder /app/myapp . # ビルドステージからアーティファクトをコピー
CMD [“./myapp”]
“`
このDockerfileを--platform linux/amd64,linux/arm64
でビルドすると、BuildKitは以下を行います。
linux/amd64
向けのビルドステージを実行します。その際、TARGETOS=linux
,TARGETARCH=amd64
のビルド引数が自動的に渡されます。go build
コマンドはAMD64向けのバイナリをコンパイルします。linux/arm64
向けのビルドステージを実行します。その際、TARGETOS=linux
,TARGETARCH=arm64
のビルド引数が自動的に渡されます。go build
コマンドはARM64向けのバイナリをコンパイルします。linux/amd64
向けの実行ステージを作成し、AMD64ビルドステージからコンパイルされたAMD64バイナリをコピーします。linux/arm64
向けの実行ステージを作成し、ARM64ビルドステージからコンパイルされたARM64バイナリをコピーします。- 最終的に、AMD64イメージとARM64イメージを含むマニフェストリストを生成します。
このように、Buildxはマルチステージビルドにおけるクロスコンパイルも透過的にサポートします。ARG TARGETOS TARGETARCH
をDockerfileに追加することで、ビルド中のスクリプトやコマンド内でターゲットOS/アーキテクチャを参照できるようになり、より柔軟なマルチプラットフォーム対応が可能になります。
Buildxによるマルチプラットフォームビルドは、異なるアーキテクチャ対応の複雑さを解消し、単一のコマンドで様々な環境で動作するイメージを効率的に提供することを可能にします。
8. ビルダーインスタンスの管理と活用
Buildxのビルドは、すべてビルダーインスタンスを介して行われます。ビルダーインスタンスは、BuildKitデーモンを実行する環境(ローカルのDockerデーモン、Dockerコンテナ、リモートホスト、Kubernetesクラスターなど)と、それに接続するための設定をカプセル化したものです。
8.1 ビルダーインスタンスの種類 (ドライバー)
Buildxはいくつかのドライバーをサポートしており、それぞれ異なる実行環境を提供します。
docker
: これは従来のDockerデーモンに組み込まれているBuildKitを利用します。Docker Desktopのデフォルトや、BuildKitが有効化されたLinuxのDocker Engineで使われます。手軽に使えますが、BuildKitの機能の一部に制限がある場合があります(特にネットワークやボリューム関連)。docker-container
: BuildKitデーモンを、別の特権コンテナとして実行します。これが推奨されるドライバーであり、BuildKitの最新機能や全機能を最も安定して利用できます。ローカル環境での開発、CI/CD環境での利用に適しています。ステートレスな運用が可能で、ビルド間の分離性が高いです。kubernetes
: Kubernetesクラスター上でBuildKitを実行します。大規模なチームやCI/CD環境で、ビルド環境をスケーラブルに提供したい場合に利用できます。remote
: リモートホスト上のBuildKitデーモンに接続してビルドを実行します。
8.2 ビルダーインスタンスのライフサイクル
ビルダーインスタンスは以下のコマンドで管理します。
docker buildx ls
: 既存のビルダーインスタンスを一覧表示します。docker buildx create
: 新しいビルダーインスタンスを作成します。
bash
# docker-container ドライバーで新しいビルダーを作成
docker buildx create --name my-container-builder --driver docker-containerdocker buildx use
: 現在使用するビルダーインスタンスを切り替えます。
bash
docker buildx use my-container-builderdocker buildx inspect
: ビルダーインスタンスの詳細情報(ドライバー、エンドポイント、サポートプラットフォーム、状態など)を表示します。--bootstrap
オプションを付けると、必要に応じてBuildKitデーモンを起動します。
bash
# my-container-builder を検査し、起動していなければ起動
docker buildx inspect my-container-builder --bootstrap
Buildxビルドコマンドを実行した際も、自動的に使用するビルダーがブートストラップされます。docker buildx stop
: 起動中のビルダーインスタンスを停止します(docker-container
ドライバーの場合など)。
bash
docker buildx stop my-container-builderdocker buildx rm
: ビルダーインスタンスを削除します。関連するコンテナなども削除されます。
bash
docker buildx rm my-container-builder
8.3 docker-container
ドライバーの活用
多くの場合、デフォルトのdocker
ドライバーでBuildxの基本的な恩恵は受けられますが、BuildKitの機能を最大限に活用するにはdocker-container
ドライバーのビルダーを作成して使用するのが推奨されます。
docker-container
ビルダーの利点:
- BuildKitの全機能を利用可能:
--mount=type=cache
や多様な--output
形式など、BuildKitの最新かつ全ての機能にアクセスできます。 - 分離性: BuildKitがホストのDockerデーモンとは別のコンテナ内で実行されるため、ホストのDockerデーモンへの影響を最小限に抑えられます。
- ステートレス: ビルダーコンテナは停止・削除が容易で、クリーンな状態で再起動できます。CI環境などでの信頼性向上に繋がります。
- 柔軟な設定: BuildKitデーモンの設定を細かく調整できます。
docker-container
ビルダーの設定例:
CI環境のセットアップスクリプトなどで、最初に以下を実行することが多いです。
“`bash
BuildKitをコンテナとして実行するビルダーを作成 (存在しなければ)
docker buildx create –name mybuilder –driver docker-container –use
ビルダーがサポートするプラットフォームを確認し、必要ならブートストラップ
docker buildx inspect –bootstrap
“`
この設定により、その後のdocker buildx build
コマンドは作成したmybuilder
インスタンス(BuildKitコンテナ)を使って実行されるようになります。
ビルダーインスタンスは、Buildxの柔軟性とパワーの基盤となります。最初はデフォルトビルダーで十分ですが、より高度な機能(特にマルチプラットフォームや外部キャッシュ)を利用する際には、docker-container
ドライバーのビルダーを積極的に活用することを検討しましょう。
9. その他の便利な機能
Buildx/BuildKitは、ビルドプロセスをよりセキュアに、より柔軟にするための様々な追加機能を提供します。
9.1 ビルド secrets の利用 (--secret
)
ビルド中に、外部サービスへのAPIキー、プライベートリポジトリのパスワードなどの秘匿情報が必要になることがあります。これらをDockerfileに直接書いたり、--build-arg
で渡したりするのはセキュリティ上好ましくありません(レイヤーに情報が残る可能性があるため)。
BuildKitは--secret
オプションを使って、安全にビルドプロセスに秘匿情報を渡す機能を提供します。
まず、Dockerfile側でsecretを利用することを宣言します。
“`dockerfile
syntax=docker/dockerfile:1
FROM alpine:latest
secretをID ‘mysecret’ としてマウントすることを宣言
マウントポイントはデフォルトで /run/secrets/
RUN –mount=type=secret,id=mysecret \
apk add –no-cache curl \
# マウントされたsecretファイルを読み取って利用
&& curl -H “Authorization: token $(cat /run/secrets/mysecret)” https://api.github.com/…
“`
次に、Buildxコマンドでsecretファイルや環境変数を渡します。
- ファイルから渡す:
bash
# secret_file.txt にAPIキーなどが書かれているとする
docker buildx build . \
--secret id=mysecret,src=secret_file.txt - 標準入力から渡す:
bash
# 環境変数からパイプで渡す例 (注意: 履歴に残らないように注意)
cat secret_file.txt | docker buildx build . \
--secret id=mysecret,src=/dev/stdin
# あるいは、環境変数自体を渡す
API_TOKEN="your_api_key" docker buildx build . \
--secret id=mysecret,env=API_TOKEN
src=/dev/stdin
は標準入力をsecretとして読み込む指定です。env=ENV_VAR_NAME
は指定した環境変数の値をsecretとして渡します。
BuildKitは、これらのsecret情報をビルドコンテナ内の指定されたマウントポイントに一時的に公開しますが、ビルドが完了するとその情報は破棄され、最終的なイメージレイヤーには含まれません。これにより、秘匿情報を安全に扱うことができます。
9.2 SSH エージェント転送 (--ssh
)
ビルド中に、プライベートなGitリポジトリをクローンしたり、SSH経由でリソースにアクセスしたりする必要がある場合があります。これにはSSHキーが必要ですが、DockerfileにSSHキーを埋め込むのは非常に危険です。
BuildKitは--ssh
オプションを使って、ビルドコンテナからホストのSSHエージェントを利用できるようにします。
Dockerfile側でSSHマウントを宣言します。
“`dockerfile
syntax=docker/dockerfile:1
FROM alpine:latest
RUN apk add –no-cache git openssh-client
SSHマウントを宣言 (デフォルトIDは default)
RUN –mount=type=ssh \
git clone [email protected]:myorg/private-repo.git /app/private
“`
次に、BuildxコマンドでSSH転送を有効にします。
“`bash
ホストのSSHエージェントを利用してビルド
docker buildx build . –ssh default
“`
これで、ビルド中のRUN
命令からSSHエージェントが利用可能になり、ホストに登録されているSSHキーを使ってプライベートリポジトリにアクセスできます。これもsecretと同様、SSHキー自体がイメージレイヤーに含まれることはありません。
9.3 多様な出力形式 (--output
) の詳細
--output
オプションはBuildxの柔軟性を高める重要な機能です。前述のtype=image
, type=tar
, type=registry
に加えて、いくつかの便利なタイプがあります。
-
type=local
: ビルド結果を、イメージとしてではなく、指定したローカルディレクトリにファイルとして出力します。Dockerfileで生成した特定のファイル(例:コンパイルされたバイナリ、設定ファイル、レポートなど)だけを取り出したい場合に便利です。“`bash
ビルド結果を作業ディレクトリの ‘output’ サブディレクトリに出力
docker buildx build . –output type=local,dest=./output
``
.はビルドコンテキストを指しますが、
dest=./output`はホスト側のローカルファイルシステム上のパスを指します。 -
type=cacheonly
: イメージ本体は生成せず、ビルド中に得られたキャッシュデータのみをエクスポートします。これは、キャッシュを更新するだけのビルドパイプラインなどに使えます。“`bash
ビルドは実行し、得られたキャッシュだけをレジストリにプッシュ
docker buildx build . \
–cache-to type=registry,ref=your-repo/your-image:buildcache,mode=max \
–output type=cacheonly
“`
--output
オプションでは、カンマ区切りで複数のオプションを指定できます。
name=
: 出力するイメージ名/タグを指定します。type=image
やtype=registry
で使います。複数の名前を指定することも可能です(例:name=image:latest,image:v1.0
)。push=true/false
:type=registry
の場合、ビルド完了後にイメージをプッシュするかどうかを指定します。--push
フラグは--output type=registry,push=true
のショートカットです。dest=
:type=tar
やtype=local
の場合、出力先のパスを指定します。mode=
:type=cacheonly
やtype=registry
(キャッシュエクスポート時) でキャッシュのエクスポートモードを指定します (max
またはmin
)。oci=true/false
:type=tar
やtype=local
、type=registry
の場合、OCI形式で出力するかDocker形式で出力するかを指定します。デフォルトはドライバに依存しますが、明示的に指定できます。
--output
オプションを組み合わせることで、Buildxビルドの成果物を非常に柔軟に制御できます。例えば、マルチプラットフォームイメージをビルドしてプッシュしつつ、ビルドキャッシュも同時にプッシュするといったことが、単一のdocker buildx build
コマンドで実現可能です。
bash
docker buildx build . \
--platform linux/amd64,linux/arm64 \
-t your-repo/your-image:latest \
--cache-to type=registry,ref=your-repo/your-image:buildcache,mode=max \
--output type=registry,push=true
このコマンドは、まず指定されたプラットフォーム向けのイメージをビルドし、ビルド中に生成されたキャッシュをyour-repo/your-image:buildcache
としてレジストリにプッシュします。そして、ビルドされたマルチプラットフォームイメージ本体をyour-repo/your-image:latest
としてレジストリにプッシュします。
10. 実践的なシナリオ:CI/CDでのBuildx活用
Buildxの真価は、CI/CDパイプラインのような自動化されたビルド環境で最大限に発揮されます。高速化、効率化、マルチプラットフォーム対応といったBuildxのメリットは、CI/CDの実行時間を短縮し、パイプラインの信頼性を向上させ、様々な環境へのデプロイを容易にします。
10.1 CI/CDでのBuildx導入ステップ
CI/CDパイプラインでBuildxを導入する一般的なステップは以下のようになります。
- Buildx CLIのインストール/有効化: CIエージェント/ランナーに必要なDockerバージョンがインストールされており、Buildxが利用可能であることを確認します。多くのマネージドCIサービス(GitHub Actions, GitLab CI, CircleCIなど)では、Docker EngineとともにBuildxも利用できるようになっています。
- ビルダーインスタンスのセットアップ: BuildKitの機能をフルに活用するため、
docker-container
ドライバーを使ったビルダーインスタンスを作成して使用するのが推奨されます。多くのCI環境向けのBuildx Action/Orb/Extensionは、このセットアップを自動的に行ってくれます。
“`yaml
# GitHub Actions の例 (docker/setup-buildx-action を使用)- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
“`
これにより、ジョブ内でBuildxコマンドが利用できるようになり、BuildKitコンテナがバックエンドとしてセットアップされます。
- name: Set up Docker Buildx
-
Dockerレジストリへのログイン: ビルドしたイメージをプッシュしたり、レジストリキャッシュを利用したりするために、CI環境からターゲットとなるDockerレジストリへの認証を行います。
“`yaml
# GitHub Actions の例 (docker/login-action を使用)- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
または GHCR (GitHub Container Registry)
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
“` - Buildx ビルドコマンドの実行:
docker buildx build
コマンドを実行します。 - マルチプラットフォームビルド:
--platform
オプションでターゲットプラットフォームを指定します。 - レジストリへのプッシュ:
--push
オプション(または--output type=registry,push=true
)でビルド完了後にイメージをプッシュします。 - キャッシュの活用:
--cache-from
で既存のキャッシュを読み込み、--cache-to
で新しいキャッシュを保存します。レジストリキャッシュがCI/CDでは一般的です。
“`yaml
GitHub Actions での Buildx ビルド例
- name: Build and Push Docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/${{ github.repository }}:latest
cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache
cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:buildcache,mode=max
``
docker/build-push-action`という公式アクションを利用しています。これは内部でBuildxコマンドを実行しており、キャッシュやマルチプラットフォームプッシュを簡単に設定できます。
このGitHub Actionsの例では、
- name: Log in to Docker Hub
10.2 CI/CDにおけるBuildxのメリット
- ビルド時間の短縮:
- BuildKitの並列処理により、ビルドステップ全体が高速化されます。
--mount=type=cache
と外部キャッシュ (--cache-to
/--cache-from
) により、依存ライブラリのダウンロードやコンパイル済みの成果物を再利用でき、特に変更が少ない場合のビルドが大幅に高速化されます。CIの実行時間はコストに直結するため、これは大きなメリットです。
- マルチプラットフォーム対応の簡素化: 単一のCIジョブで複数のアーキテクチャ向けのイメージをビルドし、マニフェストリストとしてまとめてプッシュできるため、パイプラインの複雑性が軽減されます。これにより、異なる環境へのデプロイ戦略がシンプルになります。
- パイプラインの信頼性向上:
docker-container
ビルダーはステートレスで、ビルド間の分離性が高いため、CIエージェントの状態に依存しにくく、より信頼性の高いビルドが実現できます。ビルドキャッシュも外部で管理されるため、エージェントが入れ替わってもキャッシュを利用できます。 - セキュリティ:
--secret
や--ssh
オプションにより、APIキーやSSHキーなどの秘匿情報を安全にビルドプロセスに渡せます。 - 多様な出力: ビルド結果を直接レジストリにプッシュしたり、別のステージで利用するためにファイルとして出力したりと、パイプラインの設計に合わせて柔軟な出力が可能です。
CI/CDパイプラインでBuildxを導入することは、Dockerビルドのモダンなベストプラクティスと言えます。多くのCIサービスがBuildxとの連携をサポートしているため、比較的容易に導入を進めることができます。
11. トラブルシューティングとよくある質問
Buildxを利用する上で遭遇する可能性のある問題や疑問点について説明します。
docker: 'buildx' is not a docker command.
と表示される- お使いのDockerのバージョンが古い可能性があります。BuildxはDocker Engine 19.03 以降、またはDocker Desktopに含まれています。Dockerを最新版にアップデートしてみてください。
- Linux環境の場合、BuildxがCLIプラグインとして正しくインストールされていない可能性があります。Dockerのインストール方法やBuildxの公式インストールガイドを確認してください。
docker buildx ls
を実行しても何も表示されない、あるいはdefault
ビルダーがない- Buildxがインストールされていても、まだ一度もビルダーインスタンスが作成されていない可能性があります。
docker buildx create --name mybuilder --use
のようにコマンドを実行して、新しいビルダーを作成し、使用するように設定してみてください。
- Buildxがインストールされていても、まだ一度もビルダーインスタンスが作成されていない可能性があります。
- ビルダーインスタンスが
inactive
またはerror
状態になるdocker-container
ドライバーを使用している場合、BuildKitコンテナが停止しているか、起動に失敗している可能性があります。docker buildx inspect --bootstrap
コマンドで起動を試み、エラーメッセージを確認してください。- 権限の問題かもしれません。特にLinuxで
docker-container
ドライバーや--privileged
が必要なコマンド(tonistiigi/binfmt
など)を実行する場合、ユーザーがdocker
グループに所属しているか、sudo
が必要ないか確認してください。 - デフォルトの
docker
ドライバーの場合、ホストのDockerデーモンに問題がある可能性があります。docker info
やデーモンログを確認してください。
- マルチプラットフォームビルドが遅い、または
exec user process caused: exec format error
のようなエラーが出る- これは、異なるアーキテクチャのバイナリを実行しようとして失敗している典型的なエラーです。QEMUエミュレーションが正しく設定されていない可能性が高いです。
docker run --privileged --rm tonistiigi/binfmt --install all
コマンドを実行して、必要なエミュレーターがホストOSに登録されているか確認してください。このコマンドは、ホストOSのbinfmt_misc
設定を更新するため、多くの場合--privileged
権限が必要です。- Docker Desktopや一部のCI環境では自動的に設定されますが、セルフホストのDocker Engineなどでは手動設定が必要です。
--mount=type=cache
を使ってもキャッシュが効かない- Dockerfileの先頭に
# syntax=docker/dockerfile:1
のようなBuildKitシンタックス指定を忘れていませんか? --mount
オプションは特定のRUN
命令に付随します。同じDockerfileでも、別のRUN
命令ではそのキャッシュは利用できません。- キャッシュ対象のディレクトリが正しいか(例:npmキャッシュなら
/root/.npm
など、使用しているイメージやユーザーによってパスが異なります)確認してください。 - 依存するファイル(例:
package.json
やrequirements.txt
など)が変更された場合、キャッシュは無効になります。 - ビルダーインスタンスを変更したり再作成したりすると、以前のキャッシュが利用できなくなることがあります。
docker buildx du
コマンドでキャッシュの使用状況を確認できます。
- Dockerfileの先頭に
- ビルド後のイメージが
docker images
で見えないdocker buildx build
のデフォルト出力はtype=image
ですが、--push
オプションを使うと、デフォルト出力がtype=registry
になり、ローカルデーモンには保存されません。ローカルにも保存したい場合は、--output type=image,type=registry,push=true
のように複数指定が必要です。
- ディスク容量が不足する
- BuildKitのキャッシュは、適切に管理しないとディスク容量を消費します。
docker buildx du
コマンドでBuildKitキャッシュの使用量を確認できます。docker buildx prune
コマンドで不要なキャッシュを削除できます。
bash
docker buildx prune --all --force
--all
は全て(停止中のビルダー関連含む)、--force
は確認プロンプトなしで削除を実行します。注意して実行してください。
これらのトラブルシューティングのヒントは、Buildx利用時に遭遇しやすい問題に対処するのに役立つでしょう。
12. まとめ:Buildxで未来のDockerビルドへ
この記事では、Docker Buildxがなぜ必要とされているのか、そのバックエンドであるBuildKitの強力な機能(並列処理、高度なキャッシュ、マルチプラットフォーム対応)がどのようにビルドを高速化・効率化するのか、そしてBuildxの基本的な使い方から高度な機能、CI/CDでの活用法までを詳細に解説しました。
従来のdocker build
はシンプルで多くの用途に十分ですが、現代の開発ワークフロー、特に高速なCI/CDや多様なプラットフォームへの対応が求められる環境では、Buildxが提供する機能は必須となりつつあります。
Buildxを利用することで:
- ビルド時間が大幅に短縮されます。
- マルチプラットフォームイメージのビルドが驚くほど簡単になります。
- ビルドキャッシュを効率的に管理し、CI/CDパイプラインを高速化できます。
- 秘匿情報を安全にビルドプロセスに渡せます。
- ビルド成果物を柔軟な形式で出力できます。
BuildxとBuildKitは、Dockerビルドの未来を担う技術です。最初は少し慣れが必要かもしれませんが、一度そのパワーを知れば、従来のビルド方法には戻れなくなるでしょう。
この記事が、あなたのBuildx入門の一助となり、より快適で強力なDockerビルドライフを送るための一歩となれば幸いです。ぜひ今日からBuildxを使ってみて、その違いを体感してください。
13. 付録:関連リソース
- Docker Buildx 公式ドキュメント: https://docs.docker.com/buildx/
- BuildKit GitHub リポジトリ: https://github.com/moby/buildkit
- Dockerfile Best Practices: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ (BuildKitの機能と組み合わせることで、さらに効果的なDockerfileが書けます)
docker/build-push-action
(GitHub Actions): https://github.com/docker/build-push-action (GitHub ActionsでBuildxを使う際の公式アクション)
以上で、約5000語の詳細なDocker Buildx入門記事となります。初心者の方にも理解しやすいように、各機能の目的や仕組み、具体的なコマンド例、実践的なシナリオなどを盛り込みました。