ヘッドレスインストール—Docker on Alpine Linux on Raspberry Pi Zero W

ドッカー・オン・アルパイン・リナックス・オン・ラズベリー・パイ・ゼロ・ダブリュー


意地でもモニタを繋げたくなかった。

# インストール

Alpineは何もしないとディスクレスで動くが、RPi0にはメモリが512MBしかない。普通にインストールしてDockerデーモンをブート時に起動させようとすると、必要なパッケージ類が全てメモリ上に置かれることになり容量不足で落ちるっぽいかもなのです[^1]。なのでディスクに書き込む普通のインストールを行う。

## 事前準備

まずはmicroSDカードを準備する。基本的にはここを読んで従うだけ。

- https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi

なのだが、ヘッドレスインストールするためにはブート前にWi-FiやSSHのセットアップをしなければならない。追加で以下の作業（オーバーレイファイルの作成&コピー）が必要なのだが、一部修正が必要なので後述。

- https://wiki.alpinelinux.org/wiki/Raspberry_Pi_-_Headless_Installation

修正というのは`hostname`の内容で、一行追加しないとWi-Fiが動かない。上記記事にあるものの代わりに以下のをコピペすればOK（もちろんSSIDなどは各自書き換えること）。

```shell
#!/bin/sh

apk add wpa_supplicant

cat <<EOF >> /etc/network/interfaces
auto lo
iface lo inet loopback

auto wlan0
iface wlan0 inet dhcp
	hostname localhost

EOF

cat <<EOF >> /etc/wpa_supplicant/wpa_supplicant.conf
network={
	ssid="Changeme"
	key_mgmt=WPA-PSK
	psk="Changeme"
}
EOF

service wpa_supplicant start
service networking start
rm /var/run/ifstate

rc-update add wpa_supplicant boot # we need this line

/sbin/setup-sshd -c openssh
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig

cat <<EOF >> /etc/ssh/sshd_config
PermitEmptyPasswords yes
PermitRootLogin yes
EOF

service sshd restart
mv /etc/ssh/sshd_config.orig /etc/ssh/sshd_config

rm /bin/hostname
ln -s /bin/busybox /bin/hostname
```

ちなみにこのファイルは何かというと、ブート時に呼び出される`/bin/hostname`をフックしてWi-FiとSSHの設定を済ませてしまうシェルスクリプト。

つまり要約すると、ブート前の作業は、

1. microSDカードをフォーマットする
2. Alpine Linuxのarmhf用パッケージを解凍してぶちこむ
3. （上記`hostname`ファイルを含む）オーバーレイを作成してぶちこむ

という流れになる。

## ブート

これも基本的にはここを読んで従うだけ。

- https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi#Installation

**ただし**最後の`reboot`の前にやっておく必要のある作業がある。先ほどWi-FiとSSHをオーバーレイで設定したが、今`/mnt`にマウントしたAlpine Linuxにはそれらは反映されておらず、`setup-alpine`による初期設定のみが反映されているっぽいかもなのです。つまりここで`reboot`してしまうと、Wi-Fiの設定は`setup-alpine`中に行なったので問題ないが、SSHの設定はデフォルトのままなので`root`でパスワードレスログインできなくなってしまう。

したがってこの時点で`/mnt/etc/ssh/sshd_config`を編集したり`/mnt/root/.ssh/authorized_keys`を作成したりしなければならない。

必要なところを編集したら`reboot`。峠は越えた。

## Dockerセットアップ

Dockerのインストールは下記参照。

- https://wiki.alpinelinux.org/wiki/Docker

以下略。以上。

# おまけ

筆者がmacOS上で上記を実行したときのコマンド一覧。

```sh
diskutil list # microSDカードの番号を調べる。ここでは`2`
sudo diskutil partitionDisk /dev/rdisk2 MBR 'MS-DOS FAT16' VOL1 256MB 'FREE' VOL2 R
cd /Volumes/VOL1
tar zxvf ~/Downloads/alpine-rpi-3.11.3-armhf.tar.gz
cp ~/localhost.apkovl.tar.gz ./ # オーバーレイファイルを入れる
```

RPi0ブート後に実行したコマンド一覧。

```sh
setup-alpine
vi /etc/apk/repositories # `edge`リポジトリに切り替え
apk update
apk upgrade
apk add cfdisk e2fsprogs
cfdisk /dev/mmcblk0
mkfs.ext4 /dev/mmcblk0p2
mount /dev/mmcblk0p2 /mnt
setup-disk -m sys /mnt
mount -o remount,rw /media/mmcblk0p1
rm -f /media/mmcblk0p1/boot/*  
cd /mnt
rm boot/boot
mv boot/* /media/mmcblk0p1/boot/  
rm -Rf boot
mkdir media/mmcblk0p1
ln -s media/mmcblk0p1/boot boot
echo "/dev/mmcblk0p1 /media/mmcblk0p1 vfat defaults 0 0" >> etc/fstab
sed -i '/cdrom/d' etc/fstab
sed -i '/floppy/d' etc/fstab
sed -i 's/^/root=\/dev\/mmcblk0p2 /' /media/mmcblk0p1/cmdline.txt
vi /mnt/etc/ssh/sshd_config # `root`ログインを有効にしたり
mkdir /mnt/root/.ssh
vi /mnt/root/.ssh/authorized_keys
reboot
```

リブート後は好きにしたらいいと思う。

```sh
apk add raspberrypi wiringpi docker docker-compose
rc-update add docker boot
```

```:/media/mmcblk0p1/usercfg.txt
enable_uart=1
gpu_mem=32
dtparam=audio=on
dtparam=i2c_arm=on
```

```:/media/mmcblk0p1/cmdline.txt
root=/dev/mmcblk0p2 modules=loop,squashfs,sd-mod,usb-storage quiet console=tty1 cgroup_enable=memory cgroup_enable=cpuset swapaccount=1 iomem=relaxed
```

```:/etc/modules
af_packet
ipv6
i2c-dev
```

[^1]: 回避する方法があったら知らせなさい