🚀

AWS Elastic BeanstalkにNest.jsアプリをデプロイする

2022/01/27に公開

はじめに

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に以下を追加します。

package.json
...
"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 startnest start:devが失敗します。なので、コンパイルしたソースのmainクラスを直接実行するように指定する必要があります。

またGithub Actionsを利用した自動デプロイを設定する場合、通常node_modulesはGit管理対象に含まれないと思いますので、npm installnpm packを実行してからdist/deploy.zipをBeanstalk環境にアップロードするよう記載すればOKです。

Discussion