MENU

docker マルチステージビルドをNext.js でやってみた

目的

最近では、AWSなどのインフラを設定するときに、 dockerがマストになってきていて、AWSはECSの利用、GCPの場合Cloud Runでコンテナを利用してdockerの扱いに慣れる必要があるなと思い取り組んでみました

必要性

dockerを利用した開発において、開発環境、テスト環境、本番環境をdocker で管理する場合、dockerfileを分けるケースがありました

ただその場合のデメリットとして下記があるかなと感じました。

  • 保守性が悪い 例えば、開発環境で新しいライブラリを入れたら、 テスト環境、本番環境のdockerfileを編集しないといけない

  • DRYでない ベース imageなどの重複したコードになる

マルチステージビルド

マルチステージビルドでは、これが解消できそう

特徴は下記かなと思う - as を利用してステージ(環境、ステップを分ける) - --from= を利用して、別ステージの要素を引き継げる

  • 利用方法
## 利用したいステージで buildする

docker build -t prod-front --target prod .  

## 実行する
docker run prod-front -p 3000:3000

完成したコード

# ビルド イメージを設定
FROM node:18.12-alpine AS base

# 作業ディレクトリを設定
WORKDIR /app

# 依存関係をコピーしてインストール
COPY package.json package-lock.json ./
RUN npm install

# アプリケーションのソースコードをコピー
COPY . .
RUN npm run build

# dev ステージを追加
FROM node:18.12-alpine AS dev

# 作業ディレクトリを設定
WORKDIR /app

# 依存関係をコピー
COPY package.json package-lock.json ./
RUN npm install

# アプリケーションのソースコードとビルドアーティファクトをコピー
COPY --from=base /app/.next ./.next
COPY --from=base /app/public ./public

# アプリケーションを開発モードで実行
CMD ["npm", "run", "dev"]

# 本番用のイメージを作成
FROM node:18.12-alpine AS prod

# 作業ディレクトリを設定
WORKDIR /app

# 依存関係をコピー
COPY package.json package-lock.json ./
RUN npm ci --only=production

# アプリケーションのソースコードとビルドアーティファクトをコピー
COPY --from=base /app/package.json package.json
COPY --from=base /app/.next ./.next
COPY --from=base /app/next.config.js next.config.js
COPY --from=base /app/node_modules node_modules
COPY --from=base /app/public ./public

# アプリケーションを本番モードで実行
CMD ["npm", "run", "start"]