Docker海賊Hypriotを使ってRaspberry Pi上でゼロから任意アプリを15分で起動する方法

概要

HypriotというLinux Distributionを15分ぐらいでラズパイにインストールして、Dockerで楽にアプリを動かしたり、環境構築したりしようっていう話です。 問題が発生しない限り、ラズパイにキーボードやディスプレイをつける必要もないです。

※15分かどうかはダウンロード速度に主に依存するので、15分ですまなくてもどうかお許しください。

用意するもの

  • Raspberry Pi 2
  • Wifiドングル(USB接続, Raspberry Piと互換性のあるもの)
  • Mac OS Xのマシン + マイクロSDカードリーダ・ライタ
  • SSID, パスワードがわかっているWifiアクセスポイント

Raspberry Pi 2 を動かしていて不満なポイントは?

以下のようなことです。

  • apt-get等でインストールにかかる時間が馬鹿にならない。
  • バージョンの問題等で失敗することも多く、ごそごそ修正する羽目になる
  • しばらく環境をいじっていると、どこをどういじったかわからなくなり、クリーンな状態からどうすれば、動かしたいアプリの実行環境になるのか、完全には把握できなくなる。
  • (きっちりシャットダウンせずに)電源抜き差しすることでSDカードが壊れやすく、壊れると上記理由で復活が面倒でガッカリする

Dockerの利用

上記の問題点は最近話題のDockerでおおかた解決可能なものです。環境セットアップをDockerfileの形で書いて残しておくこと、イメージをビルドしたら、docker hub等のリポジトリにアップロードしておくことが必要ですが、それさえできれば、以下のようなメリットが得られます。

  • dockerだけ入った素の環境から、 docker run 一発で高速、自動的にアプリの動作環境が再現できる
  • Dockerfileがあれば、どう作られたかは明らか
  • 公式を含む、他の人が作ったDockerイメージも流用、派生できるため、大きなモジュールのインストールに時間を割く必要もない。

便利!

残る課題

しかしながら、Dockerだけでは解決しない問題があります。それは、Dockerを動かす環境自体を作るところも結構面倒ということです。少なくとも、以下のようなものが必要でしょう。

  • Wi-Fi認識
  • 接続先SSID、パスワードを指定する
  • avahiのインストール(Bonjourで なんとか.local というアドレスでアクセスできるようにする)

面倒だ!

Hypriot! (はいぷらいおっと?はいぷりおっと?)

そこで、HypriotというLinux Distributionの出番です。

公式: Docker Pirates ARMed with explosive stuff · Docker Pirates ARMed with explosive stuff

f:id:hammm:20160105020216p:plain

Hypriotのとくちょう

  • ロゴがドクロマークで怖そう。
  • 公式サイトの構成がイマイチで情報を探しにくい(汗)
  • RaspberryPi (ARM)で動作するDebianLinuxディストリビューション (基本はRaspbianらしいです)
  • 余分なプログラムが入っておらずサイズが小さい
  • Wifi, Bonjour (avahi), ssh等がセットアップ済みのイメージが用意されており、Wifiドングルさえ挿しておけば起動後、即sshで外部からのコントロールが可能
  • 最新のDocker/Docker Machineが入っており、すぐにDockerを利用できる。

まあ、要するにDockerに最適化された楽ちんなRaspberry Pi向けLinuxです。

※ ちなみに、ドクロの下にでかでかと "Docker Pirates ARMed with explosive stuff" とか書いてありますが、直訳すると 「爆発物を装備(ARM)したDocker海賊」みたいな感じで、Dockerと、Raspberry PiのCPUアーキテクチャであるARMをうまくひっかけつつカッチョいい感じのイメージにしたかったという意思がひしひしと伝わってきます。一部タイトルに頂きましたw

Hypriotのインストール手順 (Mac OS X向け)

今回はflashという名前の、hypriotが用意したスクリプトを使います。 このスクリプトは、Mac OS XLinux向けになっています。

Windowsの場合は、残念ながらこのスクリプトは使えません。 別の方法でSDカードにイメージを書き込んで、occidentalis.txtを手動で修正するなどしてください。

GitHub - hypriot/flash: Command line script to flash SD card images for the Raspberry Pi

flashスクリプトの実行準備

flashの動作に必要なツールおよびflash本体をダウンロード・インストールします。 Mac OS Xのターミナル上で以下を実行してください。brewは入っている前提とします。

brew install wget pv awscli
wget https://raw.githubusercontent.com/hypriot/flash/master/$(uname -s)/flash
chmod +x flash
sudo mv flash /usr/local/bin/flash

(マイクロ)SDカードの確認

MacにHypriotインストール先となる(マイクロ)SDカードを挿します。アダプタでMacBookのスロットに挿すなり、カードライターをUSBでつなぐなりしてください。4GBくらいあればちょっとした用途には大丈夫と思いますが、8GB以上の高速タイプ(60MB/s以上)がおすすめです。

dfコマンドで、SDカードのデバイスを確認しておきましょう。

$ df
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk1 740234368 587525560 152196808 80% 73504693 19024601 79% /
devfs 392 392 0 100% 679 0 100% /dev
map -hosts 0 0 0 100% 0 0 100% /net
map auto_home 0 0 0 100% 0 0 100% /home
/dev/disk0s4 234481656 148490912 85990744 64% 363119 43017021 1% /Volumes/BOOTCAMP 32
/dev/disk2s1 31241216 4800 31236416 1% 0 0 100% /Volumes/NO NAME

いくつかエントリがありますが、今回はNO NAMEというラベルのSDカードが入っているので、/dev/disk2s1 が該当デバイスになります。

Hypriotイメージの書き込み

flashスクリプトを実行して、(マイクロ)SDカードにHypriotのイメージを書き込みます。また、Wifi接続先のアクセスポイント等もここで指定します。 ここでは

である例を示します。 環境に応じて適宜変更してください。

# アクセスポイントのSSIDとパスワードを指定します。
# hostnameは、Raspberry Piにアクセスするときに使用したいホスト名を指定します。この場合、hypriotと指定したので、hypriot.local というホスト名でアクセスできます。(Bonjourの機能)
# zipファイルのURLは、こちらのページ (http://blog.hypriot.com/downloads/) を参照して、hypriotの最新SDカードイメージを指定します。

flash --ssid "hoge airmac" --password "xxxxxxxx" --hostname pihost http://downloads.hypriot.com/hypriot-rpi-20151115-132854.img.zip

ダウンロードページ: Downloads · Docker Pirates ARMed with explosive stuff

参考: HypriotOS: Back Again and Better then Ever · Docker Pirates ARMed with explosive stuff

実行すると、ダウンロードおよび解凍した後、dfの出力が出て、

$ flash --ssid "hoge airmac" --password "xxxxxxxx" --hostname pihost http://downloads.hypriot.com/hypriot-rpi-20151115-132854.img.zip
Using cached image /tmp/hypriot-rpi-20151115-132854.img
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
...
/dev/disk2s1 31241216 4800 31236416 1% 0 0 100% /Volumes/NO NAME
Is /dev/disk2s1 correct?

のように、Hypriotインストール先SDカードがあっているかどうかきいてきます。 たしかに合っているので y を押します。

※もし合っていなければ、中断したほうが良いです!万が一、メインのHDDがまっさらになると大ダメージですし。

引き続き、以下のようなログが出ます。

Is /dev/disk2s1 correct? y
Unmounting disk2 ...
Unmount of all volumes on disk2 was successful
Unmount of all volumes on disk2 was successful
Flashing /tmp/hypriot-rpi-20151115-132854.img to disk2 ...
Password:
1.4GiB 0:00:28 [ 51MiB/s] [==============================================================================================================>] 100%
dd: /dev/rdisk2: Invalid argument
0+22897 records in
0+22896 records out
1499955200 bytes transferred in 28.051340 secs (53471784 bytes/sec)
Set hostname=pihost
Set wifi_ssid=hoge airmac
Set wifi_password=xxxxxxxx
Unmounting and ejecting disk2 ...
Unmount of all volumes on disk2 was successful
Unmount of all volumes on disk2 was successful
Disk /dev/disk2 ejected
🍺 Finished.

完了したようですね。 せっかくなのでSDカードをMacに再度挿しなおして確認すると以下のようになってました。

f:id:hammm:20160105014532p:plain

アクセスポイント等の設定内容は、occidentalis.txt というファイルに保存されているようです。

Raspberry Piの起動とsshアクセス

Raspberry pi 2にmicro sdカードを挿し直し、USB-Wifiドングルを挿しておく。電源(USBケーブル)を入れて、20秒ぐらい?待ってから、同じLAN上のマシンのターミナルで、sshでのアクセスを試みます。

$ ssh pi@pihost.local

Are you sure you want to continue connecting (yes/no)? と聞かれたらyesを、

pi@pihost.local's password: と出たらデフォルトのパスワード raspberry を入れます。

$ ssh pi@pihost.local
The authenticity of host 'pihost.local (192.168.1.28)' can't be established.
RSA key fingerprint is ****************.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'pihost.local,192.168.1.28' (RSA) to the list of known hosts.
pi@pihost.local's password:
 
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
 
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
HypriotOS: pi@pihost in ~
$

(※ 以下はhypriot.local というホスト名の場合。pi@ を付け忘れたのでやりなおしてます(汗)) f:id:hammm:20160105014744p:plain

入れた!

入れない場合

  • Raspberry Piとsshを実行しているマシンは、同じLAN(アクセスポイント)につながっていますか?

  • 同じホスト名で、2回Raspberry Piをセットアップしませんでしたか?その場合、RSA key fingerprintが変化しているので「怪しい!」ということになります。 エラーメッセージに出ているように、known_hosts内の該当行(ホスト名が記述されている行)を削除してあげれば、新しいホストだと認識されるため、エラーがなくなります。

  • (ホスト名).local が見つからないといったエラーが出ている場合には、Bonjourが正常動作していないかもしれません。接続元がBonjourを認識するマシンか?もしWindowsの場合は、***.localというアドレスでアクセスするためには、Bonjour SDKをインストールしてあげる必要があるかもしれません。

そのほかの場合、、、状況を確認しなければなりません。 ひとまずHDMIをモニタにつないで、USBキーボードをつなぎましょう。

  • ネットがつながっているか? ping google.com と打ってping: unknown host google.com となるならつながっていない。 SSID/passwordを確認。

  • avahiが動いているか? ps aux | grep avahi | grep -v grep としてプロセスが出てくるか?指定したホスト名になっているか?

$ ps aux | grep avahi | grep -v grep
avahi 355 0.0 0.2 3772 2456 ? Ss 15:58 0:00 avahi-daemon: running [pihost.local]
avahi 356 0.0 0.0 3772 220 ? S 15:58 0:00 avahi-daemon: chroot helper

docker動かしてみる

正常にsshログインできたら、ためしに、hypriot/rpi-busybox-httpd というイメージを動かしてみます。ダウンロードと展開に多少時間がかかりますが、10分程度じゃないかと思います。

HypriotOS: pi@pihost in ~
$ docker run -d -p 80:80 hypriot/rpi-busybox-httpd
Unable to find image 'hypriot/rpi-busybox-httpd:latest' locally
latest: Pulling from hypriot/rpi-busybox-httpd
af1721be47cc: Pull complete
6ace3cef50ed: Pull complete
27616286225e: Pull complete
c7278d0bf2e2: Pull complete
Digest: sha256:c00342f952d97628bf5dda457d3b409c37df687c859df82b9424f61264f54cd1
Status: Downloaded newer image for hypriot/rpi-busybox-httpd:latest
92bd30e679fd192ac4ac375df81f361dd073cbd6e421600ae1f4460d3e161750
HypriotOS: pi@pihost in ~
$

ブラウザで http://pihost.localにつないで、以下のようにhypriotの画像が出てくれば動作しています!ちなみに、Chromeのアドレスバーに pihost.local とだけ打つと、google検索に行ってしまうので注意。

(※ 以下はhypriot.local というホスト名の場合) f:id:hammm:20160105014815p:plain

docker動作状況の確認

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
92bd30e679fd hypriot/rpi-busybox-httpd "/bin/busybox httpd -" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp cranky_northcutt
HypriotOS: pi@pihost in ~

cranky_northcuttという名前がついているようです。(dockerは名前を指定しなければ、毎回ランダムにつけてくれます)

止める

この名前を指定して止めます。

$ docker stop cranky_northcutt
cranky_northcutt

これでdockerイメージが停止しました。ブラウザからのアクセスもできなくなっているはずです。

あとはdockerhubで rpi-なんたら となっているイメージを選びたい放題というわけです!

Enjoy!

次回は、Dockerの仕組みを利用しつつ、ウェブカメラ(Theta S等)を接続して、動画ストリーミングする方法を書くはずです。書きたいなあ。