第24章 “毎回全部ビルド”をやめる:ターゲット/プロファイル戦略 🎯🚦⚡️
今日のゴールはこれ! 「いま必要なものだけ」ビルドして、起動して、作業を最短ルートにする 🏎️💨 Dockerが遅い最大の原因のひとつが「関係ないものまで毎回やってる」なので、ここをズバッと切ります✂️✨
0) まず最初に:この章の“2つのスイッチ”🔘🔘
「全部ビルドしちゃう」のを止めるには、スイッチが2つあります👇
-
ターゲット(build target):Dockerfileの「どの段階まで作る?」スイッチ → マルチステージの特定ステージで止める(例:dev / test / prod) →
docker build --target ...や、Composeのbuild.targetを使う感じです。(Docker Documentation) -
プロファイル(profiles):Composeの「どのサービスを起動する?」スイッチ → devだけ、testだけ、debugだけ…を切り替える →
--profileやCOMPOSE_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)
プロファイル有効化は👇
docker compose --profile debug upCOMPOSE_PROFILES=debug docker compose up(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-prodもtest-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)
さらに必要なら👇
- 依存もまとめてビルド:
--with-dependencies(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個なら、まずdepsとdevを分けるだけでも大勝利🏆✨
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) まとめ:この章で“遅い”が一気に消える理由 🧹⚡️
- ターゲットで「作る範囲」を小さくする🎯(止める)(Docker Documentation)
- プロファイルで「動かす範囲」を小さくする🚦(選ぶ)(Docker Documentation)
- buildはサービス指定で「関係ないビルド」を避ける🧯(Docker Documentation)
これで、dev中に test/prod/ツール類を巻き込む地獄から抜けられます😆🌈
次の章(第25章)は CI 側(GitHub Actions等)でこの「ターゲット/プロファイル+キャッシュ」をさらに効かせて、**“pushしたら遅い”**を潰しに行く流れになります🧪🏎️