空雲 Blog

Eye catchNext.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');
4
5const clusterSize = Math.min(os.cpus().length, 4);
6
7if (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 build
2WORKDIR /app
3COPY package.json yarn.lock ./
4RUN --mount=type=cache,target=/usr/local/share/.cache/yarn/v6 yarn
5COPY . .
6RUN yarn build
7RUN 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/standalone
11COPY package.json yarn.lock ./
12
13FROM node:alpine
14WORKDIR /app
15COPY --from=build /app/.next/standalone ./
16
17EXPOSE 3000
18CMD ["node","forker.js"]

まとめ

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