第28章:遅いを潰す(キャッシュ/依存/ビルド分離)🏎️💥
「遅い…😇」って一言で言っても、だいたい原因はこの3つのどれかです👇
- ビルドが遅い(
docker compose buildが長い)🧱🐢 - 依存インストールが遅い(毎回
npm install祭り)📦🔥 - 開発ループが遅い(保存→反映が遅い、watchが効かない)👀💤
この章は、体感が一気に変わるやつだけに絞って、順番に直します💪✨
1) まずは「どこが遅いか」を10秒で見える化👀🕒
✅ ビルド時間の見える化(おすすめ)
docker compose build --progress=plain
- どのステップ(
COPY/RUN npm ci/RUN npm run buildなど)が時間食ってるか分かります🍱
✅ ありがちな“遅いポイント”あるある
COPY . .が早い段階に来てて、ちょっとファイル変えただけでキャッシュ全崩壊💣.dockerignoreが無くて、巨大フォルダを毎回送り付けてる📦📦📦- 依存が変わってないのに、毎回フルインストール🌀
- Windowsのファイル共有で、マウントが重い🐘(※後半で対策)
2) 速くする “即効薬” ベスト5💊⚡
.dockerignoreを入れてビルドコンテキストを小さくする🧹- Dockerfileの順番を変えて「依存キャッシュ」を最大化📦✨
- BuildKitの cache mount で npm/pnpm のDLを高速化🚀
- マルチステージ +
targetで「開発用」と「本番用」を分離🧩 - **
cache_to/cache_fromでキャッシュを外部化(チーム/CI向け)**🧠
この5つは全部、Docker公式が推してる方向性に沿ってます。特に cache mount と 外部キャッシュは超効きます💥 (Docker Documentation)
3) .dockerignore:まずこれ入れよう🧹📄
.dockerignore があるだけで、ビルドに送る荷物が減ってビルドが軽くなります📦➡️🪶
Dockerはビルド時、コンテキスト直下の .dockerignore を見て不要物を除外します。(Docker Documentation)
✅ 例:Node/TSの定番 .dockerignore
node_modules
dist
coverage
.vscode
.git
.gitignore
Dockerfile*
compose*.yml
compose*.yaml
*.log
.tmp
.cache
ポイント👉
node_modulesは絶対送らない(重い&OS差で地雷💣)
4) Dockerfileの「順番」だけで世界が変わる🌍✨
😇 いちばんやりがちな“遅いDockerfile”
FROM node:24-slim
WORKDIR /app
COPY . .
RUN npm install
CMD ["npm", "run", "dev"]
これ、ソース1文字変えただけで npm install やり直しになります😭
なぜなら COPY . . が依存キャッシュを全部巻き込むから。
✅ “速いDockerfile”の基本形(依存を先に固める)📦🧱
- 依存に関係するファイル(
package.json/ lockfile)だけ先にコピー - そこでインストール
- 最後にソースをコピー
## syntax=docker/dockerfile:1
FROM node:24-slim AS base
WORKDIR /app
## ① 依存だけ先に
FROM base AS deps
COPY package.json package-lock.json ./
RUN npm ci
## ② 開発用(ソースは後)
FROM base AS dev
ENV NODE_ENV=development
COPY --from=deps /app/node_modules ./node_modules
COPY . .
CMD ["npm", "run", "dev"]
これで何が嬉しい?😆
- 普段の編集(ソース変更)では
npm ciがキャッシュ命中しやすい🎯 - 依存をいじった時だけインストールが走る📦
5) BuildKit cache mount:依存DLをさらに爆速にする🚀📦
Docker公式の “Optimize cache usage” で、RUN --mount=type=cache が推奨されています。
npmのキャッシュディレクトリをBuildKitが保持して、再ビルドで再DLを減らすやつです💡 (Docker Documentation)
✅ npm(.npm キャッシュ)例
FROM base AS deps
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
- 再ビルド時、「毎回ネットから取り直し」が減って体感が変わります⚡ (Docker Documentation)
✅ pnpm派(さらに速いこと多い)🐹💨
pnpmはストア型なので、cache mountと相性よしです(使ってるなら超おすすめ)💎
FROM base AS deps
RUN corepack enable
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,target=/pnpm/store \
pnpm config set store-dir /pnpm/store && \
pnpm install --frozen-lockfile
6) 「ビルド分離」:dev と prod をマルチステージで切り替え🧩🔀
ここができると、開発が軽い&本番がキレイになります✨
✅ Dockerfile:dev/build/prod を分ける(例)
## syntax=docker/dockerfile:1
FROM node:24-slim AS base
WORKDIR /app
FROM base AS deps
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
FROM base AS dev
ENV NODE_ENV=development
COPY --from=deps /app/node_modules ./node_modules
COPY . .
CMD ["npm","run","dev"]
FROM base AS build
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM node:24-slim AS prod
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/dist ./dist
CMD ["node","dist/index.js"]
✅ compose.yaml:target で “devステージ” を使う🎯
ComposeのBuild仕様には target があり、マルチステージのどこをビルドするか指定できます。(Docker Documentation)
services:
api:
build:
context: .
dockerfile: Dockerfile
target: dev
volumes:
- .:/app
- api_node_modules:/app/node_modules
command: npm run dev
volumes:
api_node_modules:
- ソースは共有(bind mount)
- node_modules はコンテナ側に隔離(named volume) → OS差・重さ・壊れやすさをまとめて回避しやすいです🧯✨
7) キャッシュを“外に出す”:cache_to / cache_from 🧠📦
BuildKitのキャッシュは通常ビルダー内部にあり、ビルダーが変わると共有されないことがあります。 なので「外部キャッシュ(local/registry/gha など)」が用意されています。(Docker Documentation)
Compose Build仕様にも cache_from / cache_to があり、キャッシュ共有を定義できます。(Docker Documentation)
✅ 例:ローカルディレクトリにキャッシュ保存(開発PC向け)
services:
api:
build:
context: .
target: dev
cache_from:
- type=local,src=.build-cache
cache_to:
- type=local,dest=.build-cache,mode=max
cache_from/cache_toの書式(type=localなど)は仕様に書かれてます。(Docker Documentation)
💡チーム/CIなら
type=registryやtype=ghaも候補になります(環境次第)(Docker Documentation)
8) Windowsで「マウントが遅い…😇」ときの最強カード🪟🃏
Docker Desktop + WSL2 の場合、Docker公式ブログが **「プロジェクトファイルはWSL2側に置いた方が速い」**と明言しています。(Docker)
- Windows側(
C:\...)をマウントすると、仕組み上どうしても遅くなりがち💤 (Docker) - WSL2側に置くと、inotifyやキャッシュが効いて快適になりやすい⚡ (Docker)
- VS Codeも WSL 拡張で普通に編集できます(ブログ内で触れてます)(Docker)
「なんかwatchが遅い」「反映がワンテンポ遅い」系は、ここで劇的改善しがちです✨✨
9) “キャッシュが効かない”ときのチェックリスト🔎🧯
✅ npm ci が毎回走る…
package-lock.jsonが変わってない?📌COPY . .がnpm ciより前に来てない?💣.dockerignoreで余計なもの送ってない?📦
✅ ビルドが突然遅くなった…
dist/やcoverage/をビルドコンテキストに入れてない?(.dockerignore!)(Docker Documentation)- キャッシュを掃除しすぎてない?(
prune乱発注意)🧨
✅ チームで速度が揃わない…
cache_to/cache_fromを使って“共通キャッシュ”に寄せるのが効きます🧠 (Docker Documentation)
10) 演習(やると体感が変わるやつ)🧪✨
演習1:.dockerignore を入れて、ビルドが軽くなるのを確認🧹
.dockerignoreを追加docker compose build --progress=plain- “Sending build context …” が小さくなる/速くなるのを確認📉
演習2:Dockerfileの順番を直して、依存キャッシュ命中を確認🎯
COPY package*.json→npm ci→COPY . .の順にする- ソースを1文字だけ変更
- もう一度ビルド →
npm ciがスキップ/高速化してたら勝ち🏆
演習3:cache mount を入れて、2回目以降の npm ci を高速化🚀
RUN --mount=type=cache,target=/root/.npm npm ciに変更 (Docker Documentation)- 依存を少し変えてビルド
- もう一度依存を変えてビルド
- “毎回全部DL” が減るのを観察👀
11) AIに手伝わせるなら、この指示が強い🤖🧠
(GitHubのCopilot / OpenAI系ツールにそのまま投げてOK)
- 「このDockerfile、依存キャッシュが最大化される順番に並び替えて」🧱✨
- 「BuildKitのcache mount を使って npm/pnpm を速くして」🚀📦 (Docker Documentation)
- 「compose.yamlで target を使って dev/prod を切り替える例もつけて」🎯 (Docker Documentation)
- 「
.dockerignoreのおすすめも作って」🧹 (Docker Documentation)
⚠️ AIがたまにやる地雷:
COPY . .を前に置く/秘密情報をイメージに焼く/node_modulesをホスト共有する、みたいなのはレビューで弾いてね🧯🙂
おまけ:Nodeの“いま”の目安📌🟩
ベースイメージを選ぶとき、Nodeのサポート状況を知っておくと安心です。 2026年2月時点だと v24 が Active LTS、v25 が Current になってます(公式表)。(Node.js)
この章のまとめ🎬✨
.dockerignore🧹- Dockerfileの順番最適化(依存→ソース)📦
- BuildKit cache mount 🚀 (Docker Documentation)
- マルチステージ +
targetでdev/prod分離🎯 (Docker Documentation) - 必要なら
cache_to/cache_fromでキャッシュ共有🧠 (Docker Documentation) - Windowsでマウントが重いならWSL2配置が効きやすい🪟⚡ (Docker)
次の章(第29章)は、ここで整えた「速い土台」を使って、AIにCompose設計を手伝わせる“安全運用テンプレ”に入っていけます🤖📚