Docker は、コンテナ内にアプリケーションを配置できるようにするため、近年人気が高まっています。これらのコンテナは任意の環境にデプロイでき、すべての環境で同じように動作し、アプリケーションが実行されるプラットフォームに関係なく均一な動作を提供します。これらのコンテナは、アプリケーションのコピーまたは圧縮されたスナップショットであるイメージを使用します。コンテナ内に配置することで、そのまま表示されます。これは、一部の人が切望していたテクノロジーの 1 つですが、他の人は、それについて聞くまで必要性を認識していません。
Next.js は最も人気のある React フレームワークです。 webpack や Vite などのバンドラーを使用する他の JavaScript アプリケーションと同様に、運用にはプロジェクトのコンパイルされたバージョンが使用されます。これはビルドとして知られています。ビルドは、アプリケーションが開発時と同じように機能するために必要な最小限のコードを提供することを目的としています。これにより、JavaScript ファイルが非常に軽量になり、ブラウザーがそれらをフェッチして解釈し、ユーザー インターフェイスをレンダリングしたり、アプリケーションが必要とするあらゆるタスクを実行したりできるようになります。」
Next.js は、具体的には、ビルド サイズをさらに縮小するバージョン、つまりスタンドアロン ビルドを提供します。 Docker を使用して Next.js アプリケーションのイメージを作成すると、互換性や追加の構成を気にすることなく、構築した優れたアプリケーションをあらゆる環境に簡単にデプロイできます。この記事では、それを達成する方法を説明します。
私の場合、pnpm を使用して、node_modules フォルダーのディスク サイズを削減するのが好きです。したがって、Next.js Docker イメージの例ではこのパッケージ マネージャーを使用していますが、必要に応じて若干の調整を加えて npm または Yarn を使用することもできます。
next.config.js ファイルでは、アプリケーションが実稼働用にコンパイルされるときに、結果のビルド タイプがスタンドアロンになることを指定する必要があります。このためには、以下を含める必要があります:
/** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone" }; export default nextConfig;
この方法では、アプリケーションの出力はスタンドアロン型になります。
Docker イメージを表すファイルは Dockerfile です。通常、このファイルはプロジェクトのルートに配置されます。段階的に作成してみましょう。
すべての Docker イメージは基本イメージから始まります。この場合、サーバーを実行する JavaScript プロジェクトには Node.js などのランタイムが必要になります。プロジェクトと互換性のある Node.js バージョンの Docker イメージをベースとして使用します。私の場合、Alpine バージョンのイメージを使用するのが好きです。これは、Alpine バージョンの方が軽量であるためです。ただし、イメージをビルドするときに互換性の問題がないことを確認する必要があります。そうでない場合は、イメージの「非 Alpine」バージョンを使用する必要があります。この例では、node:22.6.0-alpine3.19 イメージをベースとして使用します。
/** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone" }; export default nextConfig;
イメージのさまざまなステップまたは段階でリサイクルするためにエイリアスを配置します。
次の段階では、依存関係をインストールします。この場合、必要なシステム依存関係は libc6-compat の 1 つだけです。ここではその理由について説明します。
FROM node:22.6.0-alpine3.19 AS base
pnpm はデフォルトでは Node.js に含まれていないため、pnpm を有効化し、インストールされたパッケージをキャッシュできるように環境変数を設定する必要があります。
FROM base AS build-deps RUN apk add --no-cache libc6-compat
次に、システム フォルダーとアプリケーション フォルダーを明確に区別するように作業ディレクトリを設定する必要があります。この場合、/app を使用します。
ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate
次に、プロジェクトの依存関係情報を含むファイルをコピーしてインストールする必要があります。
WORKDIR /app
--frozen-lockfile および --prefer-frozen-lockfile 引数は、pnpm のロック ファイルで指定されたバージョンを尊重するために使用されます。
この段階を終了するには、シャープ ライブラリを追加します。これは、Next.js の実稼働環境で画像を最適化するために必要です。
COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile
ステージ全体は次のようになります:
RUN pnpm add sharp
次の段階では、Next.js アプリケーションをコンパイルします。 Dockerfile の残りの部分は何も変わっていないか、他の例では見つけることができないため、ここにイメージを機能させるための鍵があります。 この段階では、プロジェクトで使用される環境変数をビルド引数として渡し、ビルドを生成する前に設定する必要があります。
これは、アプリケーションが動作する時間はビルド時と実行時の 2 つであるため、実行時に環境変数が利用できない場合、それらを使用するすべての静的アセットに値が存在しないためです。アプリケーションが正常に動作しなくなります。この例では、NEXT_PUBLIC_BACKEND_URL、FRONTEND_URL、JWT_SECRET の 3 つの環境変数が使用されています。
FROM base AS build-deps RUN apk add --no-cache libc6-compat ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile RUN pnpm add sharp
その後、pnpm がアクティブ化され、作業ディレクトリが設定され、すべてのアプリケーション ファイルがコピーされ、ビルドが生成されます。
FROM base AS builder ARG NEXT_PUBLIC_BACKEND_URL ENV NEXT_PUBLIC_BACKEND_URL=$NEXT_PUBLIC_BACKEND_URL ARG FRONTEND_URL ENV FRONTEND_URL=$FRONTEND_URL ARG JWT_SECRET ENV JWT_SECRET=$JWT_SECRET
ステージ全体は次のようになります:
RUN corepack enable RUN corepack prepare pnpm@latest --activate WORKDIR /app COPY --from=build-deps /app/node_modules ./node_modules COPY . . RUN pnpm build
最後の段階では、アプリケーションを実行します。これを行うには、まずノードの実稼働環境を設定します。
/** @type {import('next').NextConfig} */ const nextConfig = { output: "standalone" }; export default nextConfig;
個人的な好みにより、Next.js テレメトリは無効になっています。つまり、基本的に、エラー診断や使用状況メトリクスを通じて Next.js を改善するためにアプリケーション データを Vercel に送信することはありません。
FROM node:22.6.0-alpine3.19 AS base
また、良い習慣として、Docker イメージでは非 root ユーザーを使用することをお勧めします。これにより、たとえば、コンテナがホスト ネットワークにアクセスできる場合のセキュリティ侵害が回避されます。これを行うには、nodejs グループと nextjs ユーザーが追加され、.next フォルダー プロパティが割り当てられます。
FROM base AS build-deps RUN apk add --no-cache libc6-compat
次に、スタンドアロン ビルドで生成されたファイルがコピーされて、Next.js のデフォルト ビルドと同じ構造が作成されます。
ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate
nextjs ユーザーを作成したので、これが使用するユーザーであることを指定する必要があります。
WORKDIR /app
同様に、コンテナの公開ポート、使用されるノード ポートとホスト名を指定する必要があります。正確なアドレスがわからないため、0.0.0.0 になります。
COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile
次に、アプリケーション ランタイムの環境変数がビルド引数から指定されます。
RUN pnpm add sharp
docker-compose.yml ファイルで指定された環境変数は、コンテナーの実行時にも使用できますが、このコンテキストの環境変数がビルド時と実行時に異なるのは意味がありません。 .
最後に、サーバーを実行します。
FROM base AS build-deps RUN apk add --no-cache libc6-compat ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN corepack prepare pnpm@latest --activate WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prefer-frozen-lockfile RUN pnpm add sharp
完全な Dockerfile は次のようになります:
FROM base AS builder ARG NEXT_PUBLIC_BACKEND_URL ENV NEXT_PUBLIC_BACKEND_URL=$NEXT_PUBLIC_BACKEND_URL ARG FRONTEND_URL ENV FRONTEND_URL=$FRONTEND_URL ARG JWT_SECRET ENV JWT_SECRET=$JWT_SECRET
この要点からもファイルを見つけることができます。
Next.js アプリケーションの Docker イメージを作成することは、考慮する必要があるすべての考慮事項のため、最初は気が遠くなるかもしれません。さらに、Next.js アプリケーションを自己ホストするという一般的な考えがあります。つまり、ヴェルセルの外では複雑です。そうではありません。重要な部分を理解すれば、実際には簡単です。
この情報を利用して、Next.js アプリケーションを問題なく Docker 化できることを願っています。質問がある場合、または何かを共有したい場合は、コメントに残してください:)
以上がスタンドアロン ビルドを使用した Next.js アプリケーションの Docker 化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。