はじめに
ECS fargate を ARM64/Graviton で動かすためには、arm64版のDocker imageをbuildして利用する必要があります。
既存で動作しているDocker image build のサーバのCPUがx86_64版のAmazon Linux 2023だったため、通常はx86_64でimage buildされますが、Buildx + QEMU でエミュレーションをすることで、arm64(AArch64) 用イメージをクロスビルドできます。
本記事の方針は以下の通りです。
- CPUアーキテクチャやQEMUの詳しい説明は行いません。
- Amazon Linux 2023で検証した結果です。
- タイトル通り、x86_64版Amazon Linux 2023でarm64のDocker image buildをするための方法を知りたい人向けです。
- Dockerfileの記述方法やdokcer image build方法には言及しません。
最初に結論
以下のようにコマンド実行することで、Docker Buildx を有効化し、arm64でbuildすることが可能になります。(Amazon Linux 2023で確認済み)
$ ls /proc/sys/fs/binfmt_misc > /dev/null
$ sudo docker buildx rm multi 2>/dev/null || true
$ sudo docker buildx create --name multi --driver docker-container --use
$ sudo docker buildx inspect --bootstrap
$ sudo docker run --privileged --rm tonistiigi/binfmt --install all
以下のように確認してください。linux/arm64が含まれていればOKです。
$ sudo docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
multi * docker-container
multi0 unix:///var/run/docker.sock running v0.26.2 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64, linux/loong64, linux/arm/v7, linux/arm/v6
default docker
default default running v0.12.5 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
説明
それぞれのコマンドは以下のような意味合いです。
ls /proc/sys/fs/binfmt_misc > /dev/null
binfmt_misc は Linux カーネルの仮想ファイルシステムで、/proc/sys/fs/binfmt_misc を「読みに行ったタイミング」でエントリが初期化・反映される仕組みになっているため ls を実行
/usr/bin/docker buildx rm multi 2>/dev/null || true
既存 multi を一度削除する
/usr/bin/docker buildx create --name multi --driver docker-container --use
/usr/bin/docker buildx inspect --bootstrap
Buildx 作成、有効化
/usr/bin/docker run --privileged --rm tonistiigi/binfmt --install all
binfmt に QEMU を登録
記事投稿の背景
AIに聞いてみると
- (1)Buildx 作成、有効化のコマンド
- (2)binfmt に QEMU を登録するコマンド
- (3)binfmt(QEMU) にaarch64 の登録があるかを確認するコマンド(ls /proc/sys/fs/binfmt_misc)
- (4)Platforms に linux/arm64 が含まれるか確認するコマンド(docker buildx ls)
それぞれ、実行してくださいというようにアドバイスされるのですが、(1)と(2)を実行した後に(3)(4)を実行してもどうも(4)も結果にlinux/arm64が出たり出なかったりするような状況でした。
ポイントとしては、(3)のls /proc/sys/fs/binfmt_miscを先に実行しておく必要があるということです。
・binfmt_misc は Linux カーネルの仮想ファイルシステムで、
/proc/sys/fs/binfmt_misc を「読みに行ったタイミング」でエントリが初期化・反映される仕組みになっています。
• 特に Amazon Linux 2023 のように systemd-binfmt が標準で常駐していない環境だと、
tonistiigi/binfmt が QEMU を登録したあとでも、カーネル側にエントリがすぐに可視化されないケースがあります。
• ls や cat で /proc/sys/fs/binfmt_misc を参照すると、そのディレクトリの内容が「初めて評価」されて、
QEMU の登録が見えるようになります。
つまり “見えるようになるトリガーが ls 実行” という状態です。
とのことでした。
※ ls コマンドなので、設定後に設定内容を確認する用途で利用しているのかと思い込んでいました。
補足
ホストが再起動されると設定が戻ってしまうため、ホスト起動後にarm64 build を可能にするために、以下の要領で起動時にコマンド実行されるようにすると良いかと思われます。
@reboot root /usr/local/bin/register-binfmt.sh > /tmp/register-binfmt.log
#!/bin/bash
# docker が起動するまで待機
until systemctl is-active --quiet docker; do
sleep 2
done
## binfmt_misc は Linux カーネルの仮想ファイルシステムで、/proc/sys/fs/binfmt_misc を「読みに行ったタイミング」でエントリが初期化・反映される仕組みになっているため ls を実行
ls /proc/sys/fs/binfmt_misc > /dev/null
# 既存 multi を一度削除する
/usr/bin/docker buildx rm multi 2>/dev/null || true
# Buildx 有効化
/usr/bin/docker buildx create --name multi --driver docker-container --use
/usr/bin/docker buildx inspect --bootstrap
## binfmt に QEMU を登録
/usr/bin/docker run --privileged --rm tonistiigi/binfmt --install all