背景
Windows環境(Intel/AMD)で開発を進めている中で、Lambda(Linux/ARM64)にデプロイするための Docker イメージをビルドしようとしたところエラーが発生しました。
結論、ホストマシンとビルドターゲット間のプラットフォームの違いが原因でした。
この記事では、このような異なるプラットフォーム間のビルド課題を解消するために、Docker Buildxを活用する方法を解説します。
Docker Buildx とは
Docker Buildx は、Docker の拡張ツールで、特にマルチプラットフォーム対応のコンテナイメージをビルドするために使われます。
通常の Docker ビルドではホストと同じプラットフォーム向けのイメージしか作成できませんが、Buildx を使えば、異なるプラットフォーム向けのイメージを簡単にビルドできます。
なぜ異なるプラットフォームでのビルドができない?
そもそも、なぜ異なるプラットフォーム間でビルドができないのかというと、ホストマシンとターゲットプラットフォーム間のアーキテクチャや命令セットの違いが原因です。
1. CPUアーキテクチャの違い
ホストマシン(ビルドを実行するマシン)とターゲットプラットフォームのCPUアーキテクチャが異なる場合、互換性がないバイナリが生成される可能性があります。
例えば、ホストが x86_64(Intel/AMD) で、ターゲットが arm64(ARM) の場合、生成されるコードが異なるCPUの命令セットを理解できません。
そのままではターゲットの環境で実行できないコンテナイメージが作成されます。
2. ネイティブ依存関係
Dockerイメージの中には、ネイティブのライブラリやバイナリ(CやC++で書かれたコード)を含む場合があります。
これらのネイティブコンポーネントは、ビルド時のプラットフォーム(ホスト)でコンパイルされるため、異なるプラットフォームで動作しない可能性があります。
例えば、x86_64 でビルドされたライブラリ(例:glibc)は、arm64 では動作しません。
特に、Dockerfileで RUN コマンドを使用してソフトウェアをインストールする際に問題が発生します。
3. Dockerの設計方針
Dockerは、シンプルで高速なビルドを提供するため、基本的にはホストプラットフォームと同じアーキテクチャをターゲットにしています。
ホストとターゲットのアーキテクチャが一致する場合、ネイティブな速度でビルドと実行が可能です。
一致しない場合、標準的なDockerではこれをサポートしていないため、エラーになります。
マルチプラットフォームビルドの流れ
1.Buildx インスタンスの作成
docker buildx create --use --name mybuilder
mybuilderの部分は任意の名前で大丈夫です。
2.QEMUの有効化
docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64
QEMU をインストールすることで異なるプラットフォームへのビルドがエミュレート可能になります。
3.Buildx インスタンスを初期化
docker buildx inspect --bootstrap
docker buildx createはインスタンスを作成するだけなので初期化が必要
4. プラットフォームの確認
docker buildx ls
下記のように出力されれば大丈夫です。PLATFORMS
にlinux/amd64やlinux/arm64があるので、マルチプラットフォームが有効になっています。
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
mybuilder* docker-container
\_ mybuilder0 \_ unix:///var/run/docker.sock running v0.17.2 linux/amd64, linux/arm64, linux/arm/v7, linux/386
5.マルチプラットフォームビルドの実行
docker buildx build --platform linux/arm64 --tag my-image:latest .
QEMU とは
QEMUは、オープンソースのエミュレーターで、異なるプラットフォーム間(例:x86_64 と arm64)の互換性を提供します。具体的には、ホストマシンがサポートしていないCPUアーキテクチャの命令セットをエミュレーションし、その環境でアプリケーションやOSを実行可能にします。Dockerと組み合わせることで、異なるプラットフォーム向けのコンテナイメージをビルドできるようになります。
Buildx だけではダメな理由
Buildx はマルチプラットフォームビルドをサポートしますが、ホストプラットフォーム以外のアーキテクチャ向けのビルドには QEMU が必要です。
Buildx はあくまで Docker のビルド機能を拡張するツールであり、異なるCPUアーキテクチャ(例:x86_64 → arm64)の命令セットそのものをエミュレーションする機能は持っていません。
Buildx 関連の便利コマンド
1. Buildx バージョン確認
docker buildx version
2. ターゲットプラットフォームの確認
現在のホストマシンのプラットフォームを確認します。
uname -m
3. Buildx インスタンスの削除
不要になった Buildx インスタンスを削除します。
docker buildx rm mybuilder
・追記
Docker デーモンが再起動すると、 QEMU 設定がリセットされるので、定期的に有効化が必要になる。