第22章:node_modulesは“共有しない”が基本(開発体験が爆速に)🚫📁⚡️
開発コンテナが遅いとき、だいたい 「node_modules をホストと共有しちゃってる」 のが犯人です😵💫 ここを直すだけで、起動・ホットリロード・テストが一気に軽くなることが多いよ〜🏎️💨
✅ この章でゴールにすること 🎯✨
- ソースコードは共有(編集したらすぐ反映✍️)
- node_modules は共有しない(大量の小ファイル地獄を回避🧟♂️)
- 依存はボリュームに置く(コンテナ内ファイルシステム側で爆速化💥)
1) なんで node_modules を共有すると遅くなるの?🐢💦
node_modules は、とにかく ✅ ファイル数が多い ✅ 小さいファイルが多い ✅ 「存在チェック(stat)」みたいな I/O が多い …ので、ホスト共有(bind mount)に弱いです😇
特に Windows の場合、コンテナは VM 上で動くので、ホスト共有は仕組み的に不利になりがちです。そこで ボリューム(VM 側に置く) が効きます💪 「named volume がパッケージフォルダ(node_modules)に向いてる」って話も、VS Code のガイドにハッキリ書かれてます。(code.visualstudio.com)
さらに WSL2 環境だと、Docker 公式は「Linux 側のファイルシステムに置いたものを bind mount するのが速い」「/mnt/c(Windows側)を避けよう」と明言してます。(Docker Documentation)
2) 図でイメージを掴もう 🧠📉
(遅くなりがち)
Windows上のフォルダ ──(共有/ bind mount)──> Docker DesktopのVM ──> コンテナ
↑node_modules(大量の小ファイル)をここに置くと、I/Oで詰まりやすい🐢
(速くなりやすい)
node_modules を “Dockerのボリューム” に置く
Dockerのボリューム(VM内/ext4) ───────────────> コンテナ
↑ここは大量小ファイルに強い💥
3) 最短の結論:ソースは共有、node_modules はボリュームへ ✅📦
やり方は2パターンあります👇 おすすめは B(名前付きボリューム)。見通しが良くて管理しやすいです🧹✨
A. “匿名ボリューム”で node_modules だけ逃がす(最短)🏃♂️💨
services:
app:
build: .
working_dir: /app
volumes:
- .:/app
- /app/node_modules
command: npm run dev
- 2行目の /app/node_modules は「コンテナ側にボリュームを作ってそこへマウント」という意味です(ホストとは共有しない)🛟
B. “名前付きボリューム”で node_modules を固定(おすすめ)🏆✨
services:
app:
build: .
working_dir: /app
volumes:
- .:/app
- node_modules:/app/node_modules
command: npm run dev
volumes:
node_modules:
- Compose の「トップレベル volumes」は公式リファレンスにあります。(Docker Documentation)
- さらに Docker は「ボリュームはコンテナの中身で初期化される」特性があり、初回に依存をコピーしてくれる挙動と相性が良いです。(Docker Documentation)
4) Dockerfile 側のコツ(依存は“イメージ側”で入れておく)🔧📦
ボリュームは 最初は空 なので、まずイメージ内で依存を入れておくとスムーズです✨
FROM node:lts
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npm","run","dev"]
ポイント:Compose で「.:/app」をマウントすると、コンテナ内の /app はホストで上書きされます。 だからこそ /app/node_modules だけ別ボリュームで守る のが効く!🛡️🔥
5) ありがちな落とし穴(ここだけ避ければ勝ち)🕳️😱
落とし穴①:依存を追加したのに反映されない 📦➕➡️❓
ホストの package-lock.json / package.json を変えても、node_modules ボリュームは自動で更新されません。
✅ 対処:依存を変えたらコンテナ内で入れ直す
docker compose exec app npm ci
落とし穴②:うっかり「down -v」で全部消える 🧨💥
docker compose down -v
これをやると ボリュームごと消えるので、次回起動で依存を作り直しになります😭 (掃除したいときは便利だけど、普段は注意!⚠️)
落とし穴③:WSL の “高速共有機能” を当てにしちゃう 🎣
「Synchronized file shares(高速同期)」って仕組みもあるんだけど、公式ドキュメントに “WSLでは使えない” と明記されています。(Docker Documentation) しかも .syncignore の例に「node_modules みたいな巨大ディレクトリは除外しよう」が出てくるくらい、重い代表です😂(Docker Documentation)
6) 🧪ミニ演習:体感で“速い”を掴む(10分)⏱️✨
Step 1: まずは改善版 Compose(B)を入れる 🛠️
上の「B. 名前付きボリューム」の compose にする。
Step 2: 初回ビルド&起動 🚀
docker compose up --build
Step 3: node_modules がボリューム側にあるか確認 👀
docker compose exec app ls -la /app/node_modules | head
Step 4: 依存追加→反映の流れを作る 🔁
docker compose exec app npm ci
「編集は速いのに、node_modules のせいで遅い」が消えたら成功!🎉🎉🎉
7) 🤖AI活用:レビュー&事故防止プロンプト集 🧠✨
プロンプト①:compose の volume 設計レビュー
- 「この docker compose の volumes 設計で、Windows 環境で遅くなる可能性がある箇所を3つ挙げて。改善案もセットで。」
プロンプト②:node_modules が消える/空になる原因特定
- 「コンテナ内の node_modules が空になる典型原因を、今回の compose 構成を前提にチェックリスト化して。」
プロンプト③:依存更新フローの自動化案
- 「package-lock.json が変わったら npm ci を実行する運用にしたい。安全で分かりやすい手順(コマンド/スクリプト案)を提案して。」
✅ まとめ(この章の“勝ちパターン”)🏁✨
- ソース:共有してOK ✍️
- node_modules:共有しない(ボリュームへ) 🚫📁
- 依存更新:変更したらコンテナ内で npm ci 🔁📦
これだけで「なんか遅い…😩」が、かなりの確率で「え、軽っ!?😳✨」になります。
次の章(第23章)で Compose Watch と組み合わせると、さらに “再ビルド地獄” から抜けられるよ〜👀🔁🔥