目的
最近では、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"]