本文では、Prisma と Nuxt.js を組み合わせたフルスタックプロジェクトの最適化された Docker イメージの作成方法と、パッケージマネージャーとして pnpm を使用する方法について説明します。
私のプロジェクトの最終イメージサイズは 1.12GB から 160.21MB に縮小されました。
プロジェクトの構成#
Nuxt.js は、Vue.js ベースのサーバーサイドレンダリングアプリケーションフレームワークであり、モダンな Web アプリケーションの構築に非常に適しています。
私のプロジェクトは、Nuxt を使用してフルスタックプロジェクトを構築しています。
- Nuxt3
- Prisma
- PNPM
構築の開始#
まず、最終イメージのサイズを小さくするために、より軽量なベースイメージであるnode:20-alpine
を使用します。Alpine Linux は、安全性、シンプルさ、および小さなサイズのために広く使用されています。
マルチステージビルドは、Docker イメージのサイズを減らすための効果的な戦略の一つです。私たちは 3 つのステージを使用してイメージを構築します。
ステージ 1:依存関係の構築#
ARG NODE_VERSION=node:20-alpine
FROM $NODE_VERSION AS dependency-base
WORKDIR /app
RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile`
このステージでは、プロジェクトの依存関係をインストールします。私たちは、より効率的なキャッシュとディスク使用を提供するために、pnpm を使用しています。
多くのプロジェクトでは、npm の代わりに pnpm をパッケージマネージャーとして使用しています。
ステージ 2:アプリケーションの構築#
FROM dependency-base AS production-base
COPY . .
RUN pnpm run build
このステージでは、プロジェクトのコードをコピーし、ビルドコマンドを実行します。ここでのビルドとは、Nuxt.js のビルドプロセスを指します。これにより、静的ファイルとサーバーサイドレンダリングに必要なリソースが生成されます。
ステージ 3:本番イメージの生成#
FROM $NODE_VERSION AS production
COPY --from=production-base /app/.output /app/.output
ENV NUXT_HOST=0.0.0.0 \
NUXT_APP_VERSION=latest \
DATABASE_URL=file:./db.sqlite \
NODE_ENV=production
WORKDIR /app
EXPOSE 3000
CMD ["node", "/app/.output/server/index.mjs"]
最後に、本番環境で使用するイメージを作成します。このイメージには、アプリケーションの実行に必要なファイルのみが含まれており、不要なレイヤーが削減され、イメージができるだけシンプルになっています。
また、Nuxt.js アプリケーションと Prisma に必要な環境変数(NUXT_HOST
やDATABASE_URL
など)も定義しています。その中で、DATABASE_URL
はプロジェクトのルートディレクトリにある SQLite ファイルをデータベースとして使用するように設定されています。
最終的に、ポート3000
を公開し、Nuxt.js アプリケーションを実行するための起動コマンドを指定します。
異なるビルド方法のイメージサイズの比較#
それぞれのビルド方法は次のとおりです:
- 3 ステップビルド
- 2 ステップビルド
- 直接ビルド
Dockerfile の概要#
# Use a smaller base image
ARG NODE_VERSION=node:20-alpine
# Stage 1: Build dependencies
FROM $NODE_VERSION AS dependency-base
# Create app directory
WORKDIR /app
# Install pnpm
RUN npm install -g pnpm
# Copy the package files
COPY package.json pnpm-lock.yaml ./
# Install dependencies using pnpm
RUN pnpm install --frozen-lockfile
# Stage 2: Build the application
FROM dependency-base AS production-base
# Copy the source code
COPY . .
# Build the application
RUN pnpm run build
# Stage 3: Production image
FROM $NODE_VERSION AS production
# Copy built assets from previous stage
COPY --from=production-base /app/.output /app/.output
# Define environment variables
ENV NUXT_HOST=0.0.0.0 \
NUXT_APP_VERSION=latest \
DATABASE_URL=file:./db.sqlite \
NODE_ENV=production
# Set the working directory
WORKDIR /app
EXPOSE 3000
# Start the app
CMD ["node", "/app/.output/server/index.mjs"]