x86_64 な Windows 11 の WSL2 上の Docker で、aarch64 な Raspberry Pi OS 上の Docker 向けコンテナをビルドする手順です。
基本的に Multi-platform buildsをなぞった内容で、ポイントは以下の通り。
wsl2$ docker run --privileged --rm tonistiigi/binfmt --install all
wsl2$ docker build --platform linux/arm64 -t alpine_aarch64 .
WSL2 側の準備
Docker Engine のインストール
- Ubuntu(Latest を対象) をインストール。インストール済みなら次へ
- Install Docker Engine on Ubuntu の apt repository からのインストール に従って Docker Engine をインストール
- 一般ユーザーで
docker
コマンドを使いたいならsudo usermod -a -G docker $USER
を実行
- 一般ユーザーで
-
docker run --rm hello-world
で動作確認
扱えるアーキテクチャは docker buildx ls
で確認できます。
この時点では x86 アーキテクチャのみです。
wsl2$ docker buildx ls --no-trunc
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default* docker
\_ default \_ default running v0.22.0 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386
Multi-platform builds
Multi-platform builds の QEMU に沿って binfmt をインストール。
docker run --privileged --rm tonistiigi/binfmt --install all
wsl2$ docker run --privileged --rm tonistiigi/binfmt --install all
installing: mips64le OK
installing: mips64 OK
installing: ppc64le OK
installing: riscv64 OK
installing: arm OK
installing: s390x OK
installing: loong64 OK
installing: arm64 OK
{
"supported": [
"linux/amd64",
"linux/amd64/v2",
"linux/amd64/v3",
"linux/amd64/v4",
"linux/arm64",
"linux/riscv64",
"linux/ppc64le",
"linux/s390x",
"linux/386",
"linux/mips64le",
"linux/mips64",
"linux/loong64",
"linux/arm/v7",
"linux/arm/v6"
],
"emulators": [
"WSLInterop",
"WSLInterop-late",
"qemu-aarch64",
"qemu-arm",
"qemu-loongarch64",
"qemu-mips64",
"qemu-mips64el",
"qemu-ppc64le",
"qemu-riscv64",
"qemu-s390x"
]
}
再度 docker buildx ls
をすると、扱えるアーキテクチャが増えていることが確認できます。
Raspberry Pi OS(64-bit) の aarch64
は linux/arm64
です。
wsl2$ docker buildx ls --no-trunc
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default* docker
\_ default \_ default running v0.22.0 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
ビルドしてみる
FROM alpine
まずはデフォルトとなる x86 アーキテクチャ向けでビルド。
wsl2$ ls
Dockerfile
wsl2$ docker build -t alpine_x86 .
wsl2$ docker run --rm alpine_x86 uname -m
x86_64
aarch64 アーキテクチャ向けでビルド。
※ docker run
の際に --platform
をつけ忘れるとWARNINGが出ます(が、実行してくれます)
wsl2$ docker build --platform linux/arm64 -t alpine_aarch64 .
wsl2$ docker run --platform linux/arm64 --rm alpine_aarch64 uname -m
aarch64
コンテナをアーカイブ
Raspberry Pi に持ち込むため、コンテナをアーカイブします。
※ docker push
とかリポジトリ経由でもいいです
docker save alpine_aarch64 | gzip - > alpine_aarch64.tar.gz
alpine_aarch64.tar.gz
を Raspberry Pi に(何らかの方法で)コピーします。
Raspberry Pi 側の準備
Docker Engine のインストール
- Docker Engine は convenience script に沿って
get-docker.sh
を実行してインストール- 一般ユーザーで
docker
コマンドを使いたいならsudo usermod -a -G docker $USER
を実行
- 一般ユーザーで
-
docker run --rm hello-world
で動作確認
扱えるアーキテクチャは docker buildx ls
で確認できます。
当然ながら Arm アーキテクチャが扱えます。
rpi$ docker buildx ls --no-trunc
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default* docker
\_ default \_ default running v0.22.0 linux/arm64, linux/arm/v7, linux/arm/v6
alpine_aarch64.tar.gz
を取り込んで実行してみます。
rpi$ cat alpine_aarch64.tar.gz | gunzip -c | docker load
a16e98724c05: Loading layer [==================================================>] 8.461MB/8.461MB
Loaded image: alpine_aarch64:latest
rpi$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine_aarch64 latest df9cbdbfb963 3 months ago 8.17MB
rpi$ docker run --rm alpine_aarch64 uname -m
aarch64
無事、WSL2 側でビルドした aarch64 向けコンテナが、Raspberry Pi 上で実行できました。
Raspberry Pi OS(64-bit) 上で x86 向けコンテナをビルドする
逆のパターンです。
といっても、Raspberry Pi OS 上で docker run --privileged --rm tonistiigi/binfmt --install all
をすれば --platform linux/amd64
が使えるようになります。
トラブルシュート
docker run --platform ..
で exec format error
wsl2$ docker run --platform linux/arm64 --rm alpine_aarch64
exec /bin/uname: exec format error
こうなった場合は、再度 docker run --privileged --rm tonistiigi/binfmt --install all
を実行します。
wsl2$ docker run --platform linux/arm64 --rm alpine_aarch64
exec /bin/uname: exec format error
wsl2$ docker run --privileged --rm tonistiigi/binfmt --install all
...
wsl2$ docker run --platform linux/arm64 --rm alpine_aarch64
aarch64
tonistiigi/binfmt
は QEMU に対して透過的にアクセスできるようにします。
この状態はホスト側の /proc/sys/fs/binfmt_misc/
内の qemu-(arch)
ファイルで確認できます。ざっくり言うなら、このファイルがあれば --platform
オプションが機能するという理解でOKです(詳細はこちら)。
wsl2$ ls /proc/sys/fs/binfmt_misc/qemu-*
ls: cannot access '/proc/sys/fs/binfmt_misc/qemu-*': No such file or directory
wsl2$ docker run --privileged --rm tonistiigi/binfmt --install all
...
wsl2$ ls /proc/sys/fs/binfmt_misc/qemu-*
/proc/sys/fs/binfmt_misc/qemu-aarch64 /proc/sys/fs/binfmt_misc/qemu-mips64el
/proc/sys/fs/binfmt_misc/qemu-arm /proc/sys/fs/binfmt_misc/qemu-ppc64le
/proc/sys/fs/binfmt_misc/qemu-loongarch64 /proc/sys/fs/binfmt_misc/qemu-riscv64
/proc/sys/fs/binfmt_misc/qemu-mips64 /proc/sys/fs/binfmt_misc/qemu-s390x
wsl2$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64
flags: POCF
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff
このファイルは再起動後には無くなります。そのため必要時に docker run --privileged --rm tonistiigi/binfmt --install all
を実行してください。
EoT