概要
Next.jsをEC2を利用してデプロイする際の環境構築をする機会がありましたので、その際に出会った問題を羅列しております。
環境
- Ansible
- Capistrano
- Ubuntu v22.04.3
- Next.js v14.x
Node.jsのインストール
Ubuntu標準のNode.jsパッケージはv10.xのため、NodeSourceを利用して指定のバージョンをインストールします。
# nodeの特定のバージョンをインストールするための下準備
- name: import gpg key
apt_key:
url: https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key
keyring: /etc/apt/keyrings/nodesource.gpg
- name: create nodesource repository
apt_repository:
repo: deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main
filename: nodesource.list
state: present
- name: Install nodejs
apt:
name: nodejs
update-cache: true
become: true
参考:
Ubuntu 22.04 LTSへの最新版Node.jsのインストール
https://self-development.info/ubuntu-22-04-lts%E3%81%B8%E3%81%AE%E6%9C%80%E6%96%B0%E7%89%88node-js%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/
PM2のインストール
Next.jsのサーバーはデーモン化が出来ないため、Capistranoのサーバー起動処理がリターンしません。
そのためNodeのスクリプトをデーモン化できるPM2を利用します。
また、PM2のログローテーションの設定にはpm2-logrotateを利用します。
PM2はpm2 install
を行えるPlaybookが存在しないので、苦肉の策としてshell
を利用しています。
PM2のモジュールをインストールする場合、実行ユーザーに注意が必要です。
become: true
のみ指定した場合、rootのみにモジュールがインストールされてしまいます。
become_user: xxxxx
で正しいユーザーを指定しましょう。
- name: Install pm2
community.general.npm:
name: pm2
global: true
- name: Install pm2 logrotate
shell: "pm2 install pm2-logrotate"
become: false
- name: set pm2 logrotate config TZ
shell: "pm2 set pm2-logrotate:TZ Asia/Tokyo"
become: false
# ログをデイリーの0時0分に切り替え
- name: set pm2 logrotate config interval
shell: "pm2 set pm2-logrotate:rotateInterval '*/0 0 * * *'"
become: false
- name: set pm2 logrotate config max_size
shell: "pm2 set pm2-logrotate:max_size 100M"
become: false
参考
[node.js][pm2][ts-node]PM2を使ってアプリケーションを永続化・ログローテーションでログを管理する
https://zenn.dev/tsonwk/articles/3f76ce1ff60a78
※pm2-logrotateの設定をecosystemファイルに記載することは出来ない(↓公式issue)
https://github.com/keymetrics/pm2-logrotate/issues/131
ビルドIDの固定
Next.jsアプリはビルドした際に固有のビルドIDを持ち、ビルドIDが異なる場合はエラーが発生します。そのため、複数のインスタンスでビルドを行う場合、ビルドIDを固定にする設定が必要です。
Capistranoの場合、リリースしたディレクトリに最新のコミットが記載されているREVISION
ファイルが生成されるので、それを利用します。
"scripts": {
"build": "GIT_COMMIT_HASH=$(cat REVISION) next build",
}
const buildId = process.env.GIT_COMMIT_HASH
const nextConfig = {
// ビルドIDの統一
generateBuildId: async () => {
// ハッシュはcapistranoにより生成されるREVISIONファイルから取得
console.log(`BUILD_ID: ${buildId}`)
return buildId
},
}
参考
公式DOC:ビルドIDの設定
https://nextjs-ja-translation-docs.vercel.app/docs/api-reference/next.config.js/configuring-the-build-id
AWS EC2でNext.jsの環境構築
https://blog.vivita.io/entry/2020/08/17/112932
あとがき
コンテナであれば起きない問題がいくつか発生し、ハマることが多かったです。(現在もcssのファイル名がビルド毎に異なる問題にハマっています)
この記事がどなたかの助けになれば幸いです。