Skip to main content

Dockerfile ベストプラクティス 2025: 軽量・安全・高速なイメージ構築

Dockerfile の書き方ひとつで、コンテナイメージのサイズは 10 倍、ビルド時間は 20 倍、脆弱性の数は 5 倍の差がつきます。「動けばいい」から「本番で使える」Dockerfile への進化は、2025 年の DevOps エンジニアにとって必須スキルです。

Kubo では、Kubernetes 上で稼働する多数のコンテナワークロードを管理しており、Dockerfile の品質がクラスタ全体のパフォーマンスとセキュリティに直接影響します。本記事では、2025 年の最新知見に基づいた Dockerfile ベストプラクティスを体系的に解説します。

1. ベースイメージの選択: 軽量化の第一歩

ベースイメージの選択は、最終イメージのサイズとセキュリティに最も大きく影響します。Docker 公式ドキュメントでは、信頼できるソースからのイメージを推奨しています。

ベースイメージ比較

ベースイメージサイズCVE 数(目安)シェル用途
ubuntu:24.04~77MB30-50bash汎用(非推奨)
debian:bookworm-slim~52MB20-40bashDebian 系の軽量版
alpine:3.21~5MB5-10sh (busybox)軽量 + デバッグ可能
distroless/static~2MB0-2なしGo/Rust 静的バイナリ
distroless/base~20MB2-5なしglibc 依存あり
scratch0MB0なし完全カスタム

Google の distroless イメージは、アプリケーションとそのランタイム依存のみを含み、シェルやパッケージマネージャが存在しないため攻撃対象領域を最小化します。

dockerfile
# 推奨: 用途に応じた最小イメージを選択
# Go アプリケーション
FROM gcr.io/distroless/static-debian12

# Node.js アプリケーション
FROM gcr.io/distroless/nodejs20-debian12

# Python アプリケーション
FROM python:3.12-slim

バージョンピニングは再現性のために必須です:

dockerfile
# 悪い例: タグが変わる可能性
FROM node:20

# 良い例: 具体的なバージョン指定
FROM node:20.18-alpine3.21

# 最良: ダイジェストで完全固定
FROM node:20.18-alpine3.21@sha256:abc123...

Captain.AI は、プロジェクトの言語とフレームワークを分析し、最適なベースイメージを自動推薦します。

2. レイヤー構造の最適化

Docker はレイヤーキャッシュを活用してビルドを高速化します。命令の順序を最適化することで、キャッシュヒット率を最大化できます。

命令の順序: 変更頻度の低い順に

dockerfile
# 1. ベースイメージ(ほぼ変更なし)
FROM node:20-alpine AS builder

# 2. システム依存のインストール(まれに変更)
RUN apk add --no-cache python3 make g++

# 3. 依存定義のコピー(パッケージ追加時のみ変更)
WORKDIR /app
COPY package.json package-lock.json ./

# 4. 依存のインストール(パッケージ追加時のみ再実行)
RUN npm ci

# 5. ソースコードのコピー(頻繁に変更)
COPY . .

# 6. ビルド(ソースコード変更のたびに再実行)
RUN npm run build

この順序にすることで、ソースコード変更時の再ビルドはステップ 5-6 のみで完了し、依存のインストール(数分かかる場合がある)がキャッシュされます。ByteScrum のベストプラクティス記事では「間違った順序 = 20 分のリビルド、正しい順序 = 20 秒のリビルド」と表現されています。

RUN 命令の結合

dockerfile
# 悪い例: 3 つのレイヤーが作成され、中間ファイルが残る
RUN apt-get update
RUN apt-get install -y curl wget
RUN rm -rf /var/lib/apt/lists/*

# 良い例: 1 つのレイヤーに統合、キャッシュも削除
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
      curl \
      wget \
    && rm -rf /var/lib/apt/lists/*

3. セキュリティ強化の必須対策

Sysdig の調査によると、本番コンテナの 76% が root で実行されており、これは重大なセキュリティリスクです。

非 root ユーザーで実行

dockerfile
# アプリケーション用ユーザーを作成
RUN addgroup -g 10001 -S appgroup && \
    adduser -u 10001 -S appuser -G appgroup

# 必要なディレクトリの所有権を設定
COPY --chown=appuser:appgroup . /app

# 非 root ユーザーに切り替え
USER appuser

UID 10000 以上を使用することで、ホスト OS のシステムユーザーとの ID 衝突を回避します。

シークレット管理

dockerfile
# 絶対にやってはいけない: イメージレイヤーにシークレットが残る
COPY .env /app/.env
ENV API_KEY=sk-secret-key

# 正しい方法: BuildKit シークレットマウント
RUN --mount=type=secret,id=api_key \
    export API_KEY=$(cat /run/secrets/api_key) && \
    ./setup.sh

BuildKit のシークレットマウントは、シークレットをイメージレイヤーに残さずにビルド時のみ利用可能にします。

.dockerignore の活用

gitignore
# .dockerignore
.git
.gitignore
node_modules
.env
.env.*
*.md
docker-compose*.yml
Dockerfile*
.DS_Store
__pycache__
*.pyc
coverage/
.pytest_cache/

.dockerignore はビルドコンテキストのサイズを削減し、意図しないファイル(特にシークレット)のイメージへの混入を防ぎます。GeeksforGeeks の Dockerfile ガイドでも必須対策として紹介されています。

Kubo のセキュリティポリシーでは、非 root 実行と .dockerignore の使用を標準として推奨しています。

4. BuildKit の活用

BuildKit は Docker の次世代ビルドエンジンで、並列ビルド、改善されたキャッシュ、セキュリティ機能を提供します。

BuildKit の有効化

bash
# 環境変数で有効化
export DOCKER_BUILDKIT=1

# docker buildx を使用(推奨)
docker buildx build -t myapp:latest .

キャッシュマウント

依存パッケージのキャッシュをビルド間で共有し、再インストールを回避します:

dockerfile
# pip のキャッシュを保持
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

# npm のキャッシュを保持
RUN --mount=type=cache,target=/root/.npm \
    npm ci

# Go モジュールのキャッシュを保持
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    go build -o /app/server .

# apt のキャッシュを保持
RUN --mount=type=cache,target=/var/cache/apt \
    --mount=type=cache,target=/var/lib/apt \
    apt-get update && apt-get install -y curl

ヒアドキュメント構文

dockerfile
# 従来の方法(エスケープが煩雑)
RUN echo "server {" > /etc/nginx/conf.d/default.conf && \
    echo "  listen 80;" >> /etc/nginx/conf.d/default.conf && \
    echo "  location / { proxy_pass http://app:8080; }" >> /etc/nginx/conf.d/default.conf && \
    echo "}" >> /etc/nginx/conf.d/default.conf

# BuildKit のヒアドキュメント(読みやすい)
COPY <<EOF /etc/nginx/conf.d/default.conf
server {
    listen 80;
    location / {
        proxy_pass http://app:8080;
    }
}
EOF

5. イメージサイズ削減のテクニック集

COPY を ADD より優先

dockerfile
# 避ける: ADD はリモート URL ダウンロードと tar 自動展開を行う
ADD https://example.com/app.tar.gz /app/

# 推奨: COPY は明示的なローカルファイルコピーのみ
COPY app/ /app/

ADD は予期しない動作を引き起こす可能性があるため、ローカルファイルのコピーには常に COPY を使用します。

不要パッケージの排除

dockerfile
# --no-install-recommends で推奨パッケージを除外
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
      ca-certificates \
      curl \
    && rm -rf /var/lib/apt/lists/*

# Alpine では --no-cache で apk キャッシュを無効化
RUN apk add --no-cache curl

マルチステージビルドの活用

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --production

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER node
CMD ["node", "dist/index.js"]

DevOps Training Institute の最適化ガイドでは、これらのテクニックを組み合わせることで 80% 以上のサイズ削減が達成可能と報告されています。

定期的なイメージ再ビルド

本番イメージは少なくとも月次で再ビルドし、ベースイメージの最新セキュリティパッチを適用します。DependabotRenovate で自動化するのが Docker 公式の推奨です。

6. ヘルスチェックの定義

dockerfile
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:8080/healthz || exit 1

HEALTHCHECK 命令は Docker がコンテナの健全性を判断するために使用します。Kubernetes では liveness/readiness Probe に置き換えられますが、Docker Compose 環境では依然として有効です。

まとめ: Dockerfile チェックリスト 2025

本番品質の Dockerfile を書くための最終チェックリスト:

  • 最小限のベースイメージを選択(alpine - distroless - scratch)
  • バージョンピニングで再現性を確保
  • 変更頻度の低い命令を先に配置(キャッシュ最適化)
  • RUN 命令を結合し、キャッシュを削除
  • 非 root ユーザーで実行(UID 10000+)
  • .dockerignore でビルドコンテキストを最小化
  • シークレットを BuildKit マウントで管理
  • マルチステージビルドで本番と開発を分離
  • COPY を ADD より優先
  • HEALTHCHECK を定義
  • 定期的な再ビルドスケジュールを設定

Kubo では、これらのベストプラクティスに準拠したコンテナイメージを Kubernetes クラスタ上で効率的に運用しています。Captain.AI を活用すれば、Dockerfile の自動レビューと最適化提案により、チーム全体の Dockerfile 品質を底上げできます。

Dockerfile の最適化やコンテナ運用のご相談は、お問い合わせよりお気軽にどうぞ。

← Back to all posts