Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (2/3)



この記事は、[Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説の第2回目です。

* [Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (1/3)](https://qiita.com/MahoTakara/items/86c0d1072d1cd34187d5)
* [Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (2/3)](https://qiita.com/MahoTakara/items/605b1e32ddf22fb7b910)
* [Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (3/3)](https://qiita.com/MahoTakara/items/8cfa4d0be22277869084)
* [Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (番外編)](https://qiita.com/MahoTakara/items/2529c4a66519fb459e5d)


第2回目は、Node-REDをコンテナで動作させた場合、データベースなどの外部サービスの利用方法、そして、同じコンテナのサービスの接続方法について、動作を確認しましたものです。


---
# 実行環境

## Node-REDコンテナ

この記事は、DockerHub に登録したコンテナ・イメージ [maho/node-red](https://hub.docker.com/r/maho/node-red/) を利用して検証するものです。 このNode-REDのコンテナを自分用にカスタムビルドしたい人は、前述の記事「[Node-RED v1.8が動作するコンテナをビルドして Kubernetes で実行するまでを解説 (1/3)](https://qiita.com/MahoTakara/items/86c0d1072d1cd34187d5)」に記載してあります。

#### Node-REDコンテナの起動方法

```console
$ docker run -d -p 1880:1880 --name nr maho/node-red:1.0

```

#### Node-REDへのログイン方法

Dockerコンテナを動作させたパソコンやサーバー上で、http://localhost:1880/ とする事で利用できます。  ブラウザで前述のURLをアクセスすると、ユーザー名とパスワードの入力画面がでますので、ユーザー名:admin、パスワード: password をインプットするとログインできます。

![スクリーンショット 2018-03-11 17.38.49.png](https://qiita-image-store.s3.amazonaws.com/0/42829/3417e9e1-2d28-89ac-1f49-2873a488ab12.png "スクリーンショット 2018-03-11 17.38.49.png")

一回目にログインするとプロジェクト情報の説明ウィンドが表示されます。

![スクリーンショット 2018-03-11 17.39.01.png](https://qiita-image-store.s3.amazonaws.com/0/42829/89df0eaf-ec8e-4f36-925c-0afce914ac4b.png "スクリーンショット 2018-03-11 17.39.01.png")

---
# サービス利用について

旧Bluemix PaaS、 現IBM Cloud Cloud Foundryアプリケーションとして、[Node-REDボイラーテンプレート](https://console.bluemix.net/catalog/starters/node-red-starter?taxonomyNavigation=apps)をデプロイした場合、[Cloudant (Apache CouchDB)](https://console.bluemix.net/catalog/services/cloudant-nosql-db?taxonomyNavigation=app-services)が、一緒に起動します。 この場合、Node-REDとCloudantが関連づけられ、選択リストを選ぶだけで、認証情報をセットしなくても、利用できます。

しかし、Dockerコンテナとして利用する場合は、IBM Cloud のサービスを利用する場合、サーバーのDNSアドレス、ユーザー名、パスワード等を設定する必要があります。 この章では、IBM Cloudの [Cloudant (Apache CouchDB)](https://console.bluemix.net/catalog/services/cloudant-nosql-db?taxonomyNavigation=app-services)を利用するケース、DockerHubの[Cloudantコンテナ](https://hub.docker.com/r/ibmcom/cloudant-developer/)を利用する二つのケースについて記載します。 いづれも最初の一回実行するだけですから、大きな手間にはならないと思います。




## パブリック・クラウド IBM Cloud Cloudantの利用

IBM Cloud [Cloudant](https://console.bluemix.net/catalog/services/cloudant-nosql-db?taxonomyNavigation=app-services) の無料で利用できるLiteプランをオーダーして、Cloudantのインスタンスを開始します。

次に、このインスタンスの「サービス資格情報」のメニューを選択して、「サービス資格情報の表示」をクリックして、"host"、"username"、"password" の3項目の値を Node-REDのCloudantノードにインプットします。

![スクリーンショット 2018-03-11 18.19.28.png](https://qiita-image-store.s3.amazonaws.com/0/42829/e12dd9ac-b6e3-f6d8-155a-da2c8c12f412.png "スクリーンショット 2018-03-11 18.19.28.png")

具体的な画面操作としては、Cloudantのアイコンをフローエディタ上において、ダブルクリックします。すると、次の様なプロパティ画面が表示されます。 Serverの入力欄に Add New Cloudant... と表示された右側に「えんぴつ」アイコンがあります。このアイコンをクリックすると、次にサーバーのホスト名、ユーザー、パスワードを入力する画面に遷移します。 

![スクリーンショット 2018-03-11 18.12.15.png](https://qiita-image-store.s3.amazonaws.com/0/42829/4a629845-efd4-770b-70e6-a8879388f4ed.png "スクリーンショット 2018-03-11 18.12.15.png")

ここで、前述の「サービス資格情報」から３項目をコピペしてインプットします。ホスト名の部分は、`https://ホスト名/` の様式で設定します。 

![スクリーンショット 2018-03-11 18.13.16.png](https://qiita-image-store.s3.amazonaws.com/0/42829/0abe5d2a-51aa-12df-fd5e-1e07de1923bd.png "スクリーンショット 2018-03-11 18.13.16.png")


#### 注意
Docker-CEの初期設定により、外部サービスへアクセスが禁止されている場合は、解除する必要があります。アクセスに際して、ポップアップ・ウィンドが表示されますので、外部サービスのアクセスに許可を与えてください。



## ローカルDockerコンテナのCloudantの利用

[Cloudant Dockerコンテナ](https://hub.docker.com/r/ibmcom/cloudant-developer/)の場合でも、ホスト名、ユーザー、パスワードを利用する事が同じですが、取得方法が少し変わります。


### Cloudant コンテナの起動

`--link`を利用する事で、IPアドレスではなくコンテナ名で接続できるのですが、Node-REDで開発するに祭して、必要なノードを後から、どんどん追加できるという特色があります。 この良い点を損なわない様に、Cloudantのコンテナを後から追加して、サービスとしてアクセスする方法をみていきます。

Node-REDのコンテナが起動している状態で構いませんので、次のコマンドで、Cloudantのコンテナを起動します。 そして、起動したら、コンテナのIPアドレスを調べます。 

下記の`-v cloudant:/srv` は、cloudantという名前で、Dockerの永続ボリュームが作成されます。 削除方法は、前述の[Cloudant Dockerコンテナ](https://hub.docker.com/r/ibmcom/cloudant-developer/)にあります。


```console
$ docker run -d -v cloudant:/srv --name cd -p 8080:80 --hostname cloudant.dev ibmcom/cloudant-developer
Unable to find image 'ibmcom/cloudant-developer:latest' locally
latest: Pulling from ibmcom/cloudant-developer
93857f76ae30: Pull complete 
408f81289ebf: Pull complete 
16348085d9a4: Pull complete 
5d3c4197f44c: Pull complete 
1089e1c45c55: Pull complete 
5648181a1269: Pull complete 
Digest: sha256:5ef613e12eb96220be4b2db43d9e644f4abc712d841c5376385836e894b78bbf
Status: Downloaded newer image for ibmcom/cloudant-developer:latest
2fddf73a276d5db1cb24e23b0307a20c7c1380d2c2ac7417539ac6c466f034c4
```


### コンテナのIPアドレスと認証情報設定

`--name cd` としてCloudantのコンテナ名を `cd` としましたので、下記の様にして、このコンテナのIPアドレスを取得できます。

```console
$ docker inspect cd --format '{{ .NetworkSettings.IPAddress }}' 
172.17.0.3
```

Node-REDのCloudauntノードをダブル・クリックして、ホスト名の入力フィールドに、上記で調べたIPアドレスをセットします。 IPアドレスは `http://172.17.0.3` の様式でインプットします。
ユーザー名とパスワードは、[Cloudant Dockerコンテナ](https://hub.docker.com/r/ibmcom/cloudant-developer/) に記載されていて、username: admin, password: pass をインプットします。



![スクリーンショット 2018-03-11 20.16.47.png](https://qiita-image-store.s3.amazonaws.com/0/42829/50688be3-0126-80fb-f831-8811d1bbe2a8.png "スクリーンショット 2018-03-11 20.16.47.png")


以上で、パブリック・クラウドであるIBM Cloud のサービスの一つである Cloudant のサービスを、Dockerコンテナ上のNode-REDからアクセスする方法、及び、CloudantのDockerコンテナにアクセスする方法を確認しました。



## MySQLコンテナののセットアップ

次は、[MySQLサーバーのコンテナ](https://hub.docker.com/_/mysql/)を起動して、Node-REDのフローから書き込める様にします。

### MySQLコンテナの起動

次のコマンドで、[MySQLサーバーのコンテナ](https://hub.docker.com/_/mysql/)を起動します。

```console
docker run --name ms -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=testdb1 -d mysql:5.7
```

こちらは、-v オプションを設定していないので、このコンテナを設定していないので、コンテナを削除すると、データベースの内容も消去されます。 -v オプションを設定する場合、`-v mysql:/var/lib/mysql`として、永続ボリュームにMySQLのデータベース領域がマウントされる様にします。 




### MySQLサーバーへ接続して、テーブル作成

下記のdockerコマンドを実行する事で、MySQLクライアントのコンテナを起動して、前述で立ち上げたMySQLサーバーへログインすることができます。 ログイン後に、テスト的にデータをインサートするテーブルを作成します。

```console
docker run -it --link ms:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'
```


ログインができたら、データベースを選択、テーブルを作成します。

```console
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| testdb1            |
+--------------------+
5 rows in set (0.00 sec)

mysql> use testdb1
Database changed
mysql> show tables;
Empty set (0.00 sec)

mysql> CREATE TABLE payload (id MEDIUMINT NOT NULL AUTO_INCREMENT, msg CHAR(30) NOT NULL, PRIMARY KEY (id) );
Query OK, 0 rows affected (0.01 sec)

mysql> show tables;
+-------------------+
| Tables_in_testdb1 |
+-------------------+
| payload           |
+-------------------+
1 row in set (0.00 sec)
```



## Node-REDのMySQLノードを設定して、テーブルへの挿入を確認

MySQLのテーブルのセットアップが完了したので、フローエディタに、MySQLノードを置いて、ダブルクリックして、プロパティ・ウィンドを表示します。

![スクリーンショット 2018-03-11 20.53.05.png](https://qiita-image-store.s3.amazonaws.com/0/42829/f1dc7382-2f33-6999-a125-00b878aa7311.png "スクリーンショット 2018-03-11 20.53.05.png")

hostに設定するIPアドレスは、以下のコマンドで取得します。 ユーザーにroot、パスワードはコンテナ起動時に設定したパスワードをインプットします。

```console
imac:Node-RED maho$ docker inspect ms --format '{{ .NetworkSettings.IPAddress }}' 
172.17.0.4
```

Node-REDコンテナからMySQLコンテナへの接続設定が完了したら、MySQLのpayloadテーブルへインサートするためのSQL文を ファンクション・ノードに書いて、接続します。 下の図のhub-functionノードの後続に、ファンクションノードを追加します。

![スクリーンショット 2018-03-11 20.34.08.png](https://qiita-image-store.s3.amazonaws.com/0/42829/78f1ef79-e6ba-ab20-90c0-5f8198626322.png "スクリーンショット 2018-03-11 20.34.08.png")


このファンクションノードには、[Node-RED ライブラリ node-red-node-mysql 0.0.16](https://flows.nodered.org/node/node-red-node-mysql)に記載される内容にしたがって、msg.topicにSQL文を設定します。 

~~~node.js
// MySQLへINSERTするSQL文 
msg.topic = "INSERT INTO payload(msg) VALUES (" + msg.payload.toString() + " ) "
return msg;
~~~


これまでの設定で、TimeStampノードをクリックする事で、タイムスタンプの文字列をpayloadテーブルへ書き込む様になります。 


![スクリーンショット 2018-03-11 22.19.24.png](https://qiita-image-store.s3.amazonaws.com/0/42829/6f9c3e86-27a1-01f5-90ad-d37f2d72676c.png "スクリーンショット 2018-03-11 22.19.24.png")


上記の画面で、TimeStampノードをクリックした結果は、以下の様にテーブルに書き込まれます。


```console
mysql> select * from payload;
+----+---------------+
| id | msg           |
+----+---------------+
|  1 | 1520768583015 |
+----+---------------+
1 row in set (0.01 sec)

mysql> 

```

## Node-REDコンテナでRESTサービスを構築

### HTTPリクエストを受けて応答を返すフロー

HTTPリクエストを受けて、応答メッセージを返すには、次の様に、HTTPを受けるノード、HTTPレスポンスを返すノードの間に、処理ノードを挟みます。 処理ノードにワトソンAPIや様々な処理に置き換える事で、RESTサービスとして完成させる事ができます。

![スクリーンショット 2018-03-11 22.22.25.png](https://qiita-image-store.s3.amazonaws.com/0/42829/81d0f028-6a3d-337a-14c5-69e77b173b92.png "スクリーンショット 2018-03-11 22.22.25.png")


それぞれのノードを見ていきます。

### HTTPリクエストの受けるノード

Get_Requestをダブル・クリックする事で表示されるノードのプロパティです。 以下の設定によって、HTTP の GETメソッド で /recv にアクセスされた時に、このフローがコールバックされる事になります。

![スクリーンショット 2018-03-11 22.23.01.png](https://qiita-image-store.s3.amazonaws.com/0/42829/582dd652-6ba4-afd1-4a53-bacf85dec3a7.png "スクリーンショット 2018-03-11 22.23.01.png")

### ファンクション・ノード

ここでは簡単に、msg.payload に "Hello World"の文字列をセットして 次のHTTP応答ノードへ渡します。

![スクリーンショット 2018-03-11 22.23.21.png](https://qiita-image-store.s3.amazonaws.com/0/42829/c4d2eea5-c448-bfe7-6990-9d3697fabaaf.png "スクリーンショット 2018-03-11 22.23.21.png")



### HTTP応答ノード

この応答ノードでは、応答するHTTPヘッダーとステータスを指定する事ができます。

![スクリーンショット 2018-03-11 22.32.27.png](https://qiita-image-store.s3.amazonaws.com/0/42829/d11e9830-df95-8828-daa0-9ec602758c7a.png "スクリーンショット 2018-03-11 22.32.27.png")



### 応答結果

コンテナが開いている 1880ポートで、"/recv" にアクセスする事で、コールバックが実行され、以下のレスポンスを得る事ができます。

```console
imac:~ maho$ curl -v http://localhost:1880/recv
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 1880 (#0)
> GET /recv HTTP/1.1
> Host: localhost:1880
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: text/plain; charset=utf-8
< Content-Length: 11
< ETag: W/"b-Ck1VqNd45QIvq3AZd8XYQLvEhtA"
< Date: Sun, 11 Mar 2018 13:36:19 GMT
< Connection: keep-alive
< 
* Connection #0 to host localhost left intact
Hello World
```

---
# まとめ (2/3)
Node-REDのコンテナと他のコンテナを連携させる方法、そして、RESTサービスの雛形について、動作を確認しました。 
最初に、必要なコンテナする際に、docker コマンドの --link 設定を利用してコンテナを関連づける事で、コンテナ名でアクセスできる様になります。また、Docker-Composeでコンテナの連携関係を設定する事で、IPアドレスを直接設定しなくても、良くなりますが、Node-REDでアイデアを練りつつコードを足して行く場合、後から後から、サービスやコンテナを追加できる事が重要です。

そこで、今回、コンテナがデプロイされた際のIPアドレスを調べて利用する事で、後から追加されたコンテナとも連携できる様な方法を検証しました。

次回は、インターネット上のKubernetesクラスタで無料のライト・プランで実行する方法を検討します。