PC LinuxのDockerコンテナでラズパイOSを動かす

このQiitaにも同様のネタは上がっているが、そこに記載の方法では目的が達成できなかったので、自分の経験と実績に基づき、PC Linux (x86-64)をホストとしたDockerコンテナでラズパイOSを動かす方法を記載する。

# 用意するもの

## Dockerホスト

| 項目             | 説明                          |
|:-----------------|:------------------------------|
| アーキテクチャ    | Intel系CPU (x86-64)           |
| OS               | Debian 10 (buster)            |
| Docker           | version 24.0.7, build afdd53b |
| qemu-user-static | version 3.1.0                 |

## ラズパイOS

| 項目            | 説明                   |
|:----------------|:-----------------------|
| アーキテクチャ   | ARM系CPU (armhf)       |
| アーキテクチャ   | ARM系CPU (arm64)       |
| OS              | Raspbian 11 (bullseye) |

# 構築手順(armhf)

OSはインストール済みであることが前提。
https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/debian/ にしたがって、現時点で最新のDockerエンジンをインストール。
以下のコマンドを実行するユーザーはdockerグループに所属していることが前提。

```bash
# qemu-arm-staticを含むパッケージをインストール
$ apt-get -y install qemu-user-static

# ラズパイOSの入手
$ wget https://downloads.raspberrypi.org/raspios_lite_armhf/root.tar.xz -O raspios_lite_armhf-root_2022-04-04.tar.xz

# Dockerイメージの取り込み
$ docker image import --platform=linux/arm/v7 raspios_lite_armhf-root_2022-04-04.tar.xz raspios_lite_armhf:2022-04-04

# ld.so.preloadの準備（これが無いとエラーが発生）
$ echo /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so > ld.so.preload

# Dockerコンテナを起動
$ docker run -it --platform=linux/arm/v7 --name raspbian32 --rm -v $(pwd)/ld.so.preload:/etc/ld.so.preload raspios_lite_armhf:2022-04-04 /bin/bash
```

肝となるのは --platform でdockerコマンドにアーキテクチャを指定する点。

上記ld.so.preloadをDockerコンテナにマウントせず起動すると、以下のエラーが発生するので注意。

:::note warn
ERROR: ld.so: object '/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
:::

ラズパイOSのダウンロード先には[raspbian_lite](https://downloads.raspberrypi.org/raspbian_lite/)、[raspbian](https://downloads.raspberrypi.org/raspbian/)、[raspbian_full](https://downloads.raspberrypi.org/raspbian_full/)も存在するが、試したところ、これらはRaspbian 10 (buster)であり、armhf用のものだった。

## DockerコンテナのRaspbianで試したコマンド

取り敢えず、apt-getが動作したのでこれで良しとする。

```bash
# cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)"
NAME="Raspbian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
# apt-get update
...
# apt-get upgrade
...
# apt-get install file
...
# file -e elf /bin/ls
/bin/ls: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)
# cat /proc/cpuinfo
...ホストの情報...
# date
Wed Nov  1 15:28:57 GMT 2023
```

# 構築手順(arm64)

armhfに続いて、arm64の方も試した。

```bash
# ラズパイOSの入手
$ wget https://downloads.raspberrypi.org/raspios_lite_arm64/root.tar.xz -O raspios_lite_arm64-root_2022-04-04.tar.xz

# Dockerイメージの取り込み
$ docker image import --platform=linux/arm64 raspios_lite_arm64-root_2022-04-04.tar.xz raspios_lite_arm64:2022-04-04

# Dockerコンテナを起動
$ docker run -it --platform=linux/arm64 --name raspbian64 --rm raspios_lite_arm64:2022-04-04 /bin/bash
```

残念なことに、apt-get upgradeを実行すると、以下のエラーが発生し、正常に動作しなかった。

```
Preparing to unpack .../libc-bin_2.31-13+rpt2+rpi1+deb11u7_arm64.deb ...
Unpacking libc-bin (2.31-13+rpt2+rpi1+deb11u7) over (2.31-13+rpt2+rpi1+deb11u2) ...
Setting up libc-bin (2.31-13+rpt2+rpi1+deb11u7) ...
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
dpkg: error processing package libc-bin (--configure):
 installed libc-bin package post-installation script subprocess returned error exit status 139
Errors were encountered while processing:
 libc-bin
E: Sub-process /usr/bin/dpkg returned an error code (1)
```

その後、[raspios_arm64](https://downloads.raspberrypi.org/raspios_arm64)や[raspios_full_arm64](https://downloads.raspberrypi.org/raspios_full_arm64/)も試してみたが、apt-get upgradeで同じエラーが発生した。
しかし、[raspios_lite_arm64](https://downloads.raspberrypi.org/raspios_lite_arm64/)に比べて多くのツールが含まれているため、パッケージを追加する必要がないかも知れない。

また、[qemu-uesr-static 8.1.2](https://packages.debian.org/sid/amd64/qemu-user-static/download)を試してみたが、apt-get upgradeのエラーは回避できなかった。

# 未解決な疑問

dockerコマンドの--platformオプションに指定可能な値は何か、調べてもはっきりしない。
現在の環境で使える値が分かるので、dockerコマンドで表示できるのが最も良いのだが、それができるのかどうかも分からずじまい。