Open6
Docker、Next.jsでの環境構築メモ
node_modulesをホストとコンテナで分離する重要性
Node.jsアプリケーションをDockerコンテナ内で開発する際、node_modules
ディレクトリの取り扱いは非常に重要である。
なぜnode_modulesを同期させてはいけないのか
-
プラットフォーム非互換性の問題
- ローカル環境(Windows/macOS)でホスト側で
npm install
を実行すると、そのOS向けにビルドされたバイナリモジュールがnode_modules
配下に作成される - コンテナ内はLinux環境であるため、これらのバイナリモジュールは互換性がなく、正常に動作しない
- 特にネイティブ拡張機能を持つモジュール(sharp, node-sass, bcryptなど)で顕著に問題が発生する
- ローカル環境(Windows/macOS)でホスト側で
-
パフォーマンスの問題
-
node_modules
には非常に多数の小さなファイルが含まれており、ボリュームマウントで同期すると著しいI/Oオーバーヘッドが発生することがある - 特にWindowsやmacOSではパフォーマンス低下が顕著になる場合がある
-
解決策
1. node_modulesを名前付き/匿名ボリュームで保持する(Volume Trick)
volumes:
- ./frontend:/app
- /app/node_modules # 匿名ボリューム
メリット:
- シンプルな設定で実装できる
- ほとんどのDocker環境で動作する
デメリット:
-
package.json
に変更があった場合、明示的にボリュームを削除する必要がある - 更新の度に
docker compose down -v
とdocker compose up --build
が必要
2. Compose Watchを使う(推奨)
develop:
watch:
- action: sync
path: ./frontend
target: /app
ignore:
- node_modules/
- .next/
- action: rebuild
path: ./frontend/package.json
メリット:
-
package.json
の変更を検知して自動的に再ビルド - 手動での
down -v
や--build
が不要
使用方法
docker compose watch
参考
VSCodeでnode_modulesを参照できない問題
1. Dev Containersという拡張機能を使う
ホスト側でコードは編集せず、コンテナ内を直接エディタで編集する
2. Docker Compose Watch
ローカルで編集する
WSL2、Docker、Next.jsでturbopackを使うとコンパイルが遅くなった
状況
- VS Codeを使用しローカルでソースコードを編集
- Docker Compose Watchでコンテナ内のソースコードと同期させる
Webpackの場合
package.json
"scripts": {
"dev": "next dev",
...
},
コンテナ内のログ
2025-04-01 20:57:32 app-1 | ✓ Compiled in 812ms (711 modules)
2025-04-01 20:57:32 app-1 | GET / 200 in 113ms
2025-04-01 20:57:41 app-1 | ✓ Compiled in 625ms (711 modules)
2025-04-01 20:57:41 app-1 | GET / 200 in 70ms
2025-04-01 20:57:45 app-1 | ✓ Compiled in 643ms (711 modules)
2025-04-01 20:57:45 app-1 | GET / 200 in 39ms
2025-04-01 20:57:53 app-1 | ✓ Compiled in 514ms (711 modules)
2025-04-01 20:57:53 app-1 | GET / 200 in 37ms
2025-04-01 20:58:00 app-1 | ✓ Compiled in 754ms (711 modules)
2025-04-01 20:58:01 app-1 | GET / 200 in 45ms
2025-04-01 20:58:02 app-1 | ✓ Compiled in 523ms (711 modules)
2025-04-01 20:58:02 app-1 | GET / 200 in 48ms
2025-04-01 20:58:08 app-1 | ✓ Compiled in 656ms (711 modules)
2025-04-01 20:58:08 app-1 | GET / 200 in 95ms
かかる時間
500ms ~ 800msかかっている
Turbopackの場合
package.json
"scripts": {
"dev": "next dev --turbopack",
...
},
コンテナ内のログ
2025-04-01 21:05:02 app-1 | ✓ Compiled / in 16ms
2025-04-01 21:05:06 app-1 | GET / 200 in 3464ms
2025-04-01 21:05:18 app-1 | ✓ Compiled / in 20ms
2025-04-01 21:05:21 app-1 | GET / 200 in 3516ms
2025-04-01 21:05:29 app-1 | ✓ Compiled / in 14ms
2025-04-01 21:05:33 app-1 | ✓ Compiled in 3.5s
2025-04-01 21:05:33 app-1 | GET / 200 in 3729ms
2025-04-01 21:05:35 app-1 | ○ Compiling /search ...
2025-04-01 21:05:36 app-1 | ✓ Compiled /search in 1871ms
2025-04-01 21:05:36 app-1 | GET / 200 in 3350ms
かかる時間
16ms ~ 3500ms
まとめ
コードに変更があった場合のコンパイルは著しく時間がかかっている
空のnode_modulesがrootユーザーで作られた
参考
公式のサンプル