docker-dockerfile について
アプリケーションのコンテナイメージを作成する開発者向けに、Dockerfile の作成と最適化を案内するリファレンススキルです。命令の使い方、言語別のマルチステージ構成、レイヤーキャッシュ、本番向けの強化を扱い、イメージのビルド実行やオーケストレーションは対象外です。
主な機能
- 01一般的な Dockerfile 命令と使い方のリファレンス
- 02Go、Java、Node.js、Python 向けのマルチステージ構成
- 03レイヤーキャッシュと依存ファイルを先にコピーする指針
- 04イメージの縮小、セキュリティ、本番向けの強化
- 05よくある Dockerfile の問題への対処
活用シーン
- 01アプリケーションの実行環境向け Dockerfile の作成
- 02依存レイヤーとビルドキャッシュの最適化
- 03Dockerfile のセキュリティと本番利用への適合確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ full-stack-skills/ docker-skills --skill docker-dockerfileインストール後、Claude Code で/docker-dockerfileを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evaluation-report.htmlagents/openai.yamlexamples/01-multi-stage-go.md02-multi-stage-java.md03-spring-boot-layers.md04-multi-stage-node.md05-multi-stage-python.mdreferences/01-dockerfile-instructions.md02-layer-caching.md03-dockerignore.md04-image-size-optimization.md05-multi-stage-patterns.md詳細
Dockerfile — 完全ガイド
本番環境向けの Dockerfile を作成するためのエキスパート向けリファレンスです。すべての命令、パターン、最適化を網羅します。
使用する場面
ユーザーが次の内容に言及した場合は、必ずこのスキルを使用してください。
- 「Dockerfile」、「Dockerfile の書き方」、「Dockerfile の命令」
- 「マルチステージビルド」、「multi-stage build」
- 「Dockerfile のレイヤー最適化」、「layer caching」
- 「Dockerfile テンプレート」、言語固有のもの:「Go Dockerfile」、「Java Dockerfile」、「Python Dockerfile」
- Dockerfile の作成または最適化が必要な場合
- 「Dockerfile のベストプラクティス」
命令リファレンス
FROM — ベースイメージ
FROM <image>[:<tag>] [AS <stage-name>]
FROM alpine:3.20 # Tag
FROM alpine:3.20@sha256:abc123...def456 # Digest (production!)
FROM golang:1.22-alpine AS builder # Named stage
FROM scratch # Empty image (for static binaries)
| ベストプラクティス | 理由 |
|---|---|
| 本番環境ではダイジェストを固定する | タグは変更可能ですが、ダイジェストは不変です |
| Alpine/slim バリアントを使用する | 攻撃対象領域とイメージサイズを小さくできます |
Go/Rust では FROM scratch を使用する | 静的バイナリにはほかに何も必要ありません |
RUN — コマンドを実行する
# ✅ Chain commands, clean in same layer
RUN apk add --no-cache curl && \
curl -fsSL https://example.com/script.sh -o /usr/local/bin/script && \
chmod +x /usr/local/bin/script
# ❌ Each RUN = new layer (bloat)
RUN apk add curl
RUN curl ... -o /usr/local/bin/script
RUN chmod +x /usr/local/bin/script
# Multi-line readability
RUN set -eux; \
apk add --no-cache \
curl \
ca-certificates \
tzdata; \
curl -fsSL ... | tar xz -C /usr/local
COPY — ファイルをコピーする
COPY [--chown=<user>:<group>] <src>... <dest>
COPY . /app
COPY --chown=app:app ./binary /usr/local/bin/
COPY --from=builder /app/build /app # From another stage (multi-stage)
# ✅ Layer-friendly: copy deps first, then source
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# ❌ Source change invalidates dependency cache
COPY . .
RUN go mod download
ADD — コピーと自動展開
# ADD auto-extracts tar archives
ADD archive.tar.gz /app/
# Prefer COPY unless you need tar extraction
COPY archive.tar.gz /app/
RUN tar xzf /app/archive.tar.gz -C /app
WORKDIR — 作業ディレクトリを設定する
WORKDIR /app
# All subsequent RUN/COPY/CMD use /app as base
# Prefer over:
RUN cd /app && npm install # ❌ cd doesn't persist
ENV と ARG
# ARG: build-time only (not in final image)
ARG VERSION=1.0.0
FROM myapp:${VERSION}
# ENV: runtime (persists in image)
ENV NODE_ENV=production \
PORT=8080
# Combine: pass ARG to ENV
ARG APP_VERSION
ENV APP_VERSION=${APP_VERSION}
EXPOSE — ポートを記述する
EXPOSE 8080
EXPOSE 8080/tcp # Protocol-specific
EXPOSE 8080/udp
# Note: EXPOSE does NOT publish ports. Use -p at runtime:
# docker run -p 8080:8080 myapp
CMD と ENTRYPOINT
# CMD: default command (overridable)
CMD ["nginx", "-g", "daemon off;"]
# docker run myimage echo hello → overrides CMD
# ENTRYPOINT: fixed entry (not overridable)
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
# docker run myimage → runs: docker-entrypoint.sh nginx -g 'daemon off;'
# docker run myimage echo hello → runs: docker-entrypoint.sh echo hello
# Common pattern: script + default args
ENTRYPOINT ["/entrypoint.sh"]
CMD ["start"]
USER — root 以外のユーザーに切り替える
# Create user and group
RUN addgroup --system app && adduser --system --ingroup app app
USER app
HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/health || exit 1
# Dockerfile without shell (scratch):
HEALTHCHECK --interval=30s CMD /app/healthcheck || exit 1
SHELL — デフォルトのシェルを変更する
SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]
RUN echo "Now using bash with strict mode"
マルチステージビルドのパターン
パターン 1:バイナリをビルドして scratch を使用(Go/Rust)
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o server .
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/server /server
USER 1000:1000
CMD ["/server"]
パターン 2:ビルドして最小限のランタイムを使用(Java)
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
FROM eclipse-temurin:21-jre-alpine
RUN addgroup --system app && adduser -S -G app app
COPY --from=builder /app/target/*.jar /app.jar
USER app
CMD ["java", "-jar", "/app.jar"]
パターン 3:レイヤーを最適化(Spring Boot)
FROM eclipse-temurin:21-jre-alpine AS builder
WORKDIR /app
COPY build/libs/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
FROM eclipse-temurin:21-jre-alpine
RUN addgroup --system app && adduser -S -G app app
# Layers in dependency order (max cache)
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
USER app
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
パターン 4:ビルドして Alpine を使用(Node.js)
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine
RUN addgroup --system app && adduser -S -G app app
COPY --from=builder /app/dist /app
COPY --from=builder /app/node_modules /app/node_modules
USER app
CMD ["node", "/app/index.js"]
パターン 5:Python の依存関係と slim ランタイム
FROM python:3.12 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.12-slim
RUN groupadd --system app && useradd --system -g app app
COPY --from=builder /root/.local /home/app/.local
COPY . /app
ENV PATH=/home/app/.local/bin:$PATH
USER app
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]
レイヤーキャッシュ戦略
Docker builds layers from top to bottom.
A changed layer invalidates ALL layers below it.
✅ CORRECT order:
FROM base ← rarely changes
RUN install-system-deps ← changes with system updates
COPY go.mod go.sum ./ ← changes with dependency changes
RUN go mod download ← changes with dependency changes
COPY . . ← changes every commit ← MUST BE LAST
❌ WRONG order (slow builds):
COPY . . ← changes every commit
RUN go mod download ← reruns every time!
.dockerignore
# .dockerignore
.git
.gitignore
*.md
.env
.env.*
Dockerfile
docker-compose*.yml
node_modules
__pycache__
*.pyc
.git
.idea
.vscode
*.log
tmp/
ワークフロー — 推奨される作成手順
Step 1:言語とランタイムを決める:Go/Java/Node.js/Python → ベースイメージを選択
Step 2:ビルド方式を選ぶ:単一ステージ/マルチステージ/Spring Boot のレイヤー化 → templates からテンプレートを選択
Step 3:Dockerfile を作成する:まず依存関係を COPY → RUN install → ソースコードを COPY → CMD
Step 4:検証する:docker build -t app . + docker run + dive でイメージサイズを分析
Step 5:本番向けに強化する:root 以外の USER、HEALTHCHECK、ダイジェストの固定、セキュリティチェック
注意点 — よくある落とし穴
RUN installより前にCOPY . .を実行する:コードを変更するたびに依存関係のレイヤーが無効になり、最初から再ビルドされます。→ 対処方法:依存関係を先にコピーします:COPY package.json . → RUN install → COPY src/ .。- デフォルトで root ユーザーを使用する:Dockerfile の最後には必ず
USER <non-root>を指定してください。root としてコンテナから脱出されると、ホストでも root 権限を得られます。→ 対処方法:RUN addgroup -S app && adduser -S app -G appとUSER appを追加し、docker exec myapp whoamiで確認します。 - Dockerfile に
ENV SECRET=valueを記述する:値はイメージのレイヤーに永久に含まれます。→ 対処方法:BuildKit の--mount=type=secretまたは実行時の環境変数注入docker run -e SECRET=$VALを使用します。 .dockerignoreがない:プロジェクト全体がビルドコンテキストに送られ、処理が遅くなり、機密ファイルが漏えいするおそれがあります。→ 対処方法:最低限.git node_modules .envを含む.dockerignoreを作成し、docker build --no-cache . 2>&1 | head -1で確認します。- クリーンアップせずに
RUN apt update && apt installを実行する:パッケージリストがレイヤーに残ります。→ 対処方法:&& rm -rf /var/lib/apt/lists/*を連結します。apk の場合は--no-cacheフラグを使用します。 - サイズの大きいベースイメージを使う:
ubuntu:22.04(77 MB)に対し、alpine:3.20は 7 MB です。→ 対処方法:Alpine を優先します。glibc が必要な場合はdebian:bookworm-slimを使用し、docker imagesでサイズを確認します。
対応範囲 — 対応可能なこと/できないこと
| 分類 | 場面 | 説明 |
|---|---|---|
| ✅ 対応可能 | 本番環境向け Dockerfile の作成 | 14 個の命令を網羅したリファレンスとベストプラクティス |
| ✅ 対応可能 | マルチステージビルド(Go/Java/Node/Python) | 言語ごとのテンプレートを 5 種類用意 |
| ✅ 対応可能 | レイヤーキャッシュの最適化 | 依存関係を先に COPY → RUN をまとめる → BuildKit の cache mount |
| ✅ 対応可能 | イメージのスリム化 | 5 ステップの手順:マルチステージ→Alpine→distroless→クリーンアップ→dive |
| ⚠️ 条件付き | プライベート依存関係のインストール | BuildKit の --secret または SSH forwarding が必要 |
| ⚠️ 条件付き | CMD と ENTRYPOINT の選択 | 命令リファレンスの判断ツリーを参照してください(ツールには ENTRYPOINT、サービスには CMD) |
| ❌ 対象外 | docker build コマンドの実行 | docker-build を使用 |
| ❌ 対象外 | マルチプラットフォームビルド(arm64/amd64) | docker-buildx を使用 |
| ❌ 対象外 | コンテナオーケストレーション(複数コンテナ) | docker-compose を使用 |
このスキルを使用しない場合
| ❌ 使用しない | ✅ 代わりに使用 |
|---|---|
イメージのビルド(docker build ...) | docker-build |
| マルチプラットフォームビルド | docker-buildx |
| Compose ファイルの作成 | docker-compose |
| Docker の基礎 | docker-basics |
| コンテナの実行 | docker-run |
セキュリティと安定性
- Dockerfile のテンプレートはすべて学習用です。本番環境で使用する前に確認し、セキュリティを強化してください。
- Dockerfile にシークレットを埋め込まないでください。BuildKit の
--mount=type=secretまたは実行時の注入を使用してください。 - 本番環境では必ず
USER <non-root>を使用してください。そのユーザー用のファイルをコピーするときは、COPY --chownを使用してください。 - 本番環境で再現性を確保するため、ベースイメージのダイジェストを固定してください。
📚 公式ドキュメントの参考情報
| ドキュメント | URL |
|---|---|
| Dockerfile リファレンス | https://docs.docker.com/reference/dockerfile/ |
| Docker Build の概要 | https://docs.docker.com/build/ |
| ビルドのベストプラクティス | https://docs.docker.com/build/building/best-practices/ |
| マルチステージビルド | https://docs.docker.com/build/building/multi-stage/ |
| .dockerignore | https://docs.docker.com/build/building/context/#dockerignore-files |
| イメージレイヤーとキャッシュ | https://docs.docker.com/build/cache/ |
🧭 Docker スキルの進め方
📍 現在の位置:
docker-dockerfile— Dockerfile の作成
basics → dockerfile → build → buildx → run → compose → ...
→ 次へ:docker-build — docker build でイメージをビルド