rasbery piのdockerコンテナをx86(Mac)で動かす
ラズパイの環境をdockerで作ってビルドとかテストとかそこでやったろ!って思い立ったものの意外に手間取ったので手順をメモしておきます。
これを行ったPCはintel MacのmacOS Motereyです。ただほとんどの手順はwin/linuxでも共通すると思います。
ラズパイイメージの作成
まずラズパイのベースイメージを作成します。
ここにあるルートイメージ(root.tar.xz)をダウンロードしてdockerにインポートしてイメージを作成します。このリンクは「Bullseye ベースの 64-bit 版 Raspberry Pi OS の lite」のものです。ディレクトリトラバーサルすると他のも見つかるでしょう。
イメージのインポートは次のコマンドで行います
docker image import https://downloads.raspberrypi.org/raspios_lite_arm64/root.tar.xz raspiarm64-lite:latest
ここのURLは先ほどのリンク先から拾ってきたものです。最後のraspiarm64-lite:latest
は任意のイメージ名:タグ名なので好きに変えられます。
もしダウンロードしてきたファイルからインポートしたければ
docker image import root.tar.xz raspiarm64-lite:latest
のようにします。
Docker Hubへのプッシュの必要性
このイメージを直接起動する場合は気にしなくてもいいのですが、これをDockerfileのベースイメージとして使用する場合、どうやらDocker Hubへあげなくてはならないようです(プライベートリポジトリとかでもなんとかなるかもしれませんが未確認)。
なので、Docker Hubにアカウントを作った上でリポジトリを1つ作っておきます。ここでは、ユーザー名user、リポジトリ名をraspitestとしておきます。
まず公開用のタグ設定をして
docker tag raspiarm64-lite:latest user/raspitest:latest
ここでは、docker tag ローカルのイメージ名:タグ 公開用のリポジトリ名/イメージ名:タグ
のように指定します。ローカルのイメージ名はインポートした時につけたものです。
その後プッシュします
docker push user/raspitest:latest
buildxによるビルド
こうしてDocker Hubにあるラズパイのベースイメージができたので、それを使ってDockerfileを作ります。例えば
FROM user/raspitest:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get upgrade -qqy --no-install-recommends \
&& apt-get install -qqy --no-install-recommends \
git build-essential cmake python3-pip \
&& apt-get -y clean \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --upgrade pip \
&& pip3 install meson ninja
CMD ["/bin/bash"]
--platform=arm64
は要らない気がします。
x86環境では、そのまま普通にビルドしようとするとできないはずなので(ベースイメージからARMなので)、ビルドのためにbuildxというものを使用して、実行環境と異なるアーキテクチャ向けのイメージを作成します。buildxはDcoker Desktopを使っていればすでに入ってるらしいです。Linuxでは無い可能性がありますが、手動インストール方法があるようです。
buildxでのビルドにあたっては、まずbuilderを作成します。デフォルトのものがあるのですが、これだと異なるアーキテクチャ向けのビルドができないようです。
docker buildx create --name mybuilder
mybuilder
という名前で作成しています。
DockerDesktop環境では必要ないですが、それ以外の場合は異なるアーキテクチャ向けビルドのためのエミュレーション環境の設定(QEMU周りの設定)が追加で必要です。
docker run --privileged --rm tonistiigi/binfmt --install all
tonistiigiって誰だよって感じですが、公式のドキュメントがこれを使えと言ってるので多分大丈夫でしょう、多分。また、DockerDesktop環境で実行しても別に不都合は起こりません(多分)。
mybuilder
を使って次のようにビルドを行います
docker buildx build --builder mybuilder --platform linux/arm64 -t rpiarm64_env --load .
--builder
は先ほど作ったbuilderを、--platform
にはビルド対象のターゲットを指定(ここではlinux/arm64)します。--load
はビルド成果物をローカルのdockerに転送することを指示するもので、その他のものは普通のビルド時と同じオプションが使えるようです。
ここではしないですが、--platform
には複数のターゲットを指定でき、マルチプラットフォームイメージを作成することができます。
Dockerfile自体もbuildxのために何かをする必要はなく、ビルド自体もいつものDockerfileビルドの時と同じように行われます。
実行
ビルドが終わると、--load
オプションを指定していればそのまま普通のdockerイメージとして利用可能となっています。起動も特別なことはなくdokcer run
で行うことができます。
ただし、このイメージはARM64のものなので、実行に際しては暗黙的にエミュレーションが行われています。また、docker run
ではプラットフォームを指定しないと実行環境のものと一致するイメージが自動で選択されて実行されますが、この場合はlinux/arm64しかないのでそれが自動で選択され、その旨が警告で表示されます。警告を抑制するためには、プラットフォームを明示的に指定してやります
docker run -it --rm --platform linux/arm64 rpiarm64_env
これ以外のところでは、通常のコンテナに準じた使い方が可能です。
Discussion