Open1
Docker の Node バージョンと、local の Nodeバージョンを合わせる必要はあるかどうか📝

Docker の Node バージョンと、local の Nodeバージョンを合わせる必要はあるかどうか📝
結論から言うと 「絶対に同じにしなければ動かないわけではないが、node_modules
をホストとコンテナで共有する場合は“ほぼ同じ(少なくともメジャーバージョンは一致)にしておくほうが安全” です。理由と対処方針を整理します。
1. 何が起こるか
ケース | 影響 | 詳細 |
---|---|---|
純粋な JS パッケージのみ (ネイティブアドオンなし) |
多少のバージョン差なら動くことが多い | Node の ABI を使わないため。ただし package-lock.json の生成物が変わるので lock ファイルの差分が頻発する。 |
バイナリ/ネイティブアドオンを含むパッケージあり (node-gyp, bcrypt, sharp など) |
ほぼ確実に壊れる | ホスト側でビルドされたネイティブコードは「Node の ABI version × OS × CPU」で固有。Docker(Linux) と macOS/Windows で食い違う or Node のメジャーが違うと読み込めない。 |
npm scripts で Node API を呼ぶ (例: node --watch , ESM loader) |
動作差・エラーの可能性 | 17→18 で --watch が入り、20 で ESM Loader 周りが変わる…など CLI オプション差異による失敗が起きる。 |
2. ベストプラクティス
-
node_modules
は基本的にコンテナ内で完結させる-
共有したいのはソースコードだけにし、
node_modules
やpackage-lock.json
の書き込み先は volume にマッピングしない。 -
例:
volumes: - ./:/app # ソースだけ - /app/node_modules # node_modules は匿名ボリューム(ホストに出さない)
-
-
Node のバージョンを 1 か所で定義して合わせる
-
Dockerfile
と.nvmrc
/.node-version
を同じ値に。 - チーム開発なら
engines.node
をpackage.json
に書き、"engine-strict": true
(npm)やvolta
を使うと揃えやすい。
-
-
どうしても共有したい場合の最低条件
- OS が同じ(例: WSL2 で Linux⇔Linux)
- Node のメジャーバージョンが一致(ABI 互換を保てる)
- それでもネイティブアドオンがあると壊れるので、
npm rebuild
かnpm ci
をコンテナ側で一度は実行する。
3. よくある運用フロー
# 1) ホストでソースを編集
# 2) コンテナへアタッチまたは docker compose exec
npm ci # コンテナ内で依存をインストール
npm run dev # コンテナ内で開発サーバー起動
こうしておけばコンテナが Node の実行環境を完全に担うため、ホストの Node は「エディタ補完や軽いスクリプト用」と割り切れます。
4. まとめ
- lock ファイルのノイズを減らし、ネイティブアドオン事故を防ぐには「node_modules を共有しない」+「Node バージョンを揃える」 が鉄板。
- もし共有するなら メジャーバージョン一致は必須、さらにコンテナ内で必ず
npm rebuild
して ABI を合わせる。