Skip to main content

第45章:RUN(依存インストールの基本)📥

(Todo API を Dockerfile で動かすための “依存インストール回” だよ!😆)


この章のゴール🏁

  • Dockerfile の RUN が「ビルド中に実行されて、レイヤー(キャッシュ)になる」感覚をつかむ🧠✨
  • Node/TS の依存を 速く・再現性高く 入れられるようになる(=npm ci を使いこなす)🚀
  • 「なぜ毎回依存の再DLが起きるの?」を卒業する🧯🙂

1) RUN って何者?🤔⚙️

RUNイメージを作る最中(docker build中)に コマンドを実行する命令だよ💡 しかも RUN の結果は レイヤーとして保存されて、次回ビルドのキャッシュになるのが超重要!🔥

  • RUN:ビルド時に実行(依存インストール、ビルド、OSパッケージ追加など)🧱
  • CMD:コンテナ起動時に実行(起動コマンド)▶️(これは次章でやる!)

2) まず “正しい型” を覚える:依存は 先に 入れる📦➡️

Dockerfileの依存インストールで一番効くコツはこれ👇

依存ファイル(package.json / lock)だけ先にCOPYそこで npm ci してキャッシュを効かせる最後にソースコードをCOPY

こうすると「コードだけ変えた」ビルドで、依存が再インストールされにくくなる🎉 (Docker公式ブログでも、package*.json を先にCOPYして npm ci のレイヤーをキャッシュに乗せる流れが紹介されてるよ)(Docker)


3) npm install じゃなくて npm ci を使う理由🧪✅

結論:Dockerビルドでは npm ci が強い💪✨

npm ci はこんな性質👇

  • package-lock.json(またはshrinkwrap)が必須(docs.npmjs.com)
  • lock と package.json がズレてると 失敗して止まる(勝手に直さない)(docs.npmjs.com)
  • 既存の node_modules があれば 消してからクリーンに入れ直す(docs.npmjs.com)

つまり、毎回“同じ依存”を入れやすい=Docker向き🥳


4) ハンズオン:Todo API 用 Dockerfile(依存インストールの基本形)🛠️🐣

✅ いちばん素直な例(npm + lockfile)

## syntax=docker/dockerfile:1
FROM node:22-slim

WORKDIR /app

## 1) 依存ファイルだけ先に入れる(ここがキャッシュの要)
COPY package.json package-lock.json ./

## 2) 依存インストール(再現性優先)
RUN npm ci

## 3) その後でソースを入れる
COPY . .

## (CMDは次章で詳しく!ここでは仮)
CMD ["npm", "run", "dev"]

ポイントは # syntax=... の1行! これを入れると BuildKit が 最新安定の Dockerfile 構文を使ってくれる(後で出てくる RUN --mount=... も安定しやすい)(Docker Documentation)


5) ビルド爆速化:BuildKit のキャッシュマウントを使う⚡🧠

依存のDL(npmが落としてくるキャッシュ)を、ビルド間で使い回すと体感が変わるよ😳✨ Dockerfile では RUN --mount=type=cache が使える!(Docker Documentation)

✅ npm のダウンロードキャッシュを残す例

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

COPY package.json package-lock.json ./

RUN --mount=type=cache,target=/root/.npm \
npm ci

COPY . .
CMD ["npm", "run", "dev"]
  • target=/root/.npm は npm のキャッシュ置き場(DLしたtgz等)
  • 「毎回ネットから取り直す」を減らせるから速い🏎️💨 (キャッシュ最適化の考え方自体も Docker Docs にまとまってるよ)(Docker Documentation)

6) devDependencies どうする?(本番だけ軽くしたい時)🎭📦

「本番イメージは devDependencies いらん!」ってなるよね🙂 npm には “dev を省く” --omit=dev があるよ(npm docsに omit の説明あり)(docs.npmjs.com)

✅ 本番向けの依存だけ入れる

RUN --mount=type=cache,target=/root/.npm \
npm ci --omit=dev

⚠️ただし注意:TSのビルドやlintをコンテナ内でやる設計なら、ビルド段階では devDependencies が必要になりがち。 ここは次章以降の「開発用と本番用を分ける」回でキレイに整理できるよ😉🎯(Dockerのマルチステージ推奨もその流れで効いてくる)(Docker Documentation)


7) よくある失敗あるある🪤😵‍💫 → 即効で直す

あるある①:npm ci が「lockfile無いよ!」って怒る😢

原因:package-lock.json が無い(またはコミットされてない) 対処:ローカルで一度 npm install して lock を作り、lockも一緒に管理しよう✅ (npm ci は lockfile 前提)(docs.npmjs.com)


あるある②:npm ci が「package.json と lock がズレてる!」で落ちる💥

原因:誰かが package.json だけ変えて lock を更新してない、など 対処:ローカルで npm install して lock を同期 → その結果をコミット✅ (ズレてたら npm ci はエラーで止まる仕様)(docs.npmjs.com)


あるある③:ネイティブ依存(node-gyp系)でビルド失敗🤯🔧

症状:g++ とか make とか言い出す 対処:OSパッケージを RUN apt-get ... で入れる(必要な時だけ!) BuildKitのキャッシュマウントは apt にも使えるよ🧊(Docker Documentation)

例(必要なときだけね!)👇

## syntax=docker/dockerfile:1
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y --no-install-recommends \
python3 make g++ \
&& rm -rf /var/lib/apt/lists/*

8) 章末ミッション(手を動かそう)🕹️🔥

ミッションA:依存キャッシュが効いてるか確認👀

  1. Dockerfile をこの章の形にする✍️
  2. ビルドする(例)
docker build -t todo-api:run45 .
  1. もう一回ビルドする(速くなるのが理想⚡)
  2. src の中身だけ少し変えてビルド → 依存のステップがキャッシュされてるか確認🎯

9) AI活用(この章に効くやつ)🤖✨

  • 「このDockerfileでキャッシュが効かない原因トップ3を挙げて、修正案も出して」🧠
  • npm ci のエラー文貼る→原因と直し方を “初心者向けに3行で”」🧯
  • 「Todo APIの依存を本番向けに削るなら、dev/prod分離の作戦を2案」🎭

まとめ🎉

  • RUNビルド時に実行され、レイヤーになって キャッシュが命🧱
  • 依存は COPY package*.jsonRUN npm ci の形が基本形✅(Docker)
  • さらに速くするなら RUN --mount=type=cache(BuildKit)でDLキャッシュを使う⚡(Docker Documentation)
  • 本番だけ軽くしたいなら npm ci --omit=dev も選べる📦(docs.npmjs.com)

次は第46章で CMD をちゃんと理解して「起動コマンド設計」に入ろうね▶️😆