第3章 Dockerfileによるイメージ構築|これだけはおさえる基本知識
Docker を使えるエンジニアと、Docker を使いこなせるエンジニアを分けるのは、まさに第3章の内容です。Dockerfile は「書ければ終わり」ではなく、キャッシュ戦略・マルチステージ・セキュリティ・軽量化のすべてを押さえて初めて本番で通用します。
この章では、Dockerfileの基本構文から始まり、ビルド時間を1/10にする最適化、本番イメージを1/10に削る軽量化、root実行を避けるセキュリティ強化までを一気通貫で解説しました。読了目安:約15分。この1ページで章全体の要点が把握できます。各セクションの詳細は下部のリンクから深掘りできます。
目次
- 3-1. Dockerfileの基本構文
- 3-2. レイヤーキャッシュとビルド最適化
- 3-3. .dockerignore の活用
- 3-4. docker build の実践
- 3-5. マルチステージビルド
- 3-6. イメージの軽量化戦略
- 第3章のまとめ
1. Dockerfileの基本構文|FROM・RUN・COPY・CMD・ENTRYPOINT
Dockerfile は コンテナイメージの設計図です。1行1命令で上から順に実行され、それぞれがレイヤーを作ります。まずは最低限覚えるべき命令セットを押さえましょう。
| 命令 | 役割 | 使用頻度 |
|---|---|---|
FROM |
ベースイメージの指定 | ★★★ |
RUN |
ビルド時にコマンド実行(apt install等) | ★★★ |
COPY |
ホストからイメージへファイルコピー | ★★★ |
WORKDIR |
作業ディレクトリ指定 | ★★★ |
CMD |
コンテナ起動時の既定コマンド | ★★★ |
ENTRYPOINT |
コンテナを「実行可能ファイル」として起動 | ★★ |
EXPOSE |
Listenポートの明示(ドキュメント目的) | ★★ |
ENV / ARG |
環境変数/ビルド時引数 | ★★ |
# 最小のDockerfile例(Python Flask)
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]
CMD は「デフォルトコマンド(上書き可)」、ENTRYPOINT は「コンテナの主役コマンド(引数だけ変えたい場合に使う)」。通常は CMD で十分。CLI ツールをコンテナ化する時だけ ENTRYPOINT を検討しましょう。
📖 詳細はこちら:3.1 Dockerfile完全入門|FROM・RUN・COPY・CMD・ENTRYPOINT など全命令を実例で解説
2. レイヤーキャッシュとビルド最適化|5分→30秒の世界
Dockerfile の書き順を少し変えるだけで、ビルド時間が 5分→30秒になります。カギは「レイヤーキャッシュ」を味方にする書き方です。
鉄則:変更頻度順にレイヤーを並べる
# ❌ 悪い例:ソース1行変更で npm install が毎回走る
COPY . .
RUN npm install
# ✅ 良い例:依存定義を先にコピー → install後にソースコピー
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
この書き順の違いは、再ビルド時のキャッシュ利用率に直結します。キャッシュは上から順に評価され、1つでも壊れるとその下すべてが再ビルドされるためです。
別レイヤーにすると古いパッケージインデックスがキャッシュされ、セキュリティパッチが当たらない落とし穴にハマります。
apt-get update && apt-get install -y ... && rm -rf /var/lib/apt/lists/* のセットで覚えましょう。
📖 詳細はこちら:3.2 Dockerレイヤーキャッシュの仕組みとビルド最適化|ビルド時間を10倍速くする実践テクニック
3. .dockerignore の活用|ビルド高速化&情報漏洩防止
docker build . の最後の . で指定されたディレクトリは、まるごとDockerデーモンに送信されます(ビルドコンテキスト)。ここが大きいとビルドが遅く、さらに .env や .git が本番イメージに混入するリスクもあります。
# .dockerignore の最低限テンプレ
.git/
.env
.env.*
*.pem
*.key
node_modules/
__pycache__/
*.pyc
dist/
build/
tests/
.vscode/
.idea/
README.md
Dockerfile
.dockerignore
.env と .git/ の除外過去には
COPY . . で .git/ をイメージに含め、削除済みの APIキー が過去のコミット履歴経由で漏洩する事故が繰り返し起きています。.dockerignore はセキュリティ対策の一環です。
📖 詳細はこちら:3.4 .dockerignore完全ガイド|書き方・推奨テンプレ・ビルド高速化と情報漏洩の防止
4. docker build の実践|Webアプリを本番品質へ育てる
実プロジェクトのDockerfile は「一気に完璧を目指す」のではなく、4段階で段階的に育てるのが現実的です。Flask アプリを例に進化の過程を示します。
| 段階 | 適用する技術 | サイズ | 差分ビルド | 本番可否 |
|---|---|---|---|---|
| v1 最小 | 基本構文のみ | 約 1GB | 40秒 | ❌ |
| v2 キャッシュ最適化 | + COPY分割、.dockerignore | 約 150MB | 3秒 | △ |
| v3 マルチステージ | + ビルドと実行の分離 | 約 130MB | 3秒 | ○ |
| v4 完成形 | + 非rootユーザー、HEALTHCHECK | 約 130MB | 3秒 | ◎ |
コンテナ侵害時の影響範囲を最小化するため、本番イメージでは必ず
USER 命令で専用ユーザーを指定しましょう。COPY --chown=app:app でファイル所有者も統一するのがベストプラクティスです。
📖 詳細はこちら:3.5 docker build 完全実践|Webアプリを一からDockerize するステップバイステップ
5. マルチステージビルド|本番イメージを1/10にする
Go ならビルドツール込みの 900MB イメージが、マルチステージを使うと 15MB の静的バイナリだけになります。発想は「ビルド用ステージと実行用ステージを分ける」だけ。
# Stage 1: ビルダー(名前を builder に)
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /bin/app
# Stage 2: 本番(最小イメージ+バイナリだけ)
FROM alpine:3.19
COPY --from=builder /bin/app /usr/local/bin/app
CMD ["app"]
# 最終イメージ: 約 15MB(900MB → 60分の1)
キモは FROM ... AS <name> でステージに名前を付け、COPY --from=<name> で別ステージから成果物だけを持ち出すこと。
--target で開発・テスト・本番を1本化docker build --target test、--target production のように、1つのDockerfileで複数の環境を切り替えられます。CI/CDとの相性が抜群です(第12章で詳説)。
📖 詳細はこちら:3.3 Dockerマルチステージビルド完全ガイド|イメージサイズを1/10に削減する実践テクニック
6. イメージの軽量化戦略|full / slim / alpine / distroless / scratch
最後のピースはベースイメージ選び。同じアプリでも、ベース次第で 1GB から 50MB 以下まで差が出ます。
| 種別 | 代表タグ | サイズ | 向き |
|---|---|---|---|
| full | python:3.12 |
約 1GB | 開発・デバッグ用 |
| slim | python:3.12-slim |
約 130MB | 本番のデフォルト候補 |
| alpine | python:3.12-alpine |
約 55MB | サイズ最優先・互換性要注意 |
| distroless | gcr.io/distroless/python3 |
約 50MB | セキュリティ重視の本番 |
| scratch | scratch |
0バイト | 静的バイナリ専用(Go等) |
「alpine が一番軽いから」と安易に選ぶと、Python の numpy や pandas などでソースビルドが走り、ビルド時間が10倍以上になることも。Pythonなら slim の方が結果的に速くて小さいケースも多々あります。思い込みではなく実測で比較しましょう。
📖 詳細はこちら:3.6 Dockerイメージ軽量化の完全ガイド|full・slim・alpine・distroless・scratch の使い分け
✅ 第3章のまとめ
第3章を通して、「動くDockerfile」から「本番で戦えるDockerfile」への進化の道筋を学びました。要点を7つに整理します。
- Dockerfile は上から順に実行され、1命令=1レイヤー。
FROM・RUN・COPY・CMDの4つがコア命令。 - レイヤーキャッシュは「上から順に一致」で評価。変更頻度の低い命令を上、高いものを下に書くのが最大の最適化ポイント。
- COPYは必ず分割。依存定義(package.json/requirements.txt)を先にコピー→インストール→ソースコピーの順が鉄則。
- マルチステージビルドでビルドツールを本番に残さない。
FROM ... AS builderとCOPY --from=builderの組み合わせで劇的にスリム化できる。 - .dockerignore は必須。ビルド高速化・イメージ軽量化・情報漏洩防止の3つに直接効く。特に
.envと.git/の除外は絶対。 - 本番では非rootユーザー+HEALTHCHECK。
USERで専用ユーザーを指定し、HEALTHCHECKで Docker/Kubernetes が異常検知できる状態に。 - ベースイメージは用途で選ぶ。迷ったら
slim、セキュリティ重視ならdistroless、Go/Rust の静的バイナリならscratch。alpine は実測して判断。
これで「とりあえず動くだけのDockerfile」ではなく、ビルド時間・イメージサイズ・セキュリティの3つを意識した本番品質のDockerfileが書けるようになっているはずです。CI/CDに組み込むための土台も整いました。
次のステップ:第4章へ
Dockerfile でイメージを作れるようになった次は、「そのコンテナで扱うデータをどう守るか」が課題になります。コンテナは docker rm で削除するとデータも消える”エフェメラル”な性質を持つため、本格運用にはデータ永続化の技術が必須です。
・ボリューム(Named Volume)とバインドマウントの使い分け
・tmpfs マウントでメモリ上の一時データを扱う
・ボリュームのバックアップとリストア
DB・ログ・アップロードファイルなど、本番運用で消えたら困るデータすべてに関わる章です。
章間の移動:
- ← 第2章 イメージとコンテナの基本操作
- → 第4章 データの永続化(近日公開)
参考リンク
- Dockerfile reference(Docker公式) — 全命令の完全リファレンス。
- Dockerfile best practices — 公式のベストプラクティス集。章の内容と照らし合わせて読むと理解が深まる。
- Docker Build Cache — レイヤーキャッシュの公式解説。
- Multi-stage builds — マルチステージビルドの公式ガイド。



コメント