空雲 Blog

Eye catchNext.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のマルチプロセス化は完了です。サーバのリソースが潤沢ならば、シングルプロセスよりも効率的にサーバリソースを使えるようになります。大量アクセスを捌きたい場合などの選択肢の一つとしてどうでしょうか?