enebularからGAE(Google App Engine)へデプロイする

enebularで作ったNode-REDのフローをGAEへデプロイ出来たので、その手順をまとめてみました。

# 注意  
GAEは[スタンダード環境](https://cloud.google.com/appengine/docs/standard?hl=ja)ではなく、[フレキシブル環境](https://cloud.google.com/appengine/docs/flexible/?hl=ja)になります。そのためかなり課金されます！
個人で使うのはおすすめできません・・・
※当初は無料枠があるスタンダード環境で出来ると思ったのですが、残念ながら無理でした。
　良い方法あればご教示お願いします。

# デプロイまでの手順  

1. enebularで作ったフローをjsonファイルにする
2. デプロイ用のDockerフォルダを用意する
4. gloudコマンドでデプロイする

## enebularで作ったフローをjsonファイルにする
enebularでフローを編集する前の画面で「Download Flow」というボタンがあります。それを押せばflow.jsonを取得できます。

ここで修正しなければいけないことが2つあります。
1つ目はファイル名を「flow.json」を「**flows.json**」にします。Node-REDがデフォルトで読み込むファイル名は「**flows.json**」のためです。(これに気が付かずはまりました・・・)

2つ目がフローの形式です。

enebularから取得したjsonファイルはこんな感じです。

```json:flow.json
{
  "flow": [
    {
      "id": "xxxxx",
      "type": "tab",
      "label": "フロー １",
      "disabled": true,
      "info": ""
    },
    {
      ...
    }
  ],
  "packages": {},
  "credentialIds": [
    "xxxx"
  ]
}
```

このうち"flow"の中だけにします。"packages"などは削除します。

```json:flows.json
[
  {
    "id": "xxxxx",
    "type": "tab",
    "label": "フロー １",
    "disabled": false,
    "info": ""
  },
  {
   ...
  }
]
```

## デプロイ用のDockerフォルダを用意する
GAEにはDockerをデプロイします。
フォルダには次のファイルを入れます。

flows.json
package.json
setting.js
app.yaml
Dockerfile

### flows.json
これは上記で作成したjsonファイルです。

### package.json
[github](https://github.com/node-red/node-red-docker)にあるpackage.jsonをベースにしています。
[dockerhub](https://hub.docker.com/r/nodered/node-red-docker/)によりますと、"scirpts"には"start": "node-red -v $FLOWS"と記述し、"dependencies"に使用するノードを記述します。例えば"node-red-node-email"などです。

```json:package.json(一部抜粋)
{
(省略)
    "scripts": {
        "start": "node-red -v $FLOWS"
    },

(省略)

    "dependencies": {
        "node-red": "^1.0.3"
        ここにノード名を記述する
    },
    "engines": {
        "node": ">=10"
    }
}
```

### setting.js
ポートを1880ではなく、8080を指定します。

```json:settings.js(一部抜粋) 

(省略)

module.exports = {
    // the tcp port that the Node-RED web server is listening on
    uiPort: 8080,

(省略)
}

```

### app.yaml

このファイルにはGAEの環境を記述します。

```yaml:app.yaml
runtime: custom
env: flex
service: node-red


readiness_check:
    app_start_timeout_sec: 1800

manual_scaling:
    instances: 1
```


#### runtimeとenv
カスタムランタイム、フレキシブル環境を指定します。
Node-REDはhttpでリクエストを投げています。その場合スタンダード環境では動かず、フレキシブル環境なら動くようです。
(参照)GAEの[カスタムランタイムの説明](https://cloud.google.com/appengine/docs/flexible/custom-runtimes/build#configuring_the_dockerfile)
>カスタム ランタイムでは、サポートされている任意の App Engine フレキシブル言語を別の方法で実装したり、Google が提供する言語をカスタマイズしたりできます。受信 HTTP リクエストを処理できる任意の言語でコードを記述することもできます

#### service
GAE上の任意のサービス名です。

#### app_start_timeout_sec
アップロードまでの時間がかかったので待ち時間を指定しました。

#### instances
理屈は分かっていないのですが、インスタンス数を指定しなかった場合、なぜかNode-REDが2つ起動している状態になっていました。そのためインスタンスの最大数を1に指定します。


### Dockerfile
Node-REDの公式ページ[Dockerで実行する](https://nodered.jp/docs/getting-started/docker)・[dockerhub](https://hub.docker.com/r/nodered/node-red-docker/)・[github](https://github.com/node-red/node-red-docker)を参考にしています。

まずベースイメージを"nodered/node-red:latest-minimal"にします。
(これだけデプロイしてもNode-REDが動きます。)

また["nodered/node-red"のDockerfile](https://github.com/node-red/node-red-docker/blob/master/docker-custom/Dockerfile.custom)を見てみると、"package.json"は"/usr/src/node-red"に、"settings.js"と"flows.json"は"/data"に入っています。
enebularで作成したフローを反映させたいので、ファイルを上書きします。

上記の点をまとめると以下のようになります。

```dockerfile:Dockerfile
FROM nodered/node-red:latest-minimal

# settings.js, flows.json copy to /data
WORKDIR /data
COPY settings.js .
COPY flows.json .

# package.json contains Node-RED NPM module and node dependencies
WORKDIR /usr/src/node-red
COPY package.json .
RUN npm install
```

## gloudコマンドでデプロイする
デプロイ用のフォルダまで移動して、以下のコマンドを実行すればGAEにデプロイされます。

```
gcloud app deploy --project=[プロジェクト名]
```


# まとめ

Node-REDをデプロイできたのは良かったのですが、コストの問題で使えないのは残念でした・・・
どなたかのニーズに合えば幸いです。ではでは。

# 参考URL
[Dockerで実行する](https://nodered.jp/docs/getting-started/docker)
[dockerhub nodered/node-red-docker](https://hub.docker.com/r/nodered/node-red-docker/)
[github node-red/node-red-docker](https://github.com/node-red/node-red-docker)