メインコンテンツまでスキップ

第12章:ソース共有(bind mount)とnode_modules問題👟🧨

この章、ComposeでNode/TSを開発するときに一番ハマりがちな「node_modulesどうするの?」を、詰まらない型に固定します💪✨ (やることはシンプル:ソースだけ共有/依存はコンテナ側に置く


1) この章でできるようになること🎯✨

  • 保存したら即反映!の開発体験(bind mount)を作れる📝⚡
  • node_modulesが原因の「動かない」「重い」「壊れる」を避けられる🧯
  • 依存関係の更新も、決まった手順で安全に回せる🔁✅

2) まずはイメージ:何を共有して、何を共有しない?🧠🧩

  • bind mount:ホストのフォルダをコンテナに“そのまま見せる”仕組み。保存が即反映されるので開発向き📌 (Docker Documentation)
  • volume:Dockerが管理する保存領域。DBデータやnode_modulesみたいな「大量&OS依存」なものに向いてる📦 (Docker Documentation)

ここで大事なのが👇

共有していいsrc/package.jsontsconfig.json、設定ファイル ❌ 共有しないほうがいいnode_modules/(特にWindows環境だと地雷率UP💣)


3) node_modules問題 “あるある”3連発😇💥

あるある①:コンテナでnpm run devしたら「モジュールが見つからない」😵

原因:.:/appみたいにプロジェクト全体をbind mountすると、イメージ内で作った/app/node_modulesマウントに隠れて見えなくなるやつです🙈

あるある②:ホスト側にnode_modulesが生えてPCが重くなる🪨

原因:コンテナのnpm installが、bind mount経由でホスト側に書き込むパターン(ファイル数が多すぎて地獄😇)

あるある③:ネイティブ依存(例:bcrypt等)がOS違いで壊れる🧨

原因:Windowsで入れたnode_modulesをLinuxコンテナで使おうとして、バイナリが合わずに爆発💥 → 依存はコンテナ側(Linux側)で入れるのが安定です👍


4) 結論:黄金パターン🏆「ソースはbind mount、node_modulesはvolume」

やることはこれだけ👇✨

  • .:/appでソース共有📝
  • /app/node_modulesだけはnamed volumeにして隔離🧊

これで「即反映」と「依存の安定」を両立できます🔥


5) 実装:compose.yamlに追記しよう🛠️🐳

例:サービス名をapi、作業ディレクトリを/appとします(構成は適宜読み替えOK🙆‍♂️)

services:
api:
build:
context: .
dockerfile: Dockerfile
working_dir: /app
volumes:
- .:/app
- api_node_modules:/app/node_modules
command: npm run dev
environment:
# 監視が効かない/遅い時の保険(必要になったらON)
# CHOKIDAR_USEPOLLING: "true"
# CHOKIDAR_INTERVAL: "250"
NODE_ENV: development

volumes:
api_node_modules:

ポイントはここ👇👀

  • - .:/app(ソース共有)
  • - api_node_modules:/app/node_modules(依存を隔離) この2つの“合わせ技”が最強です🏆

6) 依存を入れる:最初に1回だけnpm ci(推奨)📦⚡

named volumeは最初は空なので、最初に依存を入れます。

docker compose run --rm api npm ci
  • npm ciはロックファイル前提で再現性が高いので教材向き👍
  • その後は普通に起動👇
docker compose up

7) 依存を更新したときの“儀式”🔁✨(固定手順)

package.jsonやロックファイルを変更したら、これだけでOK👇

docker compose run --rm api npm ci
docker compose up

「依存が変わったらこの2行」って覚えると、事故りにくいです🧯✅


8) Windowsでハマりやすい“速度&監視”の話🪟🐢➡️🐇

bind mountは便利だけど、Windowsだと ファイルの置き場所で体感が激変します⚠️

  • Linuxコンテナにbind mountするコードは、可能なら WSL2側のLinuxファイルシステムに置くと速い&変更検知もしやすいです🏎️💨 (Docker Documentation) (Docker DesktopのWSL2ベストプラクティスで明言されています📌)

もし「保存しても反映されない」「監視が不安定」なら、まずここを疑うのが近道です🔎✨ (Docker Documentation)


9) よくあるトラブルと直し方🧯🛠️

Q1. Cannot find module ... が出る😵

✅ まずこれ👇(だいたい“volumeが空”)

docker compose run --rm api npm ci

Q2. node_modulesがホスト側にできて困る😇

compose.yaml/app/node_modulesvolumeになってるか確認👀 (- api_node_modules:/app/node_modules が必要)

Q3. ホットリロードが効かない/遅い🐢

✅ まず「コードの置き場所」を見直し(WSL2側が強い) (Docker Documentation) ✅ 次に保険として polling をON(上のCHOKIDAR_USEPOLLING)🔁 ※ pollingは効くけどCPU増えがちなので、最後の手段でOK👌


10) AIに手伝わせるコツ🤖🧠(短くて効く指示)

「たたき台を出させて、人間がチェック」がおすすめです✅ 例(そのまま貼ってOK)👇

docker composeでNode(TypeScript)開発環境を作っています。
要件:
- ソースはbind mountで即反映
- node_modulesはコンテナ側に隔離(named volume)
- 依存更新は docker compose run --rm api npm ci で行いたい
compose.yamlの volumes 構成と、落とし穴チェックリストを提案して

11) ミニ演習🎒✨(理解が爆速になる)

演習A:わざと壊して直す💥➡️✅

  1. api_node_modules:/app/node_modules を一旦消す
  2. 起動してエラーを見る
  3. もう一回戻して、npm ciで復活させる

「何が原因で何が効くか」が一発で腹落ちします😋

演習B:依存を追加して儀式を回す➕🔁

  1. 何か1つ依存を追加(例:zodなど)
  2. ロックファイル更新
  3. docker compose run --rm api npm cidocker compose up

12) まとめ:この章の“合言葉”🧠✨

  • **ソースは共有(bind mount)**📝
  • **依存は隔離(volume)**📦
  • **依存更新はdocker compose run --rm ... npm ci**🔁

この型にしておくと、次の「サービス間通信」「起動順」「マイグレーション自動化」もスムーズに進みますよ〜🚀🔥


必要なら、あなたの第11章のDockerfile/フォルダ構成(例:apps/apiみたいな形)に合わせて、この章のcompose.yamlを“実物ベース”に最適化した版も作れます🙆‍♂️✨