第21章:ホットリロードをCompose運用に組み込む🔥♻️
この章は「保存したら、勝手に再起動して反映される」開発ループを、docker compose upのまま作る回です😊
ポイントはシンプルで、(1) ホストのファイル変更をコンテナへ入れる → (2) コンテナ内で“監視して再起動”する の2段構えです✨
1️⃣ まず“ホットリロード”を分解しよう🧩
ホットリロードって一言で言っても、実体はだいたいこの3つの組み合わせです👇
- ファイルがコンテナに届く(bind mount / 同期)
- TypeScriptが実行できる形になる(TSをそのまま実行 or 変換して実行)
- プロセスが再起動する(監視ツールが勝手に落として起動し直す)
このうち ①はComposeの役目、②③はアプリ側(Node/TS側)の役目です🧠
2️⃣ いちばん大事:ソースを“bind mount”する📎
Docker公式の入門でも、開発中の変更反映は bind mount + 監視ツール が基本路線です。(Docker Documentation)
✅ compose.yaml(まずはここが土台)
(appサービス想定。既存の構成に“差し込める”形にしてます)
services:
app:
build: .
ports:
- "3000:3000"
volumes:
- .:/app
- node_modules:/app/node_modules
command: npm run dev
environment:
NODE_ENV: development
volumes:
node_modules:
ここでの狙い🎯
.:/appで 編集したファイルが即コンテナに見えるnode_modulesを コンテナ側volumeに逃がす(ホストの依存関係と混ぜない)🧨
3️⃣ TypeScriptのホットリロード、どれが楽?おすすめ3択🍣
「何で監視する?」は好みが出ますが、初心者が詰まりにくい順に並べるとこんな感じです👇
🥇 A案:tsx watch(ラク・速い・設定少ない)⚡
tsxは TSをそのまま実行できて、Watchモードもあるのが強いです。(tsx)
package.json(例)
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc -p tsconfig.json",
"start": "node dist/index.js"
},
"devDependencies": {
"tsx": "^4",
"typescript": "^5"
}
}
これが動けば勝ち🏆
docker compose upしたまま src/index.ts を保存 → 自動で再起動して反映✨
🥈 B案:tsc -w + node --watch dist(王道・分かりやすい)👑
「TSはTSコンパイラに任せる、実行はNode」という分離パターンです😊 TypeScript側はwatchの設定も公式にまとまってます。(TypeScript)
さらにNodeには watch mode(変更で自動再起動) があり、近年は安定化も進んでます。(Node.js)
package.json(例:並列実行)
{
"scripts": {
"dev": "npm run dev:tsc & npm run dev:node",
"dev:tsc": "tsc -w -p tsconfig.json",
"dev:node": "node --watch dist/index.js"
}
}
&は「2つ同時に走らせる」やつです。 Windowsのローカル端末でやるとクセがありますが、コンテナ内なら割と素直に動きやすいです👍 (もし挙動が気持ち悪ければconcurrently等を使うのが定番です😊)
🥉 C案:nodemon(定番だけど“環境差”で詰まりやすい)🧯
nodemonは超定番で、公式READMEでも 監視して再起動が基本です。(GitHub)
ただし、Docker + Windowsまわりだと「イベント監視がうまく届かない」ことがあり、そういう時は ポーリング(-L) が逃げ道になります。(DigitalOcean)
package.json(例)
{
"scripts": {
"dev": "nodemon -L --ext ts --exec tsx src/index.ts"
},
"devDependencies": {
"nodemon": "^3",
"tsx": "^4",
"typescript": "^5"
}
}
4️⃣ Windowsでホットリロードが不安定な時の“だいたい効く”対処🪟🧯
✅ まずはDocker DesktopをWSL 2エンジンにする
設定画面でも、Windowsでは WSL 2エンジンの方がパフォーマンスが良いと明記されています。(Docker Documentation) (重い・反映遅い・監視が飛ぶ、みたいな症状が減ることが多いです😄)
✅ 監視が効かない時は“ポーリングに寄せる”
nodemon -L(上で紹介)(DigitalOcean)- もしくは、使ってる監視ライブラリに応じてポーリング系の設定を入れる(例:
CHOKIDAR_USEPOLLING=1など)🔁 (フレームワーク系で効くことが多いです)
✅ “反映はされてるのに再起動しない”なら、再起動の担当を疑う
- bind mountはOK(中身は更新されてる)
- でも監視プロセスが検知してない
→ 監視ツールを変える(
tsx watchへ)か、ポーリングへ寄せるのが早いです🏃💨
5️⃣ ミニ演習:30分で「開発ループ完成」🎮✨
🧪 演習1:再起動が走ることを確認する
docker compose up(ログが流れて起動したらOK)src/index.tsの適当なログ文字列を変える(例:console.log("hello"))- 保存
- コンテナログに「再起動っぽい動き」が出たら成功🎉
🧪 演習2:わざと壊して復旧する(超重要💪)
- 監視ツールを止めてみる(例:
command:をnpm run startにする) - 変更が反映されないのを確認
npm run devに戻す → 「どこが担当か」を体で覚えるやつです🧠✨
6️⃣ よくある落とし穴まとめ🕳️🐾
node_modulesをホストと共有して地獄 → volumeへ避難(今回の構成がそれ)✅- “ファイルは更新されてるのに再起動しない” → 監視ツールの問題(
tsx watch/nodemon -Lへ)✅ - Windowsで重い → WSL 2エンジン、置き場所の見直し✅ (Docker Documentation)
7️⃣ 次に繋がる話🚀
この章は「アプリ側の監視(ホットリロード)を完成させる」がテーマでした🔥 次は、Compose側がファイル変更を見て同期やリビルドまで面倒を見る「Compose Watch」に進むと、さらに楽になります👀✨ (Docker Documentation)
必要なら、この第21章用に「app + worker 両方にホットリロードを入れた compose.yaml(重複を減らした版)」も、すぐ教材として貼れる形で出しますよ😄💡