writing-dockerfiles について
アプリケーション開発者向けに、本番用 Dockerfile の作成と改善を支援するスキルです。マルチステージビルド、セキュリティ強化、キャッシュ、言語別のパターンを扱います。
主な機能
- 01マルチステージビルドの指針
- 02言語別のベースイメージ選択
- 03BuildKit のキャッシュとシークレットマウント
- 04セキュリティ強化と非 root ユーザー
- 05Dockerfile の検証とイメージ分析
活用シーン
- 01アプリケーションの本番用 Dockerfile 作成
- 02マルチステージビルドによるイメージ縮小
- 03イメージレイヤーへの認証情報混入防止
- 04言語別のコンテナパターン適用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ancoleman/ ai-design-components --skill writing-dockerfilesインストール後、Claude Code で/writing-dockerfilesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
outputs.yamlexamples/go-microservice.Dockerfilenodejs-express.Dockerfilepython-fastapi.Dockerfilerust-actix.Dockerfilereferences/base-image-selection.mdbuildkit-features.mdgo-dockerfiles.mdjava-dockerfiles.mdnodejs-dockerfiles.mdpython-dockerfiles.mdrust-dockerfiles.mdsecurity-hardening.mdscripts/analyze_image_size.shvalidate_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-alpine | gcr.io/distroless/static-debian12 | 10-30MB |
| Rust(静的) | rust:1.75-alpine | scratch | 5-15MB |
| Python | python:3.12-slim | python:3.12-slim | 200-400MB |
| Node.js | node:20-alpine | node:20-alpine | 150-300MB |
| Java | maven:3.9-eclipse-temurin-21 | eclipse-temurin:21-jre-alpine | 200-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 つのアプローチ:
- pip(シンプル) → 単一ステージ、requirements.txt
- poetry(本番向け) → マルチステージ、仮想環境
- 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 のキャッシュマウント先:
| 言語 | パッケージマネージャー | キャッシュマウント先 |
|---|---|---|
| Python | pip | --mount=type=cache,target=/root/.cache/pip |
| Python | poetry | --mount=type=cache,target=/root/.cache/pypoetry |
| Python | uv | --mount=type=cache,target=/root/.cache/uv |
| Node.js | npm | --mount=type=cache,target=/root/.npm |
| Node.js | pnpm | --mount=type=cache,target=/root/.local/share/pnpm/store |
| Go | go mod | --mount=type=cache,target=/go/pkg/mod |
| Rust | cargo | --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/ディレクトリにある動作するサンプル