メインコンテンツまでスキップ

第24章 “毎回全部ビルド”をやめる:ターゲット/プロファイル戦略 🎯🚦⚡️

今日のゴールはこれ! 「いま必要なものだけ」ビルドして、起動して、作業を最短ルートにする 🏎️💨 Dockerが遅い最大の原因のひとつが「関係ないものまで毎回やってる」なので、ここをズバッと切ります✂️✨


0) まず最初に:この章の“2つのスイッチ”🔘🔘

「全部ビルドしちゃう」のを止めるには、スイッチが2つあります👇

  • ターゲット(build target):Dockerfileの「どの段階まで作る?」スイッチ → マルチステージの特定ステージで止める(例:dev / test / prod) → docker build --target ... や、Composeの build.target を使う感じです。(Docker Documentation)

  • プロファイル(profiles):Composeの「どのサービスを起動する?」スイッチ → devだけ、testだけ、debugだけ…を切り替える → --profileCOMPOSE_PROFILES でONにする。(Docker Documentation)

この2つで、**「必要な分だけ作って、必要な分だけ動かす」**が実現できます😆✨


1) 図でつかむ:ターゲットとプロファイルの役割 🎯🚦

ざっくりこんな分担です👇

【ターゲット】= 1つのDockerfileの中で「どこまで作る?」🎯
base → deps → dev → test → prod
↑ ↑ ↑
依存 開発 テスト 本番

【プロファイル】= composeの中で「誰を起動する?」🚦
dev: app + db + (adminer)
test: test-runner + db
prod: app-prod (軽量) + db (必要なら)
  • ターゲット:**イメージの中身(作り方)**を変える
  • プロファイル:**起動メンバー(動かし方)**を変える

2) ターゲット戦略:Dockerfileを“止められる”構造にする 🧱🛑

2-1) マルチステージは「途中で止められる」🛑✨

マルチステージは FROM ... AS <name> で段階を作って、必要なら 特定ステージで止めてビルドできます。(Docker Documentation)

さらに重要ポイント👇 BuildKitだと、ターゲットに必要なステージだけビルドしてくれます(関係ないステージをスキップ)😆⚡️(Docker Documentation)


2-2) 例:Node/TS用 Dockerfile(dev/test/prod で止める)🧑‍💻📦

Nodeの推奨は「LTS系」を使うのが無難です(2026-02時点だと v24 が Active LTS)。(Node.js)

## syntax=docker/dockerfile:1

## ①共通の土台
FROM node:24-bookworm-slim AS base
WORKDIR /app

## ②依存だけ(ここがキャッシュの要)
FROM base AS deps
COPY package.json package-lock.json ./
RUN npm ci

## ③開発用(dev依存やツール入り)
FROM deps AS dev
COPY . .
CMD ["npm", "run", "dev"]

## ④テスト用(testだけ走らせたい)
FROM deps AS test
COPY . .
CMD ["npm", "test"]

## ⑤本番用(軽くする)
FROM base AS prod
ENV NODE_ENV=production
COPY --from=deps /app/node_modules /app/node_modules
COPY . .
CMD ["node", "dist/index.js"]

ポイントはこれ👇

  • deps ステージが “超重要キャッシュポイント” 🧠✨
  • dev/test/prod は「必要な時だけ」ターゲット指定して作る🎯
  • prod はなるべく軽く(devツールを持ち込まない)🪶

3) Composeのターゲット:build.target で “devだけ作る” 🎯⚙️

Composeは build.target で「Dockerfileのどのステージをビルドするか」を指定できます。(Docker Documentation)


4) プロファイル戦略:起動メンバーを分けて“余計な起動”をゼロにする 🚦✨

4-1) profiles の基本

  • profilesないサービス:ふつうに docker compose up で起動(常時組)
  • profilesあるサービス:そのプロファイルを有効にした時だけ起動(任意組)(Docker Documentation)

プロファイル有効化は👇


4-2) 重要な落とし穴:depends_on と profiles 😵‍💫

profiles にはクセがあります👇

  • profiles によって無効になったサービスは、勝手に有効化されません
  • depends_on してても、プロファイルが一致してないとエラーになることがあります(Docker Documentation)

➡️ 対策はシンプルで、依存関係のあるサービスは同じプロファイルに入れるか、**コアな依存(db等)はプロファイル無し(常時)**にします👌


5) 実戦:ターゲット×プロファイルで“開発/テスト/本番っぽい確認”を分ける 🧪🚀

5-1) compose.yaml 例(dev/test/prod の動線を分離)🧩

services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"

# 開発:devターゲットで起動
app:
build:
context: .
target: dev
profiles: ["dev"]
ports:
- "3000:3000"
depends_on:
- db

# テスト:testターゲットで「テストだけ」実行
test-runner:
build:
context: .
target: test
profiles: ["test"]
depends_on:
- db

# 本番っぽい確認:prodターゲットで軽量起動(ポートを変えて衝突回避)
app-prod:
build:
context: .
target: prod
profiles: ["prod"]
ports:
- "4000:3000"
depends_on:
- db

ここでの狙い👇

  • dev中は app-prodtest-runner起動しない(=待ち時間ゼロへ)🚫⏳
  • 必要になった瞬間だけプロファイルONで呼び出す🚦✨

6) コマンド動線:最短で動かす(“全部”を避ける)🏎️💨

6-1) 開発だけ起動(dev)

docker compose --profile dev up --build

6-2) テストだけ実行(test)

docker compose --profile test up --build --abort-on-container-exit

6-3) 本番っぽい確認(prod)

docker compose --profile prod up --build

7) 「全部ビルド」を防ぐ超重要テク:buildは“サービス指定”する 🧯🔥

docker compose buildサービス名を指定できます。 つまり、これができます👇

docker compose build app
docker compose build test-runner

(Usage に docker compose build [OPTIONS] [SERVICE...] とあります)(Docker Documentation)

さらに必要なら👇


8) よくある“遅くなる設計”と直し方 😭➡️😆

パターンA:dev中に test / prod まで毎回巻き込む

✅ 解決:profilesで起動分離(dev中はdevだけ)(Docker Documentation)

パターンB:Dockerfileが「止められない」一本道

✅ 解決:dev/test/prod をステージ化して target で止める(Docker Documentation)

パターンC:db を profiles に入れてしまい、別プロファイルで依存崩壊

✅ 解決:dbは **常時(profiles無し)**にする or 依存側と同プロファイルへ(Docker Documentation)


9) 🧪ミニ演習:あなたのプロジェクトを“3動線”に分けよう 🚦

Step 1:Dockerfileにステージ名をつける(dev/test/prod)

  • いま FROM ... が1個なら、まず depsdev を分けるだけでも大勝利🏆✨

Step 2:compose.yaml に profiles を入れる

  • dev:普段の開発(app + db)
  • test:テストだけ(test-runner + db)
  • prod:本番っぽい確認(app-prod + db)

Step 3:計測してニヤける 😏⏱️

  • dev起動:前より速い?
  • test 実行:dev環境を巻き込まずに走った?
  • prod 確認:devと別ポートで起動できた?

10) 🤖AI活用:レビュー用プロンプト(コピペOK)🧰✨

10-1) ターゲット設計レビュー(Dockerfile)

「このDockerfile、targetで止められる設計になってる?」を聞く👇

次のDockerfileをレビューして:
1) dev/test/prod のターゲット分離が適切か
2) キャッシュが壊れやすい命令順がないか
3) BuildKitの「必要ステージだけビルド」を活かせる構造か
改善案を3つ、理由付きで出して。差分パッチ形式も欲しい。

10-2) profiles 設計レビュー(compose.yaml)

「起動メンバーが最小か?」を聞く👇

次のcompose.yamlをレビューして:
1) dev中に不要なサービスが起動しない設計か(profiles)
2) depends_on と profiles の組み合わせで壊れる点がないか
3) dev/test/prod の動線が分かりやすいか
改善案と、改善後のcompose例を提示して。

10-3) “コマンド動線”を整える(初心者にやさしい設計へ)

この構成で、開発者が迷わないコマンド動線を作りたい。
dev/test/prod の各動線を「短いコマンド(npm scripts想定)」にして提案して。
ついでにREADMEの使い方セクションも書いて。

(ここで GitHub の Copilot や OpenAI 系の拡張に投げると、かなり捗ります🤖✨)


11) まとめ:この章で“遅い”が一気に消える理由 🧹⚡️

これで、dev中に test/prod/ツール類を巻き込む地獄から抜けられます😆🌈


次の章(第25章)は CI 側(GitHub Actions等)でこの「ターゲット/プロファイル+キャッシュ」をさらに効かせて、**“pushしたら遅い”**を潰しに行く流れになります🧪🏎️