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