Node-RED実行環境としてHerokuの代替え先について検討してみた

# はじめに

2022年8月25日、Herokuの無料プランが廃止されると発表された。

![スクリーンショット 2022-09-12 14.41.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f2909b25-c502-fe5a-5106-c50bc9c47e32.png)

Herokuログイン後に表示されるバナー
![スクリーンショット 2022-09-13 8.17.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/df63133c-cdc5-2a3c-2f44-89867128f1d8.png)

https://jp.heroku.com/

詳細へのリンク

https://blog.heroku.com/next-chapter

# 代替え先の候補

- Render

https://render.com

- Railway

https://railway.app

- Cyclic

https://cyclic.sh

- Deta

https://www.deta.sh/

- Fly.io

https://fly.io/

- Vercel (旧:ZEIT Now)

https://vercel.com

- Koyeb

https://www.koyeb.com/

## 機能比較

|サービス |無料プラン |CPU |メモリ |Disk |時間 |非アクティブまでの時間 | その他|
|---|---|---|---|---|---|---|---|
|Heroku |Dyno Free |不明 |512MB |不明 |550時間+450時間 |30分 |クレジットカード認証で450時間追加 |
|Render　|Free |Shared |512MB |不明 |750時間 |15分 | |
|Railway  |Trial |vCPU |512MB |1GB |5$ or 500時間 |不明 | $ 0.000463/vCPU/分 | |
|Cyclic |Free Forever |不明 |1GB, アプリサイズ:250MB |512MB /tmp, 1GB S3 |100,000 API requests |実行時間:30秒 |AWS API Gateway + Lambda + S3で実装, 転送容量:10GB/月 |
|Deta |Free Forever |不明 |512MB, アプリサイズ:250MB |512MB /tmp, ストレージ:10GB |不明(制限なし？) |実行時間:10秒 |AWS API Gateway + Lambdaで実装 |
|Fly.io |Trial Plan |shared-cpu-1x |256MB |合計:3GB |3個/月 |不明 |$ 0.0000008/秒 (1.94/月), リージョン毎の転送容量:100+30+30GB/月, クレジットカード認証なしで2個まで |
|Vercel (旧:ZEIT Now)|hobby |不明 |1,024MB, 同時実行:1,000 |不明 |不明 |実行時間:10秒 |AWS API Gateway + Lambdaで実装, 転送容量:100GB/月, ビルド実行:100時間/月, デプロイ:100回/日 |
|Koyeb |Hobby |1vCPU |512MB |5GB |5$ |不明 | 1個のMICRO(1vCPU,512MB,5GB)、または、2個のNANO(1vCPU,256MB,2.4GB)|

## 結果

### OK

- Render
- Fly.io
- Koyeb

### NG (一部、OK)

- Cyclic

### NG

- Deta
- Vercel

### 調査中

なし

### 廃止

- Railway (2023/10/1 追記)

![スクリーンショット 2023-10-01 10.14.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/fda49896-2866-d848-fd67-14f4e1a4628e.png)

![スクリーンショット 2023-10-01 10.13.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/926ee157-4f7b-db06-ed86-68bf5ae9136c.png)

# 手順

### 1. package.jsonファイルを作成する

適当なディレクトを作成・移動し、package.jsonファイルを作成する。

```bash
$ mkdir 20220912 && cd 20220912
$ npm init -y
```

### 2. Node-REDモジュールをインストールする

npm installコマンドでNode-REDモジュールをインストールする。

```bash
$ npm install node-red
```

### 3. package.jsonファイルを編集する

viコマンドなどでpackage.jsonファイルを開き、"scripts"-"start"キーを追加する。

```bash
$ vi package.json
```

変更前

```json:package.json
{
  "name": "20220912",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-red": "^3.0.2"
  }
}
```

変更後

```json:package.json
{
  "name": "20220912",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node node_modules/node-red/red.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-red": "^3.0.2"
  }
}
```

### 4. package.jsonファイルをGitHubへアップロードする

サンプル

https://github.com/kitazaki/node-red-test-01

以上で準備は終わり、以降は各サービスのダッシュボード画面、コマンドで操作します。

# OK

## Render

新規にWeb Serviceを選択し、Public Git repositoryにpackage.jsonが保存されたGitHubのURLを入力します。

![スクリーンショット 2022-09-13 15.23.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/aa57fa98-cb7d-0e0b-bb50-14e549922e8f.png)

Nameの設定でユニークな名前を入力し、Start Commandの設定を「npm start」へ変更します。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f01f8fee-1e28-d861-db17-bdf78ec96b82.jpeg)

その他の設定は変更せず、「Create Web Service」ボタンを押します。

![スクリーンショット 2022-09-13 15.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/473bf846-73d2-4f94-3bad-b4273980ba35.png)

デプロイ完了後

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/adb6aa55-7843-f336-060d-56cb95ee4e00.jpeg)

Dashboard上でアクセス先のURLを確認できます。

![スクリーンショット 2022-09-13 15.28.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5cb6a06b-5040-542c-1f59-6061ce0ee684.png)

しばらく待つとNode-REDのフロー画面が表示されます。

![スクリーンショット 2022-09-13 15.35.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b501a06a-addb-1d0c-3b2d-40d54cd72a62.png)

## Railway

New Projectから「Deploy from GitHub repo」を選択します。

![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/7a2d2413-b2b8-5449-8575-523cd5f4cef8.png)

GitHub連携を済ませた後、デプロイするレポジトリを選択します。

![スクリーンショット 2022-09-13 15.37.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a1ce29b7-0dc6-e78c-6edf-c74a45a1ce48.png)

デプロイが開始され、しばらくするとステータスが「Success」に変わります。

![スクリーンショット 2022-09-13 15.37.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5eff25ae-8060-b2e2-b75c-7c2f50445160.png)

![スクリーンショット 2022-09-13 15.39.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/beb5e4a2-2c3e-0278-e898-49e1b0e0cf36.png)

「View Logs」を押すと「Build Logs」と「Deploy Logs」を確認できます。

![スクリーンショット 2022-09-13 15.42.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1e04ef74-e877-08f5-e7c7-0115f67d51f0.png)

「Settings」タブを選択し、Domainsで「Generate Domain」ボタンを押します。

![スクリーンショット 2022-09-13 15.43.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4af4ca3f-3079-9aaf-101b-79c0d08d8814.png)

しばらくすると、アクセス先のURLが作成されます。

![スクリーンショット 2022-09-13 15.44.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/7a41cb6b-2a4e-6f02-f438-be2c02bfbcf9.png)

URLへアクセスすると、Node-REDのフロー画面が表示されます。

![スクリーンショット 2022-09-13 15.46.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d2e2d3b8-7f31-3bff-1b75-ce2a1d1d98dd.png)

## Fly.io

### 1.アカウントの作成

GitHubアカウント連携、または、Eメールアドレスでアカウントを作成します。

![スクリーンショット 2022-09-19 13.07.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c9827a45-b6ad-7721-0d2f-b34ee11a7cb6.png)

### 2.flyctlツールのインストール

macOSを例に説明する。

```bash
$ brew install flyctl
```

または

```bash
$ curl -L https://fly.io/install.sh | sh
```

/usr/local/binにflyctlコマンドがインストールされる。

### 3.Fly.ioへログインする

```bash
$ flyctl auth login
```

ブラウザが開くので、Fly.ioへログインする。
コマンドを実行してSafariが起動した場合はサポートしていないので、ChromeまたはFirefoxでログインする。

### 4.アプリケーションを作成する

GitHubからpackage.jsonをcloneします。

```bash
$ git clone https://github.com/kitazaki/node-red-test-01
$ cd node-red-test-01
```

flyctl launchコマンドでアプリケーションを作成(登録)する。
いくつか質問を聞かれるので回答します。

- App Name
  アプリケーションの名前を入力する。改行すれば自動で名前が設定される。
- Select region
  複数のリージョンの中から選択します。「nrt (Tokyo, Japan)」を選択します。
- Would you like to set up a Postgresql database now?
  Postgresql databaseは使用しないので、改行します。(Noが選択されます)
- Would you like to deploy now?
  一旦、デプロイせずに終了(改行)します。(Noが選択されます)

```bash
$ flyctl launch
Creating app in /Users/kitazaki/tmp/20220919/node-red-test-01
Scanning source code
Detected a NodeJS app
Using the following build configuration:
	Builder: heroku/buildpacks:20
? App Name (leave blank to use an auto-generated name):  (←改行)
Automatically selected personal organization: kitazaki
? Select region: nrt (Tokyo, Japan)  (←上下操作でnrt (Tokyo, Japan)を選択)
Created app quiet-sunset-5366 in organization personal
Wrote config file fly.toml
? Would you like to set up a Postgresql database now? No  (←改行)
? Would you like to deploy now? No  (←改行)
Your app is ready. Deploy with `flyctl deploy`
```

同じディレクトリに設定ファイル(fly.toml)が作成される。

### 5.アプリケーションをデプロイする。

アプリケーションをデプロイする。最初のデプロイ時にビルド環境が構築されるため、構築〜ビルド完了まで時間(20分程度)が掛かる。

```bash
$ flyctl deploy
An existing fly.toml file was found for app quiet-sunset-5366
App is not running, deploy...
Deploying quiet-sunset-5366
==> Validating app configuration
--> Validating app configuration done
Services
TCP 80/443 ⇢ 8080
Remote builder fly-builder-fragrant-sound-4715 ready
==> Building image with Buildpacks
--> docker host: 20.10.12 linux x86_64
20: Pulling from heroku/buildpacks
Digest: sha256:301b9dc19959020a56bc5a5c7a506778ecc4f3b92841c1cea0bd97ed531583b6
Status: Image is up to date for heroku/buildpacks:20
20-cnb: Pulling from heroku/heroku
Digest: sha256:c233084a9a068c6526928956bfe2445ed1a7d05cc696cec089ce87c40fd99893
Status: Image is up to date for heroku/heroku:20-cnb
===> DETECTING
2 of 3 buildpacks participating
heroku/nodejs-engine 0.8.8
heroku/nodejs-npm    0.5.2
===> ANALYZING
Previous image with name "registry.fly.io/quiet-sunset-5366:cache" not found
===> RESTORING
===> BUILDING

[Heroku Node.js Engine Buildpack]

[Checking Node.js version]
Detected Node.js version range: *
Resolved Node.js version: 18.9.0

[Installing Node.js distribution]
Downloading Node.js 18.9.0
Extracting Node.js 18.9.0
Installing Node.js 18.9.0
[INFO] Installing toolbox
[INFO] - yj
[INFO] Using npm v8.19.1 from Node
[INFO] Installing node modules
npm WARN config production Use `--omit=dev` instead.

added 292 packages, and audited 293 packages in 13s

38 packages are looking for funding
  run `npm fund` for details

6 vulnerabilities (5 low, 1 moderate)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
npm notice 
npm notice New patch version of npm available! 8.19.1 -> 8.19.2
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v8.19.2>
npm notice Run `npm install -g npm@8.19.2` to update!
npm notice 

[Warning: Skip pruning because NODE_ENV is not 'production'.]

===> EXPORTING
Adding layer 'heroku/nodejs-engine:dist'
Adding layer 'heroku/nodejs-engine:web_env'
Adding 1/1 app layer(s)
Adding layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Setting default process type 'web'
Saving registry.fly.io/quiet-sunset-5366:cache...
*** Images (1af4f97aec52):
      registry.fly.io/quiet-sunset-5366:cache
      registry.fly.io/quiet-sunset-5366:deployment-01GD9ZRFDK1DTHHQRPBMPZMCR8
Adding cache layer 'heroku/nodejs-engine:dist'
Adding cache layer 'heroku/nodejs-npm:toolbox'
--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/quiet-sunset-5366]
83d85471d9f8: Mounted from icy-sound-8382 
866d7e8c299d: Mounted from icy-sound-8382 
9497805c7bd5: Mounted from icy-sound-8382 
333a2f1443d2: Pushed 
531c7b7d4790: Mounted from icy-sound-8382 
52408cad065e: Mounted from icy-sound-8382 
c4dabb6be5f0: Mounted from icy-sound-8382 
8c79cb6457ba: Mounted from icy-sound-8382 
b61e2d828315: Mounted from icy-sound-8382 
b892e318de68: Mounted from icy-sound-8382 
b40ed86654e5: Mounted from icy-sound-8382 
deployment-01GD9ZRFDK1DTHHQRPBMPZMCR8: digest: sha256:31e743f9d0f51b48e71b5a7664b774c0e1cf605eb1d83e4e3212933ceafc24fe size: 2622
--> Pushing image done
Image: registry.fly.io/quiet-sunset-5366:deployment-01GD9ZRFDK1DTHHQRPBMPZMCR8
Image size: 783 MB
==> Creating release
Release v2 created

You can detach the terminal anytime without stopping the deployment
Monitoring Deployment

1 desired, 1 placed, 1 healthy, 0 unhealthy
```

flyctl statusコマンドでアプリケーションの動作状況(ステータス)を確認できます。

```bash
$ flyctl status
App
  Name     = quiet-sunset-5366          
  Owner    = personal                   
  Version  = 0                          
  Status   = running                    
  Hostname = quiet-sunset-5366.fly.dev  
  Platform = nomad                      

Deployment Status
  ID          = cd4cd1c1-36d8-b51e-359d-36df6358f209         
  Version     = v0                                           
  Status      = successful                                   
  Description = Deployment completed successfully            
  Instances   = 1 desired, 1 placed, 1 healthy, 0 unhealthy  

Instances
ID      	PROCESS	VERSION	REGION	DESIRED	STATUS 	HEALTH CHECKS     	RESTARTS	CREATED   
bad917f0	app    	0      	nrt   	run    	running	1 total, 1 passing	0       	3m14s ago
```

### 6.ダッシュボードでアクセス先のURLを確認する

Appsにデプロイされたアプリケーションの一覧が表示されます。アクセス先のURLを確認したいアプリケーションを選択します。

![30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/78e555f6-226a-998f-cf94-39c577d6c13a.jpeg)

![31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b6f6f30f-fa1d-1373-9f46-535c9c27d0e4.jpeg)

### 7.デプロイされたサイトを確認する

手順6.で確認したアクセス先のURLをブラウザで確認します。

![40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/8f365325-6701-15ef-1530-12032aa127ad.jpeg)

## Koyeb

https://qiita.com/kitazaki/items/570a5fc359c4928473b3

# NG

いずれもAWS API Gateway + Lambda実装で、Node-REDを動かすには工夫が必要そうです。

## Cyclic

同じpackage.jsonでデプロイしましたが、うまく起動しません。

![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/dd641118-961d-576f-ebca-cd7dfdd120f3.jpeg)

![10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/2994f3ab-3744-075c-5549-c7e3029b4db6.jpeg)

### 一部、OKになるケース

Serverlessで実行時間が30秒に制限されているため、Node-REDのフローエディタを使用することはできませんが、Githubにflows.jsonを保存し、Node-REDの起動オプションでファイルを指定すれば読み込み可能で、フローを実行可能です。
また、起動オプションでユーザーディレクトリを/tmpに指定する必要があります。

```json:package.json (抜粋)
    "start": "node node_modules/node-red/red.js -u /tmp ./flows.json",
```

![スクリーンショット 2022-10-08 21.37.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/f68631c4-433b-5466-d37d-501b1d237c40.png)


フロー実行例

```bash
$ curl https://lazy-pear-chiton-ring.cyclic.app/status
{"status":"ok","message":"health endpoint"}
```

https://github.com/kitazaki/node-red-test-02

## Deta

同じpackage.jsonでデプロイしましたが、うまく起動しません。

![30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/cfd7e3c8-ea3b-6a67-abe9-780d1a5f9add.jpeg)

![10-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ae8190f6-6652-66c2-bd55-ade68430a895.jpeg)

(参考: 上手くいった事例)

https://qiita.com/kitazaki/items/b1b19aa997b6a1437f7f

## Vercel

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/a0a55685-ca0d-dc3c-b570-849b21b592cd.jpeg)

(参考: 上手くいった事例)

https://github.com/kitazaki/vercel-nodejs-test01

https://github.com/kitazaki/vercel-php-test01