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