Raspberry PiでDockerコンテナを動かす

いまさらながら、Raspberry Pi 2を買ってみました。

しばらく、オフィシャルOSのRaspbianをインストールして遊んでいましたが、Raspbery Pi 2にDockerを導入してみたくなったのでやってみました。

以下では、Raspberry Pi 2をDocker導入済みのimageで起動し、hubotをDockerコンテナとして動かしてslackに接続してみます。

参考

概要

まず、Raspberry Pi 2におけるDocker利用可否については、[Raspberry Pi]ラズパイ2でDockerコンテナを実行する に詳しくまとめられています。

ポイントは以下のとおりです。

  • Hypriot Docker Imageを導入することで手軽にdockerを利用可能
  • しかし、armv7アーキテクチャのRaspberry Piでは一般的なx86_64のDockerイメージを利用できない

また、この記事が書かれた以降に、Hypriot Docker Image および、専用のDockerパッケージがアップデートされ、現状では、ラズパイ上で docker 1.8.0-rc3 を使うことができます。

Hypriot Docker Image でラズパイを起動する

イメージファイルをダウンロードし、microSDに書き込みます。

Hypriotのサイトの記事 Getting started with Docker on your Raspberry Pi に、Windows / OS X / Linux、それぞれの導入手順について詳しく書いてあります。

以下では、Mac OS X で実際に導入した手順を紹介します。

1. microSDのデバイス名を確認

まず、MacにmicroSDを挿入し、接続されているデバイス名を確認します(microSDはPNY製の64GBのものを使いました)

microSDが/dev/disk2として認識されていることが分かります。

2. microSDをアンマウント

microSDにイメージを書き込むための準備として、microSDをアンマウントします。

アンマウントしてもmicroSDは挿したままにしておきます。

3. イメージのダウンロード

microSDに書き込むHypriot Docker Imageをダウンロードします。
最新は Version 0.5 (beta) となっていますが、手元では3回ほど試しましたがうまく起動しないため Version 0.4 をダウンロードして展開します。(COMMUNITYを見るとイメージを修正してるような書き込みがあるので、近日中に修正されそうです)

これで、ディレクトリに hypriot-rpi-20150416-201537.img が作成されます。

4. イメージの書き込み

展開したイメージをddコマンドで書き込みます。

ifに書き込むイメージファイル名を指定し、ofに書き込み先のmicroSDのデバイス名を指定します。
(注:指定するデバイス名のdiskの前にrを付けます /dev/disk2 なら /dev/rdisk2 )
bs=1mはイメージを書き込む際のブロックサイズを指定しています。

ofは、各自のデバイス名に読み替えて実行してください。

書き込みには結構時間がかかりました。書き込みが終わるまでターミナルの表示が変化しないため動いてるのか不安になりますが落ち着いて待ちます。自分の場合は10分ちょっとかかりました。

書き込みが終わったあとに再度microSDをアンマウントし取り外します。

5. 起動

イメージの書き込みが終わったら、ラズパイに挿して起動してださい。Hypriot Docker Image は、起動するとDHCPでIPアドレスを取得します。初期ユーザ名は root、パスワードは hypriot です。

キーボードとHDMIを接続して画面を見ながらログインしてもいいし、取得したIPアドレスを調べてSSHログインしてもよいです。

さっそくDockerをつかってみる

Hypriot Docker Imageを起動して、ログインできたら、さっそくDockerを使ってみます。

ラズパイに振られたIPアドレスが192.168.1.20であれば、ブラウザからhttp://192.168.1.20:80/にアクセスするとこんな画面が見えます。

using-docker-on-raspberry-pi

簡単ですね!

ラズパイでhubotのコンテナを起動する

以降では、拙作ですが、ラズパイ上で動かすために調整したhubotをDockerfile含めて用意しましたので、これを使って解説します。
(x86_64環境では動作しないのでご注意ください)

1. ソースの取得

GitHubから knjcode/rpi-hubot-docker-template をクローンします。

2. Dockerのコンテナイメージをビルドする

ソースをクローンしたディレクトリにてイメージをビルドします。

このDockerイメージは hypriot/rpi-node を元にビルドします。
hypriotのみなさんは、OSのイメージだけでなく、node, iojs, python, java, golang等、様々な環境をarm用にビルドしてくれています。大変ありがたいですね。

3. ローカルで起動

まずは、ローカルでhubotを起動します。

無事に動きました。このイメージはコマンドなしで起動すると、shellアダプタを呼び出すようにしてあります。

4. hubotをslackに接続

次に、hubotを起動してslackに接続します。

まず、slackのhubot用トークンをHUBOT_SLACK_TOKEN環境変数に設定します。

次に、コンテナ起動時のコマンドとしてslackを指定すると、slackアダプタでhubotが起動します。

無事slackに接続できました。

5. 外部からhubotへアクセス

外部からhubotにアクセスしたい場合には、EXPOSEされている8080ポートをホストの適当なポートに割り当ててください。

5000番ポートからhubotにアクセスしたい場合は以下のとおりです。

ちなみに、最近のhubotのslackアダプタはwebsocketでslackに接続するため、hubot自体に接続する必要がなければ、ホスト側にポートを割り当てなくても大丈夫です。

6. hubotの自動再起動

slack等の外部サービスに接続している場合に多いのですが、hubotとslack間の通信が一定時間途絶えるとhubotが落ちてしまいます。そんなときのためにコンテナの再起動オプションを指定しておきます。コンテナ停止時の挙動はdockerのrestartオプションで以下のように制御できます。

--restart=alwaysを指定すると、コンテナの終了コードを問わず再起動を試みます。

補足

その他、Hypriot Docker Image を使う際の補足です。

dockerのバージョンを上げる

今回導入したイメージには、初期状態で docker 1.6.0 が入っていましたが、
hypriotのwebサイトには、Raspi用にカスタムビルドしたdockerのパッケージがおいてあります。ここです

現在の最新はDocker 1.8.0-RC3で、以下のようにdpkgコマンドで導入して利用可能です。

Logging driver に fluentd を使う

docker 1.8.0 からは、Logging driver に fluend が利用できるので便利です。

hubot起動時に以下のように指定すると、外部サーバに起動している fluend(192.168.1.10:24224)にログを送信できます。

fluentd の Logging Driver については、Docker の Logging driver に fluentd が組み込まれるということでリリースを待ちきれずに試してみたメモ にて細かく解説されています。

dockerのラッパーツールの fugu を使う

mattes/fugu

fuguというdockerのラッパーツールを日頃便利に使っています。docker-composeは複数コンテナを管理するような用途に、fuguはコンテナ単体での利用に向いています。使い方もdocker-composeと同様ですが、fugu.ymlにdockerコマンドのオプションと似たような内容を書いて使います。

fuguはlog-driverオプションに対応していなかったのですが、fluentdのLogging Driverを使いたかったので実装してプルリクを出したところマージしてもらえました。

また、fuguはgoで実装されているので、armv7用にコンパイルすることでラズパイ上でも使えます。

自前でコンパイルしたものをこちらに置いてますので、よかったら使ってください。

以下のように、ラズパイに導入できます。

おわりに

ARMアーキテクチャということで、大量にあるx86_64のDockerイメージが使えないというデメリットはありますが、hypriotのラズパイ用イメージを使うだけでも色々と遊べそうです。

まだ、4日ほどしか運用していませんが、hubotについては問題なく動いているように感じます。今後、hubotとラズパイ用の各種センサとを組み合わせてみるのも面白そうです。

また、あまり重いアプリでなければ、ラズパイにコンテナとして起動しておけば、低消費電力で場所も取らず便利です。Node.js以外にも、いろいろと使ってみて、ノウハウがたまれば共有しようと思います。