docker

IoTの心強い味方!MQTTブローカーのクラスターをDocker+eMQTTで構築

「MQTTブローカーを使いたいからDocker上でクラスター組んどいて」
フロントエンドエンジニアの僕は言ってることの意味がすべてわからず無事死亡。
Dockerはハンズオンで触ったことある程度だったのでMQTTの概念の理解からDockerコマンドに慣れるまで非常に苦戦した。

MQTTはいわゆるPUB/SUB型のメッセージプロトコル

mqtt.png

HTTP は片方向なので、クライアントが接続を開始しなければならないが、MQTTは非同期メッセージング・プロトコルなので デバイスまたはセンサーがネットワークから受動的にコマンドを受信できる。また、非常に軽量なので、センサーが沢山あって、細かいデータがバンバン飛んでくるIoT アプリケーションなどに適している。

クライアントは特定のトピックに属するメッセージをパブリッシュするために、メッセージとトピックをブローカーに送信し、ブローカーは、そのトピックにサブスクライブしているすべてのクライアントにメッセージを転送してくれる。

ここが詳しい。IBMが出してる記事
MQTT の基本知識

早速使ってみる

今回はeMQTTを使う。eMQTTはElrang/OTPで実装されたオープンソースのMQTTブローカー。こいつを使って今回はMQTTクラスターをDocker上で組んで見る
ちなみに公式ドキュメントはここ
emqx-docs

先ずはDockerでMQTTコンテナ作成

$ brew install docker
$ docker -v
Docker version 18.03.0-ce, build 0520e24

eMQTTの圧縮ファイルを書きサイトからダウンロード
2018/4/10現在ではバージョンは2.3.6だった
http://emqtt.com/

そして解凍

$ unzip emqx-enterprise-docker-v2.3.6.zip

そしてイメージをロード

$ docker load < emqx-enterprise-docker-v2.3.6

イメージができているか確認

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
emqttd-docker-v2.3.6   latest              c27b8c216b3d        2 weeks ago         78MB

そしてコンテナ立ち上げ

$ docker run -tid --name emq1 -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqttd-docker-v2.3.6

これでMQTTブローカーが動いている。
Web Dashboardでブラウザ上でも状況が確認できる
http://localhost:18083/

クラスターを組む

docker-mqtt.png

さて、ここから上のようにクラスターを組んでいく。故にクラスターを組む相手のMQTTブローカーをもう一つ立てる。
ポートはそのままだと前に立てたコンテナとかぶるのでずらしてマッピング

$ docker run -tid --name emq2 -p 2883:1883 -p 9083:8083 -p 9883:8883 -p 9084:8084 -p 28083:18083 emqttd-docker-v2.3.6

これで二つのMQTTが立ち上がった。dockerコンテナの中に入って中身確認。

$ docker exec -it emq2 /bin/sh
$ ls
bin         erts-9.1.5  hook_lua    log         start.sh
data        etc         lib         releases

設定などはetc/に、実行バイナリはbin/に入っている
クラスタを組むのでnodeの名前を確認する。node.nameはetc/emq.confで確認できる。

vi etc/emq.conf

このファイルの149行目らへんのnode.nameがそのままnodeの名前。これをコピーなりして覚えておこう。ちなみにこれはDashBoardからも確認できる
http://localhost:18083/

Dockerコンテナを停止させずにコンテナから出るときはCtr+pqで出れる。

更にちなむとコンテナ立ち上げる際にnode.nameの指定も可能。下の通り-eオプションを使う。これでいろんな指定ができるので公式ドキュメントを見るといい。これはnode.name=emq@172.31.1.1の設定で立ち上げる例

docker run -tid --name emq3 -e EMQ_NODE_NAME="emq@172.31.1.1" -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqttd-docker-v2.3.6

そしてemq2のコンテナに入ってemq1とクラスターを組んで見ましょう

$ docker exec -it emq2 /bin/sh
$ cd bin
$ emqttd_ctl cluster join <emq1のnode.name>
$ emqttd_ctl cluster status
Cluster status: [{running_nodes,['<emq21のnode.name',
                                 '<emq20のnode,name>']}]

これでクラスタが作れた。emqttd_ctl cluster statusでクラスタの確認。emqttd_ctl cluster leaveでクラスター解除ができる。ちなみに、DashBoardでも確認できる。1度コンテナを停止してから立ち上げても、ちゃんとクラスタ状態を維持してた。
細かいDockerコマンドはここのサイトがよくまとまっている

Dockerでよく使うコマンドまとめ

最初にダウンロードしたzipやローカル確認用のコード(Ruby)はGitHubにあげてます。
https://github.com/po3rin/eMQTT-client-Ruby

今後はこれをECSにあげるやつやってく。