Skip to main content

第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 と組み合わせると、さらに “再ビルド地獄” から抜けられるよ〜👀🔁🔥