Bluemix IBMコンテナ ibmnode をテンプレートに チャットアプリのコンテナを作成する

BluemixのNode.jsのIBM(Docker)コンテナを作成しても、それだけでは Bluemix上で動作しません。なぜなら、テンプレート用に提供されているからなんです。 そこで、このテンプレートを利用して、チャット・アプリケーションが動作するコンテナ・イメージを作成して、Bluemix上で実行した時の記録です。

![スクリーンショット 2017-02-05 17.43.31.png](https://qiita-image-store.s3.amazonaws.com/0/42829/2f505388-b430-116e-1cf8-6f5f1b863c2a.png)


# 前提条件
ibmnodeテンプレートを ローカルのDocker環境でビルドして、Bluemix のリポジトリに登録する作業となります。この作業のために、以下に列挙する環境が整備されている必要があります。

* ローカル環境として、Ubuntu 14.04 以降の Ubuntu Linuxが動作している
* 同環境に cfコマンド、bluemixコマンドが導入されている。
* 同環境に dockerが、インストールされている。

Mac や Windows パソコンの上に、上記環境を導入することも可能ですが、自己のPCは出来るだけクリーンな環境を保てる様にするために、vagrant と Virtual BOX　を利用した環境を提案します。 この環境構築の手順として、[IBM Container に Vagrant からログインする設定 忘備録](http://qiita.com/MahoTakara/items/3dd8e717fe51b49ad3e7) を参考にしてください。


# ウェブ・チャットアプリケーション

コンテナ上で動作させるアプリケーションの概要を以下の図に表します。 チャットアプリは、ブラウザ上のJavaScript と サーバー上の Express.js のアプリケーションです。
![スクリーンショット 2017-02-05 18.24.11.png](https://qiita-image-store.s3.amazonaws.com/0/42829/9091b5e6-25f9-c314-16ef-00308153f034.png)

クライアント側のプログラムは、HTMLに埋め込まれたJavaScriptとして配信します。また、サーバー側プログラムは、Node.jsのフレームワーク Express.js で 前述のHTMLを配信して、WebSocketで受信したメッセージを全クライアントに同報送信するものです。

* [クライアント・サイドのコード](https://github.com/takara9/docker_chat/blob/master/websocket_chat/index.html)
* [サーバー・サイドのコード](https://github.com/takara9/docker_chat/blob/master/websocket_chat/app.js)

図中の実行環境として、IBM (Docker) コンテナを利用します。


# コンテナのビルド用ファイル Dockerfile

ここから 図１の実行プログラムを含む Docker コンテナを作成していきます。 必要なファイル群は[https://github.com/takara9/docker_chat](https://github.com/takara9/docker_chat)にありますが、要点についてコメントしていきます。

Dockerイメージをビルドするために利用するDockerfileです。 FROM節にある registry.ng.bluemix.net/ibmnode は、Bluemix の Dockerコンテナのリポジトリーです。 この文字列の末尾部分から、Bluemix の コンテナ の ibmnode をテンプレートにしていることが、解ると思います。 次に、ADD は、GitHub https://github.com/takara9/docker_chat にある websocket_chat ディレクトリの内容を Dockerコンテナ上の /chat ディレクトに置きます。 EXPOSE 3000 は、外部に公開するポート番号です。 そして、CMD から始まる行が実行されることで、コンテナが継続して実行され、外部からのアクセスを処理できる様になります。

~~~ shell:Dockerfile
FROM registry.ng.bluemix.net/ibmnode
ADD ./websocket_chat /chat
ENV NODE_ENV production
EXPOSE 3000
CMD ["node", "/chat/app.js"]
~~~

参考までに、このDockerfileでビルドされた コンテナ・イメージにログインして、psコマンドで確認すると、以下の様に、唯一の常駐プロセスが、node /chat/app.js である事がわかります。

~~~
root@instance-002cd0b0:/chat# ps -ax
    PID TTY      STAT   TIME COMMAND
      1 ?        Ssl    0:00 node /chat/app.js
     16 ?        Ss     0:00 /bin/bash
     33 ?        R+     0:00 ps -ax
~~~

# コンテナのビルド

(1) GitHubから本コードをクローンして、ディレクトリをwebsocket_chatへ移動します。

~~~
# git clone https://github.com/takara9/docker_chat
# cd docker_chat/websocket_chat
~~~

(2) package.json に定義されたパッケージをインストールします。

~~~
# npm install
~~~

(3) Cloudant のサービス資格情報を取得して、websocket_chat/cloudant_credentials.json を更新します。

(4) ローカルの環境に docker イメージをビルドします。　dockerが未インストール場合は、apt-get install docker.io を予め実行しておきます。

~~~
# cd ..
# docker build -t mynode:node1 .
~~~

# Bluemix のリポジトリーへ登録

(5) 自己のアカウントのネームスペース名を取得します。

~~~
# cf ic namespace get
takara_node
~~~

(6) 先に作成した docker イメージにタグを付けます。

~~~
# docker tag mynode:node1 registry.ng.bluemix.net/takara_node/mynode1
~~~

(7) ローカルで作成した docker イメージをBluemix のリポジトリに PUSH します。

~~~
# docker push registry.ng.bluemix.net/takara_node/mynode1
~~~

(8) 完了したら、以下のコマンドで登録された事を確認できます。

~~~
# cf ic images
REPOSITORY                                    TAG                 IMAGE ID            CREATED             SIZE
<中略>
registry.ng.bluemix.net/takara_node/mynode1   latest              54c09e04680e        3 minutes ago       190.9 MB
~~~

# Bluemix上で Dockerコンテナを起動

(9) Bluemixのリポジトリから、Bluemix IBMコンテナとして、コンテナを起動します。

~~~
# cf ic run -p 3000 --name mynode1 registry.ng.bluemix.net/takara_node/mynode1:latest
183a6898-cd39-457e-baf4-4ee7a7348761
~~~

(10) 起動の確認とコンテナIDを取得します。

~~~
# cf ic ps
CONTAINER ID        IMAGE                                                COMMAND             CREATED             STATUS                        PORTS               NAMES
183a6898-cd3        registry.ng.bluemix.net/takara_node/mynode1:latest   ""                  39 seconds ago      Shutdown (-1) 6 seconds ago   3000/tcp            mynode1
~~~

(11) 起動したコンテナ用に、パブリックIPアドレスをリクエストします。

~~~
# cf ic ip request
OK
The IP address "169.**.**.***" was obtained.
~~~

(12) パブリックIPアドレスを コンテナに結び付けます。

~~~
# cf ic ip bind 169.**.**.*** mynode1
OK
The IP address was bound successfully.
~~~

コマンドからコンテナを起動したのですが、Bluemixのコンソールにも表示されています。
![スクリーンショット 2017-02-05 20.17.22.png](https://qiita-image-store.s3.amazonaws.com/0/42829/a3ef9b8b-28ea-766a-ec64-6de644d49225.png)


# 動作テスト

これで外部からアクセスできる様になりましたので、ブラウザから http://169.**.**.***:3000/ へアクセスします。　複数のブラウザでメッセージが共有されてれば、デプロイ成功です。

![スクリーンショット 2017-02-05 20.21.48.png](https://qiita-image-store.s3.amazonaws.com/0/42829/f456eee1-e046-8c20-4d66-6d4c64ce8c03.png)

# コンテナにログインする方法
以下のコマンドで、コンテナのIDを確認する

~~~~
# cf ic ps
CONTAINER ID        IMAGE                                                COMMAND             CREATED             STATUS                  PORTS                          NAMES
26dba932-cc4        registry.ng.bluemix.net/takara_node/mynode1:latest   ""                  7 minutes ago       Running 3 minutes ago   169.**.**.***:3000->3000/tcp   mynode1
~~~~
コンテナIDを指定して、bashでログインする

~~~
# cf ic exec -i -t 26dba932-cc4 /bin/bash
root@instance-002ce9d3:/# 
~~~