Next.jsのstandaloneビルドのカスタムサーバにマルチプロセス機能を加え高速化する
publication: 2023/07/23
update:2023/07/23
Next.jsとstandaloneビルド
Next.jsで作成したアプリケーションをデプロイするとき、Vercelなどを使わずDockerコンテナでイメージを起動する場合、standaloneビルドを使うとコンテナサイズが最適化できるのでサイズ的に有利になります。この時、起動用にNext.jsがserver.jsを自動生成するのですが、このファイルを呼び出す部分を細工して、マルチプロセス化してみます。
必要なファイル
server/forker.js
Node.jsのclusterを利用してserver.jsを最大4プロセス呼び出すためのコードです。clusterを利用すると、同じポートで待ち受けしているソケットのアクセスを自動的に負荷分散し、各プロセスに割り振ってくれるようになります。
/* eslint-disable @typescript-eslint/no-var-requires */
const cluster = require('cluster');
const os = require('os');
const clusterSize = Math.min(os.cpus().length, 4);
if (cluster.isPrimary) {
(async () => {
for (let i = 0; i < clusterSize; i++) {
cluster.fork();
await new Promise((resolve) => setTimeout(resolve, 500));
}
})();
} else {
require('./server');
}
Dockerfile
standaloneビルド用Dockerファイルに対して、起動時にforker.jsを使うように指定しています。
FROM node:alpine as build
WORKDIR /app
COPY package.json yarn.lock ./
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn/v6 yarn
COPY . .
RUN yarn build
RUN cp -r -u .next/server .next/standalone/.next &&\
cp -r -u .next/static .next/standalone/.next &&\
(cp -r -u .next/public .next/standalone/.next || true) &&\
cp -u server/forker.js .next/standalone
COPY package.json yarn.lock ./
FROM node:alpine
WORKDIR /app
COPY --from=build /app/.next/standalone ./
EXPOSE 3000
CMD ["node","forker.js"]
まとめ
これだけでNext.jsのマルチプロセス化は完了です。サーバのリソースが潤沢ならば、シングルプロセスよりも効率的にサーバリソースを使えるようになります。大量アクセスを捌きたい場合などの選択肢の一つとしてどうでしょうか?