AWS Elastic BeanstalkにNest.jsアプリをデプロイする
はじめに
Nest.jsで構築したアプリをElastic Beanstalkにデプロイする際、公式の手順に従っているのにアプリの起動に失敗(nest startでPermission Denied)する事例に苦しんだので、対処を記載しておきます。なお、Beanstalk環境の作成手順は割愛します。
$ node --version
v14.17.5
$ nest --version
8.2.0
# Elastic Beanstalk Platform
Node.js 14 running on 64bit Amazon Linux 2/5.4.9
結論
package.jsonのscriptsに以下を追加します。
...
"scripts": {
"prebuild": "rimraf dist",
"build": "npx nest build",
"pack": "npm run build && zip dist/deploy.zip -r dist package.json .npmrc",
"start": "node dist/main",
...
}
そのうえでnpm run packを実行し、dist配下に作成されたdeploy.zipをBeanstalk環境にアップロード&デプロイすれば完了です。
解説
BeanstalkでNest.jsアプリケーションが起動に失敗する理由は、必要なパッケージが取得できていないためです。
Beanstalk環境はデフォルトでNPM_USE_PRODUCTIONがtrueになっているため、本番環境用の依存関係しか取得してくれません。結果、devDependenciesに指定されたts-nodeがインストールされずにエラーが発生します。
これに対処する方法が上記package.jsonとなります。ポイントは2点です。
1つ目はpackコマンドです。
npx nest buildしてTypeScriptをコンパイルし(コンパイルされたソースはdist配下に格納されます)、これらのjsファイルと依存関係を記載したpackage.json(.npmrcは必要な場合のみ)をzip化しています。
srcフォルダがネストしていると正しく動かないことがあったので、プロジェクトフォルダ直下にsrcやpackage.jsonが配置される構成にしてください。
# NG
project-name
-hoge
-src
-main.ts
# OK
project-name
-src
-main.ts
2つ目はstartコマンドにdist/mainを指定することです。
Beanstalkでは開始コマンドとしてstartコマンドが実行されますが、先述の原因によりデフォルトのnest startやnest start:devが失敗します。なので、コンパイルしたソースのmainクラスを直接実行するように指定する必要があります。
またGithub Actionsを利用した自動デプロイを設定する場合、通常node_modulesはGit管理対象に含まれないと思いますので、npm installとnpm packを実行してからdist/deploy.zipをBeanstalk環境にアップロードするよう記載すればOKです。
Discussion