Raspberry PiでDockerを動かす

[DockerCon19](https://www.youtube.com/watch?v=H3qcJgSJA6U)にてDockerのARM対応が話されていたので、ラズパイ向けのイメージをMacでクロスコンパイルして見ることにしました。
ちなみに、元々ARM自体には対応していましたが今回のカンファレンスの話だとクロスコンパイルとDockerHubでのマルチアーキテクチャ対応がメインかと思います。

## Raspberry PiにDockerをインストール

まずは、ラズパイにDockerをインストールします。
Raspbianを使ってるので[こちら](https://docs.docker.com/install/linux/docker-ce/debian/)に記載がある通りapt-getで入れます。

```bash
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
$ docker -v
Docker version 18.09.0, build 4d60db4
```

ラズパイ側の準備はこれで完了です。

## Docker Desktop(β)のインストール

`19.03.0`からバックエンドでqemuを利用してMacでも`linux/amd64`のみならず`linux/arm/v7`や`linux/arm64`、さらには`windows/amd64`がビルドできるようになりました。
ただし、19.03はまだベータ版なので、以下のURLから`Docker Desktop for Mac Community`のベータ版を入れる必要があります。

https://beta.docker.com/

```bash
$ docker -v
Docker version 19.03.0-beta3, build c55e026
```

上記のように19.03がインストールされていれば成功です。

## Dockerfileの作成

Dockerfileの作成をします。なんでも良いのですが、以前作った「[Raspberry PIでデスクトップ環境無しでChromiumを起動する](https://qiita.com/koduki/items/73feb19d0ccca62a923c)」の内容をDockerイメージにしてみます。

```Dockerfile
FROM debian:buster

RUN apt-get update && \
    apt-get install -y xinit matchbox-window-manager xterm chromium && \
    apt-get -y --purge autoremove && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY run.sh /app/run.sh
CMD ["./run.sh"]
```

run.shは以下の通り。

```bash
#!/bin/sh

xinit matchbox-window-manager &
chromium --no-sandbox -kiosk "http://www.youtube.com"
```

Raspbianを使う必要はないので普通にDebianを使用しています。
重要なのはDockerHubの公式を見れば分かると思うのですがこの`公式イメージがArmに対応しているということ`です。

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54904/4f8e2e24-d8a3-565b-ecea-96d9eff69556.png)

Dockerは実行環境または指定されたオプションに従って適切なCPUアーキテクチャのイメージを落とします。
Dockerfile内でapt-get等もしていますがこれも元イメージが同じなので特に意識することなくx86とARMが切り替わります。
これによって動作確認は高速なx86で行って同じDockefileを編集なしにARM版のモジュールを作成することができます。

ARMイメージのビルド
-------

ではARM版のビルドを行います。具体的には`--platform`を指定します。

```bash
$ docker buildx build -t koduki/rpi-chrome --platform linux/arm/v7 --push .
```

開発版のbuildkitの機能を使うために`buildx`を指定しています。また、ラズパイはarmv7なので`linux/arm/v7`をplatformに指定しています。

詳細に関しては下記を参照してください。
https://github.com/docker/buildx#building-multi-platform-images

今回はlinux/arm/v7しか指定していませんが、マルチプラットフォームのイメージを作りたい場合は下記のようにDriverを`docker-container`に変更し、`,`で区切ることで複数モジュールのビルド/Pushができるようになります。

```bash
$ docker buildx create --driver docker-container --name multibuild
$ docker buildx use multibuild
$ docker buildx build -t koduki/rpi-chrome --platform linux/amd64,linux/arm/v7 --push .
```

Raspberry Piでコンテナを実行する
----------

実行するに当たって特に特別な事はありませんがラズパイ上で実行してみます。

```bash
$ docker run -it koduki/rpi-chrome uname -a
Linux cd4a0c8248fb 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux
```

通常通りDockerHubから落として実行されます。この時にARM向けのモジュールを登録しておけば適切に選択され上記のように実行されますあ、arm64とかamd64とかしか登録してないと当然実行時にエラーになるのでご注意ください。

では、Chromeを起動してみましょう。

```bash
$ docker run -it -e DISPLAY=:0 --privileged koduki/rpi-chrome
```

少しサボって`privileged`を渡しています。これはGPUを叩くためです。
また、同じく`:0`をDISPLAYとして環境変数に渡しています。

まとめ
-------

「ラズパイでDocker動かしてなんの意味あるの？」と言われそうですがデプロイの管理がやはり楽になります。Dockerで配布して終わりになるので。ラズパイ側でaptとか不要！
あと、ラズパイ側が究極的にはかなり薄くできるのでIoT的にも良いんじゃないかと。

`19.03.0`はビルドが高速化されたり今回のクロスプラットフォームビルドなど、かなり新機能が盛りだくさんなのでもうちょっと追っていきたいと思います。
それではHappy Hacking!

参考
------

- [GitHub buildx](https://github.com/docker/buildx)
- [GitHub buildkit](https://github.com/moby/buildkit)