AWS Elastic Beanstalk(以下EB)を使ってNode.jsアプリをデプロイしようとしてつまづいたので、備忘録として残しておく。
アプリケーションの概要
- Typescript+Expressで書かれたNode.jsアプリケーション。
- ローカルでは
ts-nodeを使って起動している。
デプロイしようとして失敗
Procfile を指定しない場合、package.json ファイルを指定すると Elastic Beanstalk は npm start を実行します。これを指定しない場合、Elastic Beanstalk は app.js または server.js をこの順序で探し、実行します。
と記載されていたので、特に何もしなくてもnpm startが実行されて、ts-nodeでサーバが起動すると思っていた。
が、実際デプロイしてみるとヘルスは「低下」、アクセスしてみると502 Bad Gateway。
ログを見ても特にエラー内容が見当たらず、なぜ動作していないのかがよく分からなかった。
参考になりそうな記事を発見
似たような事例がないかを探していたところ、参考になりそうな記事を発見した。
Deploying a TypeScript, ExpressJS app into ElasticBeanstalk NodeJS server | by Viet Hoang Le | Medium
要約すると、.ebextensionsを使って起動前にtsファイルをコンパイルすると良いとのこと。
.ebextensionsとProcfileを追加
.ebextensions
記事に書かれているとおりに.ebextensions/source_compile.configを追加した。
ただし、そのままだとnode_modules内のtscを実行するところでエラーになってしまったので、下記のように修正した。(指定の場所にtscがあるのは確認済み。原因不明。)
container_commands:
compile:
command: "tsc -p tsconfig.json"
env:
PATH: /opt/elasticbeanstalk/node-install/node-v14.17.3-linux-x64/bin/
/opt/elasticbeanstalk/node-install/node-v14.17.3-linux-x64/bin/下のtscを使ってコンパイルを行うようにしたが、デフォルトの状態ではtscがインストールされていない。
EBによって立ち上がっているEC2にsshで接続し、npm install -g typescriptを実行する必要がある。
Procfile
前述のとおり、package.jsonにはnpm startでts-nodeを実行するように書いているので、Procfileを追加しEBではnodeを実行するようにした。
web: node app.js
コンパイルしたファイルを実行するように記述するだけ。
これでデプロイしてサーバが動作するようになった。
余談
環境変数をマネジメントコンソールや.ebextensionsで指定したのに、sshで接続してexportコマンドやenvコマンドで確認しても全然反映されなくて困ったけど、そういうものだった。(実際特に問題なく動作していた。)
Elastic Beanstalk 環境から Linux および Windows インスタンスに変数を渡す
PHP を実行するスタック以外では、環境プロパティがインスタンスに存在していたとしても、それらがシェルに自動的にエクスポートされることはありません。その代わりに、環境プロパティは、使用されているプラットフォームに基づいて、アプリケーションが実行されているスタックを通じてアプリケーションに提供されます。