🐳

rasbery piのdockerコンテナをx86(Mac)で動かす

2022/03/18に公開

ラズパイの環境を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 --platform=arm64 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