Skip to main content

第56章:依存関係トラブル(モジュールが無い/バージョン違い)📦💥

この章は「依存の事故」を“怖いもの”から“作業で直せるもの”に変える回です😆✨ Node/TypeScript+Dockerで起きがちな依存トラブルは、だいたい パターンが決まってます。なので「型」を覚えれば勝ちです🏆


この章のゴール🎯

  • 「モジュールが無い」「バージョン違い」「動くはずが動かない」を 分類できる🧠
  • 最短の切り分け手順で、原因に当たりをつけられる🔍
  • 再発防止(ロックファイル・Dockerfile・チーム運用)まで一気に固める🛡️✨

1) 依存トラブル “あるある” 6パターン😵➡️🙂

A. Cannot find module 'xxx'(モジュールが無い)🚫📦

よくある原因

  • node_modules が存在しない / 空(マウントで上書きされて消えてる等)
  • コンテナ内で install してない
  • 依存の種類(dependencies/devDependencies)で本番向けに削られてる

B. npm ci が落ちる(ロックファイル不一致)🔒⚠️

npm ci は **「ロックファイルが合ってないと即エラー」**の厳しめコマンドです。(docs.npmjs.com) (CIやDockerビルドで “同じ結果を再現する” 目的で使うやつ)


C. Nodeのバージョン違いで壊れる🧨🧊

  • engines やライブラリ側の要件に合ってない
  • ローカルはNode 24、コンテナはNode 20…みたいなズレ

ちなみに本日時点では Node 24 が Active LTS(本番向けの推奨枠)で、Node 25 は Current です。(Node.js)


D. ネイティブ依存が死ぬ(node-gyp / sharp / bcrypt系)🛠️💥

  • Linuxコンテナ内でビルドが必要(ビルドツール不足)
  • ホスト(Windows)で入れた node_modules をコンテナで使おうとして壊れる(OS違い)

E. peerDependencies 地獄(依存の要求が噛み合わない)😇🔥

  • インストールは通るけど実行で死ぬ
  • あるいは新しめのnpmだとインストール時に怒られる

F. monorepo / workspaces / Yarn PnP など構造が特殊🧩🌀

  • workspaceリンクがコンテナ内で再現できてない
  • Yarn PnPだと node_modules 前提のツールが落ちることがある(設定で回避することも多い)

2) 依存トラブルの“最短切り分けフロー”🚑🔍(まずこれだけでOK)

困ったら、この順で見るだけでだいぶ勝てます😌✨

Step 0:エラー文の “型” を判定🧾

  • Cannot find moduleAへ
  • npm ci / pnpm install --frozen-lockfile が落ちる → Bへ
  • engines / Node要求 → Cへ
  • gyp / ELIFECYCLE / sharpDへ
  • peer dep / ERESOLVEEへ
  • workspaces/pnp → Fへ

Step 1:コンテナ内で「node と npm(等)」の状態確認🔦

(“ホストで動く” は今は関係ないです。コンテナが真実👑)

docker compose exec api node -v
docker compose exec api npm -v
docker compose exec api ls -la
docker compose exec api ls -la node_modules | head

Step 2:依存ファイル3点セットを見る👀

  • package.json
  • ロックファイル(package-lock.json / pnpm-lock.yaml / yarn.lock
  • .npmrc.yarnrc.yml(ある場合)

Step 3:インストール方法が「再現可能」か確認🧊

  • DockerビルドやCIでは ロックファイル固定が基本 npm ci はロックファイル必須で、合ってないとエラーになります。(docs.npmjs.com)
  • pnpm もCI環境だとロックファイル更新が必要な状態だと失敗する挙動があります。

3) ハンズオン:わざと壊して直す(最強の練習)💣➡️🛠️✨

ここからが本番😆 「Todo API(apiサービス)」がある前提で、Composeのサービス名を api とします。(違ってたら読み替えOK🙆)


ハンズオンA:Cannot find module を再現→復旧📦🚫➡️✅

1) わざと壊す(node_modulesを消す)💥

docker compose exec api sh -lc "rm -rf node_modules && node -e \"require('express')\""

たぶんこんな感じで落ちます👇 Error: Cannot find module 'express' 😵

2) 原因の当たり🎯

  • コンテナに node_modules が無い (または マウントが node_modules を上書きして空にしてる)

3) 直し方(基本ルート)🛠️

開発コンテナなら:コンテナ内で install するのがまず正解🙆

docker compose exec api npm install
## もしくは pnpm install / yarn install

4) もう一歩(再発防止)🛡️

  • node_modules をホスト共有しない(Windows↔Linuxの相性事故を避ける)
  • node_modules はコンテナ内に“置く”方針に寄せる

ハンズオンB:npm ci ロック不一致を再現→復旧🔒⚠️➡️✅

1) わざとズラす😈(package.jsonだけ変更してロックを更新しない)

例:package.json に依存を追加(手で1行足すだけでOK)

2) npm ci を実行して落とす💥

docker compose exec api npm ci

npm ci は「ロックとpackage.jsonがズレてたらエラーで止まる」仕様です。(docs.npmjs.com)

3) 直し方(2択)🧭

  • A:正しく更新する(本番)

    • npm install してロックを更新 → そのロックをコミット
  • B:変更を戻す(実験だったなら)

    • package.json を元に戻す

ハンズオンC:Nodeバージョン違い事故を防ぐ🧊🧯

1) まず “Nodeを揃える” が最強の予防🧠

本日時点では Node 24 が Active LTS(本番向け推奨枠)なので、Dockerfileのベースもそこに寄せるのが安全です。(Node.js)

2) Dockerfileの基本形(依存キャッシュも効かせる)🚀

Dockerビルドで依存が毎回再インストールされると、事故も増えます😵 Docker公式は「依存ファイルだけ先にCOPYして install を前段に置く」のを推奨しています。(Docker Documentation)

## syntax=docker/dockerfile:1
FROM node:24-slim
WORKDIR /app

## 依存ファイルだけ先に
COPY package.json package-lock.json ./

## キャッシュも使う(BuildKit)
RUN --mount=type=cache,target=/root/.npm npm ci

## ソースは後で
COPY . .
CMD ["npm","run","dev"]

ポイント👇


ハンズオンD:pnpm / corepack での“地雷”を理解する🤹‍♂️💥

pnpmをDockerで使うノウハウはpnpm公式にもまとまってて、BuildKitのキャッシュマウント例も出ています。(pnpm)

ただし!ここで超重要ニュース📣 Corepackは Node 25 から同梱されなくなります。(Node.js) (Node 24以前では“実験機能”で、明示的に corepack enable が必要です)(Node.js)

つまり👀

  • コンテナが node:25 だと「corepack前提のDockerfile」が壊れる可能性あり
  • 安全に行くなら、LTS(例:node:24)に寄せるのがラク

pnpm公式のDocker例では corepack enable+キャッシュマウントを使っています。(pnpm)


4) 「再発防止策」テンプレ集🛡️✨(ここが一番おいしい)

✅ 依存事故を減らす三種の神器

  1. ロックファイルを必ずコミット(再現性の心臓)❤️

  2. Dockerfileで依存installを先にしてキャッシュを効かせる(事故と時間を削る)🚀(Docker Documentation)

  3. CI/ビルドは“凍結インストール”

    • npm:npm ci(ロック不一致なら止まる)(docs.npmjs.com)
    • pnpm:pnpm install --frozen-lockfile(ロック更新が必要なら失敗しやすい)

✅ “モジュールが無い”を二度と起こしにくくする

  • node_modules をホスト共有しない(OS差で壊れる率が上がる)🧨
  • .dockerignorenode_modules を入れて、ビルドコンテキストにも載せない🧹 (Docker公式でも node_modules を無視する例が出ています)(Docker Documentation)

✅ 依存更新ルール(超シンプル版)🧾✨

  • 依存を追加/更新したら

    1. ローカルで npm install(またはpnpm/yarn)
    2. テスト
    3. ロックファイルの差分を必ずコミット
  • Docker/CIは npm ci で“同じ結果”を作る(docs.npmjs.com)


5) AI(Copilot / Codex)に頼むと強い質問テンプレ🤖💬✨

そのまま貼ってOK🙆

エラー解析テンプレ

  • 「このログを A/B/C/D/E/F のどれに分類できる?理由も1行で」
  • 「原因候補トップ3と、確認コマンドを順番に出して」

再発防止テンプレ

  • 「このDockerfile/composeで依存事故を減らす改善案を3つ。優先度付きで」
  • 「ロックファイル運用ルールを“短いチームルール”に整形して」

6) ミニチェック(3問)📝✨

  1. npm cinpm install と違う一番のポイントは?(ヒント:ロック)(docs.npmjs.com)
  2. Dockerfileで COPY . . を先にすると、何が遅くなりがち?(ヒント:キャッシュ)(Docker Documentation)
  3. Node 25で corepack enable 前提のDockerfileが壊れうるのはなぜ?(Node.js)

まとめ🏁🎉

依存トラブルは「発生→調査」じゃなくて、**“型で分類→最短確認→復旧→再発防止”**で勝てます💪😆 特にこの章のキモは👇

  • npm ci / --frozen-lockfile の“凍結インストール”を理解する🔒(docs.npmjs.com)
  • Dockerfileの順番とキャッシュで、事故と時間を減らす🚀(Docker Documentation)
  • Nodeの世代(LTS)と corepack の変化を踏む🧊(Node.js)

次の第57章は「権限トラブル」🔒😣 依存と並ぶ“事故の双璧”なので、ここまで来たらかなり強いです💪🔥