第47章:開発用と本番用は別物(まずは区別だけ)🎭
この章は「分け方を完璧にする」じゃなくて、“同じにしない理由”を体感して、最低限の分け方を持つのがゴールだよ🙂✨ (Todo API を題材に、開発=ホットリロード、本番=ビルド済みを比べるよ!)
1) まずイメージ:開発と本番は“現場”が違う🏗️🏪
-
開発用(dev):工事現場👷♂️ 早く回すのが正義!🔁⚡ 例:ホットリロード、デバッガ、開発ツール入り、ソースを同期して即反映
-
本番用(prod):お店オープン状態🏪 安定が正義!🧱✨ 例:ビルド済み成果物、余計なツール無し、依存も最小、設定は環境変数で差し替え
この「現場の目的が違う」ってだけで、中身を同じにすると事故りやすいんだよね😵💫💥
2) なぜ“同じにしない”の?(初心者がハマる理由トップ3)🥇🥈🥉
- ホットリロード系が本番で動くと、CPU/メモリが無駄に増える😱🔥
- devDependencies が本番に入ると、イメージが太る&攻撃面が増える📦➡️🐘 → Docker は「ビルド段階と実行段階を分ける(マルチステージ)」を強く推してるよ。(Docker Documentation)
- 本番は “ビルド済みで再現可能” が命🧪✅
→ 依存は lockfile ベースでクリーンに入れるのが基本(
npm ci)。(npm ドキュメント)
3) 最小ルール:まずはこの4つだけ守ればOK📏✨
-
「dev」と「prod」で起動コマンドを分ける▶️
- dev:
npm run dev(ホットリロード) - prod:
node dist/index.js(ビルド済み)
- dev:
-
**dev は “ソースを同期して即反映”/prod は “同期しない”**🔁🚫
- dev:bind mount か Compose Watch
- prod:イメージに成果物を入れて起動
-
prod は
NODE_ENV=productionを基本にする🎚️ Node.js公式も「本番はNODE_ENV=production」を推奨してるよ。(nodejs.org) -
Dockerfile は “dev ステージ” と “prod ステージ” を分ける🍱 Docker の Node.js ガイドでも、開発/本番(+テスト)でステージを分ける方針になってる。(Docker Documentation)
4) ハンズオン:Todo API を dev/prod で分けて動かす🧪🎮
ここから「実際に比べる」よ!😆✨
(TypeScript → dist/ にビルドされる想定)
Step A:package.json に “dev/prod” の役割をはっきりさせる📝
例(すでにあるなら読み替えでOK)👇
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc -p tsconfig.json",
"start": "node dist/index.js"
}
}
- dev:ファイル変更を監視して自動再起動🔁
- build:本番用に
dist/を作る🏗️ - start:
dist/を実行する🏁
Step B:Dockerfile(1枚)で dev/prod を“ステージ分け”する🍱
ポイントはこれ👇
- dev:devDependencies も入れる(開発ツールが必要)
- prod:devDependencies を除外&dist だけ持っていく
## syntax=docker/dockerfile:1
FROM node:24-bookworm-slim AS base
WORKDIR /app
## 依存は先に(キャッシュ効かせる)
COPY package*.json ./
## ----------------------------
## dev用:devDependencies込み
## ----------------------------
FROM base AS deps-dev
RUN npm ci
## ----------------------------
## prod用:devDependenciesなし
## ----------------------------
FROM base AS deps-prod
RUN npm ci --omit=dev
## ----------------------------
## devステージ:ホットリロード起動
## ----------------------------
FROM deps-dev AS dev
COPY . .
CMD ["npm","run","dev"]
## ----------------------------
## buildステージ:TSをdistへ
## ----------------------------
FROM deps-dev AS build
COPY . .
RUN npm run build
## ----------------------------
## prodステージ:ビルド成果物だけで実行
## ----------------------------
FROM base AS prod
ENV NODE_ENV=production
COPY --from=deps-prod /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package*.json ./
EXPOSE 3000
CMD ["node","dist/index.js"]
- マルチステージで「ビルドに必要な物」と「実行に必要な物」を切り離せるのが強みだよ。(Docker Documentation)
npm ciは CI/デプロイ向きの“クリーンインストール”として npm が説明してる。(npm ドキュメント)
Step C:Compose で “dev を快適に” する(Watch を使ってみる)👀✨
Docker には Compose Watch っていう「保存したら自動で同期/再起動/再ビルド」できる仕組みがあるよ。(Docker Documentation)
しかも Node.js では node_modules/ を同期しないのが推奨(ネイティブ依存やパフォーマンス問題がある)って明言されてる。(Docker Documentation)
compose.yml(dev と prod を profile で分ける例)👇
services:
api:
profiles: ["dev"]
build:
context: .
target: dev
ports:
- "3000:3000"
develop:
watch:
- action: sync
path: .
target: /app
ignore:
- node_modules/
- dist/
- action: rebuild
path: package-lock.json
api-prod:
profiles: ["prod"]
build:
context: .
target: prod
ports:
- "3000:3000"
**動かし方(dev)**👇
--watch で Watch を起動できるよ。(Docker Documentation)
docker compose --profile dev up --build --watch
**動かし方(prod)**👇
docker compose --profile prod up --build
5) 体感テスト:dev と prod の違いを目で見る👀🔥
✅ dev の確認(ホットリロード)
- dev 起動中に
src/のログ文を変える✍️ - 保存💾
- コンテナが自動で同期されて反映される(仕組みは Watch/ホットリロード)🎉 Watch は「編集→保存」をトリガーに更新してくれる。(Docker Documentation)
✅ prod の確認(ビルド済み)
- prod を起動する
src/を変えても 変化しない🙅♂️(だって dist を動かしてるから)- 反映したいなら build → 再起動が必要🔁
この時点で「同じにしない意味」がスッと腑に落ちるはず😆✨
6) よくある事故 😵💫💥(この章で先に潰す)
-
本番なのに dev ターゲットでビルドしてた🎭➡️💣 →
target: prodになってるか見る👀 -
本番なのにソース同期(mount/watch)してた📎 → prod は “同期なし” が基本(再現性&安全性)🧱
-
NODE_ENVを意識してなくて挙動が違う🎚️ → 公式は本番でNODE_ENV=productionを推奨。(nodejs.org) -
node_modules を同期して地獄🧟♂️ → Node.js では
node_modules/を同期しないのが推奨。(Docker Documentation)
7) AI活用(最短で身につくプロンプト集)🤖✨
-
チェックリスト化✅ 「dev と prod を分ける最小チェックリストを10個。Node/TS + Dockerfile multi-stage + compose profiles 前提で。」
-
自分のDockerfileレビュー👀 「この Dockerfile は dev/prod の区別として最低限OK?太る原因・危険ポイント・改善案を3つずつ。」
-
compose watch の設計🧩 「このプロジェクトで watch にすべき path と ignore を提案して。node_modules を同期しない前提で。」
(ちなみに Docker の公式ドキュメントや、GitHub の Copilot、OpenAI の Codex 系でレビューさせると爆速だよ🤖⚡)
8) ミニ問題(3分)🧠✨
- dev でソース変更が即反映されるのは、どの仕組みが関係してる?(2つ答えてOK)🔁
- prod で
node dist/index.jsを動かす利点は?🏁 - Node.js で
node_modules/を同期しない方がいい理由は?📦
次の章(第48章)で「タグ運用」をやると、dev/prod をちゃんと“名前で管理”できるようになって、さらに事故が減るよ🏷️✨