Contents
1. イメージのレイヤー構造がサイズに与える影響
- Dockerfile の各命令 (
FROM,RUN,COPY,ADD…) は 新しい読み取り専用レイヤー を生成します。 - 各レイヤーは「差分」だけを保持するため、イメージ全体のサイズは すべてのレイヤーの合計 です。
- Docker Hub の統計(2025‑2026 年)では、
node:22系イメージの平均レイヤー数は 12 層、総容量は ≈1.2 GB【Docker Hub Stats, 2025】。
ポイント:不要なレイヤーが増えると、ビルドキャッシュ・プッシュ/プル時の転送量が比例して増大します。
簡易イメージ例(従来型)
|
1 2 3 4 5 6 |
FROM node:22 # ベースレイヤー COPY package.json . # 1️⃣ レイヤー (package.json) RUN npm ci # 2️⃣ レイヤー (依存インストール) COPY . . # 3️⃣ レイヤー (ソースコード) RUN npm run build # 4️⃣ レイヤー (ビルド成果物) |
- 合計レイヤー:5(ベース + 4)
- 問題点:
npm ci後のキャッシュや一時ファイルが永続化され、サイズ肥大の原因になる。
2. レイヤー削減とビルドキャッシュ除去のベストプラクティス
| 手法 | 効果(目安) | 実装例 |
|---|---|---|
| RUN をチェーン化 | 1 〜 2 層削減、サイズ ≈10‑30 MB 減少 | RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* |
| ビルドキャッシュを即時削除 | 余分なファイルがレイヤーに残らず、+120 MB の増加防止【Reddit, 2025】 | npm cache clean --force, rm -rf /var/cache/apt/* |
| COPY 前に .dockerignore を徹底 | ビルドコンテキストが 1.2 GB → 180 MB、ビルド時間 ≈70% 短縮【Qiita, 2025】 | .dockerignore に node_modules/, test/, .git* を列挙 |
実装の要点(箇条書き)
- RUN
- 複数コマンドは
&& \で連結し、最後にキャッシュ削除を入れる。 - 例:
RUN apt-get update && apt-get install -y build-essential && rm -rf /var/lib/apt/lists/* - COPY・ADD
- 必要最低限のファイルだけをコピーする。
COPY ["package.json","package-lock.json","./"]のように配列構文で明示的に指定すると、不要なサブディレクトリが除外できる。- .dockerignore(重要ポイント)
- バージョン管理系 (
.git,.svn) - ローカルキャッシュ (
node_modules/,*.log) - テスト・ドキュメント (
test/,docs/,*.md)
3. 軽量ベースイメージとマルチステージビルド
3‑1. ベースイメージの選定基準(2025‑2026 年最新データ)
| イメージ | サイズ (公式リポジトリ) | 主な用途・注意点 |
|---|---|---|
node:22-alpine |
≈120 MB | Alpine は musl libc 使用。glibc 依存バイナリは動作しないことがあるので、ビルド時にテスト必須。 |
gcr.io/distroless/nodejs22 |
≈85 MB | 実行ファイルだけを提供。シェルが無いためデバッグは外部ツールで対応。 |
scratch |
0 B (空) | 完全なゼロベース。独自の静的バイナリや Go、Rust の実行ファイル向け。 |
ポイント:公式が提供する「-slim」系はサイズ削減効果が限定的(≈15‑20%)であり、Alpine または Distroless へ置き換える方が 10 倍以上の削減 が期待できる。
3‑2. マルチステージビルドの構造
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# ---------- builder ---------- FROM node:22-alpine AS builder # ビルド専用イメージ (≈120 MB) WORKDIR /app COPY package*.json ./ RUN npm ci --no-progress && npm cache clean --force COPY . . RUN npm run build # 生成物は /app/dist # ---------- runtime ---------- FROM gcr.io/distroless/nodejs22 # 実行専用イメージ (≈85 MB) WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/package.json . RUN npm ci --production --no-progress && npm cache clean --force CMD ["node", "dist/index.js"] |
効果
| 項目 | ビフォア (単一ステージ) | アフター (マルチステージ) |
|---|---|---|
| 合計サイズ | ≈1.2 GB (node:22) |
≈205 MB (builder + runtime の最小化) |
| レイヤー数 | 12+ | 4 (builder) + 3 (runtime) → 実行時は 3 層のみ |
| ビルド時間 | 長い(キャッシュ多数) | 短縮(キャッシュは builder 内で完結) |
4. dev‑dependencies の管理と本番イメージの最適化
- 依存を二段階に分離
- Builder ステージで
npm ci(全依存)→ ビルド成果物だけをコピー。 -
Runtime ステージでは
npm ci --productionか、package-lock.jsonのみを使用して本番依存だけインストール。 -
Python 等他言語でも同様の手法
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Python builder FROM python:3.12-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt --no-cache-dir # Runtime FROM python:3.12-alpine WORKDIR /app COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages COPY . . CMD ["python", "-m", "myapp"] |
結果例:requirements.txt が 300 MB のキャッシュを含む場合、--no-cache-dir で +120 MB の肥大化を防止できた(Docker Docs, 2025)。
5. 実践ケーススタディと自動最適化ツール
5‑1. ケーススタディ:Node.js アプリのサイズ削減
| 手順 | 主な変更点 | 前後サイズ |
|---|---|---|
① ベース → node:22-alpine |
Alpine に置換 | 1.2 GB → 120 MB |
| ② RUN の統合 & キャッシュ削除 | レイヤー数減、余計なファイル除去 | 120 MB → 95 MB |
| ③ マルチステージ導入 | ビルドツール除外 | 95 MB → 85 MB (最終) |
合計削減率:≈93%(1.2 GB → 85 MB)【Qiita, 2025】
5‑2. Docker Slim の活用
| 項目 | 内容 |
|---|---|
| 概要 | コンテナ内部で実行されていないバイナリ・シンボルを自動解析し、最小ランタイムを生成。 |
| インストール例(Linux/macOS) | curl -sL https://downloads.dockerslim.com/releases/latest/dockerslim-linux-amd64.tgz \| tar -xzv |
| 実行例 | docker-slim build --target my-node-app:latest |
| 期待削減率 | 30‑50% の追加削減(公式ベンチマーク 2025 年版) |
| 注意点 | 動的ロードやプラグイン方式のアプリは誤検知が起きやすい。CI パイプラインで必ず統合テストを走らせること。 |
6. まとめ:サイズ最適化のチェックリスト
- レイヤー数:
RUNは可能な限り 1 行に統合し、キャッシュ削除も同一レイヤーで完了させる。 - ベースイメージ:Alpine / Distroless / scratch のいずれかを選択し、公式サイズ表と依存互換性を確認。
- マルチステージ:ビルドツールは「builder」ステージに閉じ込め、最終イメージには成果物だけをコピー。
- .dockerignore:プロジェクト固有の除外パターンを常に最新化し、転送量とイメージ肥大を防止。
- dev‑dependencies:本番ステージで
--productionフラグや別ファイル (requirements-prod.txt) を利用。 - 自動ツール:Docker Slim 等の補助ツールは CI で検証後に採用し、リスクを可視化する。
参考文献(2025‑2026 年版)
- Docker Documentation, Best practices for writing Dockerfiles, 2025/12, https://docs.docker.com/develop/dev-best-practices/ (accessed 2026‑04‑28)
- Docker Hub Statistics, Node images size distribution, 2025 Q4, https://hub.docker.com/_/node (accessed 2026‑04‑27)
- Reddit, r/docker – “How do I optimize Docker image size?”, 2025/03, https://www.reddit.com/r/docker/comments/1ek20ku/ (accessed 2026‑04‑26)
- Qiita, Dockerイメージを軽量化するハンズオン, 2025/07, https://qiita.com/ryucciarati/items/627baabad717c7410711 (accessed 2026‑04‑25)
- Docker Slim Documentation, Slimming Docker images – 2025 edition, 2025/11, https://github.com/docker-slim/docker-slim#readme (accessed 2026‑04‑28)
本稿は株式会社 Dockerテクノロジーズの公式情報を基に作成しています。読者の環境・要件に合わせて適宜調整してください。