Elastic Beanstalkで、Node.js+expressアプリを動かそう [ハマりポイント説明]

#注意
本内容は、Beanstalkのプラットフォームが。「Amazon Linux AMI Node.js プラットフォームバージョン」以前向けの内容です。
2020/05以降は、「Amazon Linux 2 のプラットフォームバージョン」になりますので、本内容は対象外になります。

#🔶 はじめに
Lambdaの方が使い勝手がいいので、あまり使わないElastic Beanstalkですが、いざ使おうと思うと、いくつか躓くポイントがあるので、その点も含めて、Node.js+expressで作ったサンプルアプリを動かすまでの手順を紹介します。

##🔷 Elastic Beanstalk
https://aws.amazon.com/jp/elasticbeanstalk/
Java、.NET、PHP、Node.js、Python、Ruby、Go、Dockerなどで作られたプログラムをデプロイ、実行する環境。
実態としては、EC2の上にApacheやNginx等のサーバーを立てて提供してくれる。

#🔶 作業手順
大きくは以下の手順になります。

1. Node.js+expressでアプリを用意する。
2. ソースコード+node.jsモジュールをZIPファイルにまとめる。
3. Elastic Beanstalk実行環境構築、デプロイ。
4. 実行。

##🔷 Node.js+expressでアプリを用意する
今回は、`express myapp`コマンド作成される、サンプルアプリを使います。
ゴールとしては、Elastic Beanstalkにデプロイして、以下の画面が表示する事です。

<img width="646" alt="スクリーンショット 2019-12-25 2.34.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/d215f410-8902-b641-a97b-5efea76b80d0.png">

アプリの生成手順の詳細は以下を参照してください。

参考：[Node.js + ExpressでREST API開発を体験しよう for Windows［準備編］](https://qiita.com/tamura_CD/items/98bbd4a3143da960faf5#-%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E9%9B%9B%E5%BD%A2%E3%81%AE%E7%94%9F%E6%88%90)


###✅ ポイント1 : アプリ起動時のポート番号の変更

myappプロジェクトを生成したら、binフォルダ配下のwwwファイルを開き、以下のようにアプリ実行時のポート番号を、デフォルトの3000番から8081番に修正する。

```js:bin/www
#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('myapp:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

// var port = normalizePort(process.env.PORT || '3000'); ←３０００ポートは使えない
var port = normalizePort(process.env.PORT || '8081'); // 起動時のポートを8081に変更
app.set('port', port);
```
Beanstalk環境のnginxは、デフォルトでアプリケーションの8081ポートへリクエストを転送するので、上記のように変更する必要があります。

参考：[プロキシサーバーを設定する](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/nodejs-platform-proxy.html)

##🔷 ソースコード+Node.jsモジュールをZIPファイルにまとめる

Beanstalkのデプロイパッケージは、ソースコードに必要なNode.jsモジュールをインポートして、ZIPファイルにまとめて作成します。


###✅ ポイント２ : Linux環境で`npm install`を実行する

まず、Lambdaのトピックですが、以下のように紹介されています。

>注意: ほとんどの Node.js モジュールはプラットフォームに依存しませんが、一部のモジュールは特定のオペレーティングシステム環境に対してコンパイルされます。Lambda は、Linux 環境で動作します。npm でモジュールをインストールする場合、zip ファイルを Linux 環境で構築して、正しいプラットフォームに対する依存関係が必ず含まれるようにすることをお勧めします。

参考：[Node.js の Lambda デプロイパッケージを作成するには、どうすればよいですか？](https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-deployment-package-nodejs/?nc1=h_ls)

Beanstalkも、実態はEC2（Amazon Linux）インスタンスなので、Linux環境で`npm install`を実行する方が無難です。
やり方はいくつかありますが、おすすめはmyappプロジェクトをCloud9にアップロードして、そこで`npm install`を実行して、再度ローカルにダウンロードするやり方です。
詳しくは以下を参照。

参考：[Lambda関数にNode.jsモジュールを入れるなら、Cloud9が簡単でおすすめ](https://qiita.com/tamura_CD/items/7a51536b38973fb7497b)


###✅ ポイント3 : ZIPファイルはファイル指定して圧縮する

デプロイパッケージを作る際、生成したmyappプロジェクトフォルダ自体をZIPで圧縮すると、デプロイ時にエラーになります。
必ず、myappプロジェクトフォルダ配下のファイルを指定して、ZIPで圧縮してください。

<img width="592" alt="スクリーンショット 2019-12-25 18.15.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/de0b4d95-bc3d-d56e-7066-17bdbb3b8586.png">

#🔶 Elastic Beanstalk実行環境構築、デプロイ

Elastic Beanstalk
https://console.aws.amazon.com/elasticbeanstalk/

上記サイトを開き、［今すぐ始める］をクリック。
<img width="1056" alt="スクリーンショット 2019-12-25 19.27.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/d93b6b6a-43ae-6ed9-c364-17857fffd32f.png">


ウェブアプリケーションの作成画面で、
1. `アプリケーション名`に、任意の名前をセットする。（今回は'test'）
2. `プラットフォーム`は、「Node.js」を選択する。
3. `コードのアップロード`で、myappプロジェクトのファイル一式をZIPで圧縮したものを選択する。
4. ［アプリケーションの作成］ボタンをクリックする。
<img width="1179" alt="スクリーンショット 2019-12-25 19.22.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/c35d4169-8a1e-8964-8420-6f6781c8e85e.png">

以下の画面に遷移する。
暫く待つと実行環境が構築され、画面右上のURLリンクから、アプリにアクセスできるようになるが、この時点では設定が終わってないのでアプリに接続できません。
<img width="1056" alt="スクリーンショット 2019-12-25 19.25.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/50fda6d6-5253-6a3d-e798-1c1cc3a26fb0.png">

###✅ ポイント4 : Node.jsの起動コマンドを設定する

今回のNode.js製のアプリは、`npm start`コマンドで実行するようにpackage.jsonに設定されています。しかし、Elastic Beanstalkは指定が無ければ、`app.js`、`server.js`、`npm start`の順に実行する事になります。

参考：[Node.js 環境の設定](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_nodejs.container.html#nodejs-platform-console)

そこで、最初に`npm start`を実行するように設定します。

画面上部の`「すべてのアプリケーション > test > Test-env...」`の、testリンクをクリックする。

Test-envリンクをクリックする。
<img width="1132" alt="スクリーンショット 2019-12-25 19.50.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/ce1b162f-5981-6a51-7838-30fd0b81d894.png">

画面左メニューの設定リンクをクリックして、ソフトウェアのカテゴリで［変更］ボタンをクリックする。
<img width="1131" alt="スクリーンショット 2019-12-25 19.51.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/31926482-2642-ea84-79cd-cbc22e90e004.png">

ソフトウェアの変更画面のノードコマンドに、`npm start`をセットして、画面下部の[適用]ボタンをクリックする。
<img width="1136" alt="スクリーンショット 2019-12-25 19.55.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/b7c55dda-ca9e-df00-66e7-701ec21fc241.png">



#🔶 実行

変更設定が適用されると、以下の画面が表示されるので、再度画面右上にあるURLのリンクをクリクする。
<img width="1139" alt="スクリーンショット 2019-12-25 20.00.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/803187f4-b88f-09e9-7c2a-b2ed75807335.png">

expressのサンプルアプリが表示されたら成功です。
<img width="687" alt="スクリーンショット 2019-12-25 20.10.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38099/5d0b28c5-febf-5f89-ba4f-ae1e8a67fc4e.png">

#🔶 まとめ

このように、Elastic BeanstalkでNode.js+expressアプリを動かそうとすると、ローカルで実行する時と違って、いくつか詰まるポイントがあります。
しかし、この部分をうまく対応したら、後は開発に専念できるので、ぜひ使ってみてください。

#🔶 参考
- [プロキシサーバーを設定する](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/nodejs-platform-proxy.html)
- [Node.js の Lambda デプロイパッケージを作成するには、どうすればよいですか？](https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-deployment-package-nodejs/?nc1=h_ls)
- [Node.js 環境の設定](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_nodejs.container.html#nodejs-platform-console)