mcpField
W
writing-dockerfiles

writing-dockerfiles

github.com/ancolemanクラウド・DevOps52581 回インストール46 週間前に更新
リポジトリ

writing-dockerfiles について

アプリケーション開発者向けに、本番用 Dockerfile の作成と改善を支援するスキルです。マルチステージビルド、セキュリティ強化、キャッシュ、言語別のパターンを扱います。

主な機能

  1. 01マルチステージビルドの指針
  2. 02言語別のベースイメージ選択
  3. 03BuildKit のキャッシュとシークレットマウント
  4. 04セキュリティ強化と非 root ユーザー
  5. 05Dockerfile の検証とイメージ分析

活用シーン

  1. 01アプリケーションの本番用 Dockerfile 作成
  2. 02マルチステージビルドによるイメージ縮小
  3. 03イメージレイヤーへの認証情報混入防止
  4. 04言語別のコンテナパターン適用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ancoleman/ai-design-components --skill writing-dockerfiles

インストール後、Claude Code で/writing-dockerfilesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

outputs.yaml
examples/
go-microservice.Dockerfile
nodejs-express.Dockerfile
python-fastapi.Dockerfile
rust-actix.Dockerfile
references/
base-image-selection.md
buildkit-features.md
go-dockerfiles.md
java-dockerfiles.md
nodejs-dockerfiles.md
python-dockerfiles.md
rust-dockerfiles.md
security-hardening.md
scripts/
analyze_image_size.sh
validate_dockerfile.py

詳細

Dockerfile の作成

マルチステージビルド、セキュリティ強化、言語固有の最適化を取り入れた、本番環境向けの Dockerfile を作成します。

このスキルを使う場面

次の場合に呼び出します。

  • 「[Python/Node.js/Go/Rust] アプリケーション用の Dockerfile を書く」
  • 「この Dockerfile を最適化してイメージサイズを小さくする」
  • 「…にマルチステージビルドを使う」
  • 「非 root ユーザーを使って Dockerfile のセキュリティを強化する」
  • 「distroless ベースイメージを使う」
  • 「BuildKit のキャッシュマウントを追加する」
  • 「Docker レイヤーからシークレットが漏えいしないようにする」

すばやく判断するためのフレームワーク

3 つの質問でアプローチを決めます。

1. 使用する言語は何ですか?

  • Python → references/python-dockerfiles.md を参照
  • Node.js → references/nodejs-dockerfiles.md を参照
  • Go → references/go-dockerfiles.md を参照
  • Rust → references/rust-dockerfiles.md を参照
  • Java → references/java-dockerfiles.md を参照

2. セキュリティは重要ですか?

  • はい → distroless ランタイムイメージを使用します(references/security-hardening.md を参照)
  • いいえ → slim/alpine ベースイメージを使用します

3. イメージサイズは重要ですか?

  • はい(<50MB)→ マルチステージ + distroless + 静的リンク
  • いいえ(<500MB)→ マルチステージ + slim ベースイメージ

基本概念

マルチステージビルド

ビルド環境とランタイム環境を分離し、最終的なイメージサイズを最小限に抑えます。

パターン:

# Stage 1: Build
FROM build-image AS builder
RUN compile application

# Stage 2: Runtime
FROM minimal-runtime-image
COPY --from=builder /app/binary /app/
CMD ["/app/binary"]

メリット:

  • イメージサイズを 80~95% 削減します(ビルドツールを除く)
  • セキュリティを向上させます(本番環境にコンパイラーを含めません)
  • デプロイを高速化します
  • レイヤーキャッシュを改善します
ベースイメージの選択

判断基準:

言語ビルドステージランタイムステージ最終サイズ
Go(静的)golang:1.22-alpinegcr.io/distroless/static-debian1210-30MB
Rust(静的)rust:1.75-alpinescratch5-15MB
Pythonpython:3.12-slimpython:3.12-slim200-400MB
Node.jsnode:20-alpinenode:20-alpine150-300MB
Javamaven:3.9-eclipse-temurin-21eclipse-temurin:21-jre-alpine200-350MB

distroless イメージ(Google がメンテナンス):

  • gcr.io/distroless/static-debian12 → 静的バイナリ(2MB)
  • gcr.io/distroless/base-debian12 → libc を使用する動的バイナリ(20MB)
  • gcr.io/distroless/python3-debian12 → Python ランタイム(60MB)
  • gcr.io/distroless/nodejs20-debian12 → Node.js ランタイム(150MB)

詳しい比較については、references/base-image-selection.md を参照してください。

BuildKit の機能

高度なキャッシュ機能とセキュリティ機能を利用するには、BuildKit を有効にします。

export DOCKER_BUILDKIT=1
docker build .
# OR
docker buildx build .

主な機能:

  • --mount=type=cache → パッケージマネージャーのキャッシュを永続化します
  • --mount=type=secret → シークレットをレイヤーに保存せずに注入します
  • --mount=type=ssh → プライベートリポジトリ向けに SSH エージェントを転送します
  • ステージを並列実行します
  • レイヤーキャッシュを改善します

詳しいパターンについては、references/buildkit-features.md を参照してください。

レイヤーの最適化

変更頻度が低いものから高いものへ、Dockerfile の命令を並べます。

# 1. Base image (rarely changes)
FROM python:3.12-slim

# 2. System packages (rarely changes)
RUN apt-get update && apt-get install -y build-essential

# 3. Dependencies manifest (changes occasionally)
COPY requirements.txt .
RUN pip install -r requirements.txt

# 4. Application code (changes frequently)
COPY . .

# 5. Runtime configuration (rarely changes)
CMD ["python", "app.py"]

BuildKit のキャッシュマウント:

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

キャッシュはビルド間で保持され、重複したダウンロードをなくします。

セキュリティの強化

基本的なセキュリティ対策:

1. 非 root ユーザー

# Debian/Ubuntu
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Alpine
RUN adduser -D -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

# Distroless (built-in)
USER nonroot:nonroot

2. シークレット管理

# ❌ NEVER: Secret in layer history
RUN git clone https://${GITHUB_TOKEN}@github.com/private/repo.git

# ✅ ALWAYS: BuildKit secret mount
RUN --mount=type=secret,id=github_token \
    TOKEN=$(cat /run/secrets/github_token) && \
    git clone https://${TOKEN}@github.com/private/repo.git

次のコマンドでビルドします。

docker buildx build --secret id=github_token,src=./token.txt .

3. 脆弱性スキャン

# Trivy (recommended)
trivy image myimage:latest

# Docker Scout
docker scout cves myimage:latest

4. ヘルスチェック

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

包括的なセキュリティ強化パターンについては、references/security-hardening.md を参照してください。

.dockerignore の設定

不要なファイルを除外するために .dockerignore を作成します。

# Version control
.git
.gitignore

# CI/CD
.github
.gitlab-ci.yml

# IDE
.vscode
.idea

# Testing
tests/
coverage/
**/*_test.go
**/*.test.js

# Build artifacts
node_modules/
dist/
build/
target/
__pycache__/

# Environment
.env
.env.local
*.log

ビルドコンテキストのサイズを削減し、シークレットの漏えいを防ぎます。

言語固有のパターン

Python クイックリファレンス

3 つのアプローチ:

  1. pip(シンプル) → 単一ステージ、requirements.txt
  2. poetry(本番向け) → マルチステージ、仮想環境
  3. uv(最速) → pip より 10~100 倍高速

例:Poetry のマルチステージ

FROM python:3.12-slim AS builder
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install poetry==1.7.1

COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt

RUN --mount=type=cache,target=/root/.cache/pip \
    python -m venv /opt/venv && \
    /opt/venv/bin/pip install -r requirements.txt

FROM python:3.12-slim
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
USER 1000:1000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]

すべてのパターンについては references/python-dockerfiles.md を、examples/python-fastapi.Dockerfile についてはそちらを参照してください。

Node.js クイックリファレンス

主なパターン:

  • 再現可能なビルドには npm install ではなく npm ci を使用します
  • マルチステージ:ビルドステージ → 本番用依存関係のみ
  • 組み込みの node ユーザー(UID 1000)
  • Alpine バリアントが最小サイズです(約 180MB、1GB に対して)

例:Express のマルチステージ

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
RUN npm run build
RUN npm prune --omit=dev

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

npm/pnpm/yarn のパターンについては references/nodejs-dockerfiles.md と examples/nodejs-express.Dockerfile を参照してください。

Go クイックリファレンス

可能な限り小さいイメージ:

  • 静的バイナリ(CGO_ENABLED=0)+ distroless = 10~30MB
  • -ldflags="-s -w" でシンボルを削除します
  • /go/pkg/mod とビルドキャッシュの両方をキャッシュします

例:Distroless の静的イメージ

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main .

FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/main /app/main
USER nonroot:nonroot
ENTRYPOINT ["/app/main"]

references/go-dockerfiles.md と examples/go-microservice.Dockerfile を参照してください。

Rust クイックリファレンス

超小型の静的バイナリ:

  • musl 静的リンク → libc 依存関係なし
  • scratch ベースイメージ(オーバーヘッド 0 バイト)
  • 最終イメージ:5~15MB

例:Scratch ベース

FROM rust:1.75-alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /app

# Cache dependencies
COPY Cargo.toml Cargo.lock ./
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    mkdir src && echo "fn main() {}" > src/main.rs && \
    cargo build --release --target x86_64-unknown-linux-musl && \
    rm -rf src

# Build application
COPY src ./src
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    cargo build --release --target x86_64-unknown-linux-musl

FROM scratch
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/app /app
USER 1000:1000
ENTRYPOINT ["/app"]

references/rust-dockerfiles.md と examples/rust-actix.Dockerfile を参照してください。

パッケージマネージャーのキャッシュマウント

BuildKit のキャッシュマウント先:

言語パッケージマネージャーキャッシュマウント先
Pythonpip--mount=type=cache,target=/root/.cache/pip
Pythonpoetry--mount=type=cache,target=/root/.cache/pypoetry
Pythonuv--mount=type=cache,target=/root/.cache/uv
Node.jsnpm--mount=type=cache,target=/root/.npm
Node.jspnpm--mount=type=cache,target=/root/.local/share/pnpm/store
Gogo mod--mount=type=cache,target=/go/pkg/mod
Rustcargo--mount=type=cache,target=/usr/local/cargo/registry

永続キャッシュにより、ビルド間で重複するパッケージのダウンロードをなくせます。

検証とテスト

Dockerfile の品質を検証する:

# Lint Dockerfile
python scripts/validate_dockerfile.py Dockerfile

# Scan for vulnerabilities
trivy image myimage:latest

# Analyze image size
docker images myimage:latest
docker history myimage:latest

最適化の結果を比較する:

# Before optimization
docker build -t myapp:before .

# After optimization
docker build -t myapp:after .

# Compare
bash scripts/analyze_image_size.sh myapp:before myapp:after

Dockerfile の自動リントについては scripts/validate_dockerfile.py を参照してください。

関連スキルとの連携

上流(入力を提供):

  • testing-strategies → コンテナ化の前にアプリケーションをテストします
  • security-hardening → Docker レイヤーの前にアプリケーションレベルのセキュリティ対策を行います

下流(Dockerfile を利用):

  • building-ci-pipelines → CI で Docker イメージをビルドしてプッシュします
  • kubernetes-operations → コンテナを K8s クラスターにデプロイします
  • infrastructure-as-code → Terraform/Pulumi でコンテナをデプロイします

並行(関連するコンテキスト):

  • secret-management → 実行時のシークレットを注入します(K8s シークレット、Vault)
  • observability → コンテナのログ記録とメトリクス収集

よく使われるパターンのクイックリファレンス

1. 静的バイナリ(Go/Rust)→ 最小のイメージ

  • ビルド:言語固有のビルダーイメージ
  • ランタイム:gcr.io/distroless/static-debian12 または scratch
  • サイズ:5~30MB

2. インタープリター型言語(Python/Node.js)→ 本番環境向けに最適化

  • ビルド:依存関係をインストールし、成果物をビルドします
  • ランタイム:同じベース、本番用依存関係のみ
  • サイズ:150~400MB

3. JVM(Java)→ 最適化されたランタイム

  • ビルド:フル JDK を使用した Maven/Gradle
  • ランタイム:JRE のみのイメージ(Alpine バリアント)
  • サイズ:200~350MB

4. セキュリティが重要な場合 → 最大限の強化

  • ベース:Distroless イメージ
  • ユーザー:root 以外(nonroot:nonroot)
  • シークレット:BuildKit のシークレットマウント
  • スキャン:CI で Trivy/Docker Scout を使用

5. 開発 → すばやい反復

  • ベース:言語のフルイメージ(slim ではないもの)
  • ボリューム:ソースコードをマウントします
  • ホットリロード:言語固有のツール
  • このスキルでは対象外です(Docker Compose のドキュメントを参照)

避けるべきアンチパターン

❌ 絶対に避けること:

  • latest タグを使用する(ビルドが予測不能になります)
  • 本番環境で root として実行する
  • ENV 変数やレイヤーにシークレットを保存する
  • 不要なパッケージをインストールする
  • 無関係な RUN コマンドをまとめる(キャッシュが機能しなくなります)
  • .dockerignore を省略する(ビルドコンテキストが肥大化します)

✅ 常に行うこと:

  • イメージのバージョンを正確に指定する(python:3.12.1-slim。python:3 ではなく)
  • root 以外のユーザーを作成して使用する
  • 認証情報には BuildKit のシークレットマウントを使用する
  • レイヤー数とイメージサイズを最小限に抑える
  • 変更頻度の低いコマンドから高いコマンドの順に並べる
  • .dockerignore ファイルを作成する

追加リソース

ベースイメージのレジストリ:

  • Google Distroless:gcr.io/distroless/*
  • Docker Hub 公式:python:*、node:*、golang:*
  • Red Hat UBI:registry.access.redhat.com/ubi9/*

脆弱性スキャナー:

  • Trivy(推奨):trivy image myimage:latest
  • Docker Scout:docker scout cves myimage:latest
  • Grype:grype myimage:latest

リファレンスドキュメント:

  • references/base-image-selection.md → ベースイメージの完全な比較
  • references/buildkit-features.md → 高度な BuildKit パターン
  • references/security-hardening.md → 包括的なセキュリティガイド
  • references/ ディレクトリにある言語固有のリファレンス
  • examples/ ディレクトリにある動作するサンプル

コメント