Open6

Docker、Next.jsでの環境構築メモ

atnuhsatnuhs

node_modulesをホストとコンテナで分離する重要性

Node.jsアプリケーションをDockerコンテナ内で開発する際、node_modulesディレクトリの取り扱いは非常に重要である。

なぜnode_modulesを同期させてはいけないのか

  1. プラットフォーム非互換性の問題

    • ローカル環境(Windows/macOS)でホスト側でnpm installを実行すると、そのOS向けにビルドされたバイナリモジュールがnode_modules配下に作成される
    • コンテナ内はLinux環境であるため、これらのバイナリモジュールは互換性がなく、正常に動作しない
    • 特にネイティブ拡張機能を持つモジュール(sharp, node-sass, bcryptなど)で顕著に問題が発生する
  2. パフォーマンスの問題

    • node_modulesには非常に多数の小さなファイルが含まれており、ボリュームマウントで同期すると著しいI/Oオーバーヘッドが発生することがある
    • 特にWindowsやmacOSではパフォーマンス低下が顕著になる場合がある

解決策

1. node_modulesを名前付き/匿名ボリュームで保持する(Volume Trick)

volumes:
  - ./frontend:/app
  - /app/node_modules  # 匿名ボリューム

メリット:

  • シンプルな設定で実装できる
  • ほとんどのDocker環境で動作する

デメリット:

  • package.jsonに変更があった場合、明示的にボリュームを削除する必要がある
  • 更新の度にdocker compose down -vdocker 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

参考

https://zenn.dev/maybe_dog/articles/bfeeee3b6650a1
https://developer.hatenastaff.com/entry/2023/10/13/120000
https://docs.docker.com/compose/how-tos/file-watch/

atnuhsatnuhs

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

まとめ

コードに変更があった場合のコンパイルは著しく時間がかかっている

atnuhsatnuhs

空のnode_modulesがrootユーザーで作られた