STEP 14:マルチステージビルド

🏗️ STEP 14: マルチステージビルド

ビルド用と実行用を分離して、究極に小さいイメージを作る

📋 このステップで学ぶこと

  • マルチステージビルドとは何か
  • ビルド用と実行用のステージを分離する方法
  • イメージサイズを劇的に削減するテクニック
  • セキュリティを向上させる方法
  • 実践例:Pythonアプリの最適化
  • 実践演習でマルチステージビルドを実装

🔧 0. このステップの前提知識

📚 STEP 13の復習

このステップでは、以下の知識を使います。忘れた場合は復習してから進めましょう。

  • STEP 13:レイヤーキャッシュの仕組み(各命令が1つのレイヤーを作成)
  • STEP 13:イメージサイズを削減するテクニック(軽量ベースイメージ、RUNをまとめる)
  • STEP 13:同じRUN内で削除しないとサイズは減らない

0-1. 作業ディレクトリの準備

# 作業ディレクトリを作成して移動 mkdir -p ~/docker-practice/step14 cd ~/docker-practice/step14 # 現在の場所を確認 pwd

0-2. このステップで得られるスキル

【マルチステージビルドの効果】 シングルステージ マルチステージ ───────────────────────── ───────────────────────── イメージサイズ: 1.5GB イメージサイズ: 200MB 含まれるパッケージ: 500+ 含まれるパッケージ: 100 ビルドツール: gcc, g++, make ビルドツール: なし セキュリティリスク: 高 セキュリティリスク: 低 💡 このステップを学ぶと、イメージサイズを80〜90%削減、 セキュリティを大幅に向上できるようになります!

🎯 1. マルチステージビルドとは?

1-1. 基本概念

マルチステージビルドとは、1つのDockerfileの中で複数のステージ(段階)を定義し、
各ステージを独立して実行できる機能です。

📝 例え話:料理の準備と提供

レストランで料理を作ることを想像してください。

【キッチン(ビルドステージ)】
• 野菜を切る包丁
• 調理器具がたくさん
• 材料の袋やパッケージ
• 作業台が散らかっている

【お客様のテーブル(実行ステージ)】
• 完成した料理だけ
• きれいなお皿
• 包丁や材料のゴミはない
• すっきり!

マルチステージビルドも同じで、「作る場所」と「使う場所」を分けることで、最終的なイメージに不要なものを含めません。

1-2. マルチステージビルドの仕組み

【マルチステージビルドの流れ】 ┌─────────────────────────────────────────────────────────────┐ │ ステージ1: ビルドステージ(builder) │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━│ │ FROM python:3.9 AS builder │ │ │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ • gcc, g++, make などのビルドツール ││ │ │ • numpy, pandas のソースコード ││ │ │ • コンパイル中の一時ファイル ││ │ │ • ビルド済みパッケージ ✓ ││ │ └─────────────────────────────────────────────────────────┘│ │ │ │ │ │ 必要なものだけコピー │ │ ▼ │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ ステージ2: 実行ステージ(最終イメージ) │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━│ │ FROM python:3.9-slim │ │ COPY –from=builder /root/.local /root/.local │ │ │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ • ビルド済みパッケージのみ ✓ ││ │ │ • アプリケーションコード ││ │ │ • ビルドツールは含まれない ✓ ││ │ │ • 中間ファイルも含まれない ✓ ││ │ └─────────────────────────────────────────────────────────┘│ └─────────────────────────────────────────────────────────────┘ 【結果】 ビルドステージ: 1.5GB(破棄される) 実行ステージ: 200MB ← これが最終イメージ

1-3. なぜマルチステージビルドが必要?

💡 マルチステージビルドの利点
  • イメージサイズの劇的な削減:ビルドツールを含めない → 50〜90%削減
  • セキュリティ向上:不要なツールがない → 攻撃面が減る
  • クリーンな最終イメージ:実行に必要なものだけ
  • Dockerfileが1つ:管理が楽

1-4. シングルステージ vs マルチステージ

❌ シングルステージ

問題点:
• ビルドツールも含まれる
• イメージサイズ:1.5GB
• 中間ファイルも残る
• セキュリティリスク高
• 不要なファイルだらけ

✅ マルチステージ

改善:
• 実行ファイルだけコピー
• イメージサイズ:200MB
• クリーンな構成
• セキュリティリスク低
• 必要なものだけ

🏗️ 2. ビルド用と実行用の分離

2-1. 基本的な構造

マルチステージビルドでは、複数のFROM命令を使って、ステージを分離します。

# ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ1: ビルドステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS builder WORKDIR /app # ビルドに必要なツールをインストール RUN apt-get update && apt-get install -y gcc g++ make # 依存関係をインストール COPY requirements.txt . RUN pip install –user -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ2: 実行ステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9-slim WORKDIR /app # ステージ1からビルド済みパッケージだけコピー COPY –from=builder /root/.local /root/.local # アプリケーションコードをコピー COPY app.py . # PATHを設定 ENV PATH=/root/.local/bin:$PATH CMD [“python”, “app.py”]

2-2. キーポイントの解説

【マルチステージビルドの重要な構文】 FROM python:3.9 AS builder ────────── │ └─ ステージに名前を付ける この名前で後から参照できる COPY –from=builder /root/.local /root/.local ────────────── │ └─ 前のステージからファイルをコピー builder ステージの /root/.local を 現在のステージにコピー 【ポイント】 • 最後の FROM が最終イメージになる • 中間ステージは破棄される • 名前を付けないと FROM 0、FROM 1 で参照(非推奨)

2-3. 各ステージの役割

ステージ 役割
ビルドステージ(builder) ソースコードのコンパイル、依存関係のビルド、静的ファイルの生成、テストの実行
実行ステージ(最終) ビルド済みファイルだけ受け取る、実行に必要な最小限の環境、アプリケーションの実行

2-4. pip install –user の意味

📝 –user オプションとは?

pip install --userは、パッケージをユーザーディレクトリ(/root/.local)にインストールします。

なぜ使うのか?
• システム全体にインストールすると、Python本体のディレクトリにパッケージが混ざる
--userを使うと、/root/.localにまとまる
• まとまった場所をCOPY --fromでコピーしやすい

📦 3. イメージサイズの大幅削減

3-1. 実例:シングルステージ vs マルチステージ

実際の数字で比較してみましょう。

【例1】シングルステージ(最適化なし)

# シングルステージ FROM python:3.9 WORKDIR /app # ビルドツールをインストール RUN apt-get update && \ apt-get install -y gcc g++ make COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD [“python”, “app.py”]
# イメージサイズを確認 $ docker images myapp:single REPOSITORY TAG SIZE myapp single 1.5GB

【例2】マルチステージ

# マルチステージ FROM python:3.9 AS builder WORKDIR /app RUN apt-get update && \ apt-get install -y gcc g++ make COPY requirements.txt . RUN pip install –user -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━ # 実行ステージ FROM python:3.9-slim WORKDIR /app COPY –from=builder /root/.local /root/.local COPY app.py . ENV PATH=/root/.local/bin:$PATH CMD [“python”, “app.py”]
# イメージサイズを確認 $ docker images myapp:multi REPOSITORY TAG SIZE myapp multi 250MB # 削減率:約83%!

3-2. なぜこんなに小さくなる?

💡 サイズ削減の理由
  • ビルドツール不要:gcc、g++、makeなどは実行ステージに含まれない
  • 軽量ベースイメージ:実行ステージはpython:3.9-slim
  • 中間ファイル不要:ビルドキャッシュなどは破棄される
  • 必要なものだけ:ビルド済みパッケージだけコピー
サイズ削減の内訳
項目 シングルステージ マルチステージ
ベースイメージ python:3.9(約900MB) python:3.9-slim(約150MB)
ビルドツール gcc, g++, make(約300MB) なし(0MB)
Pythonパッケージ 約300MB 約100MB(必要なもののみ)
合計 約1.5GB 約250MB

🔒 4. セキュリティの向上

4-1. マルチステージビルドのセキュリティメリット

🔐 セキュリティが向上する理由
  • 攻撃面の縮小:ビルドツールがない = 悪用できるツールが少ない
  • 脆弱性の削減:パッケージ数が少ない = セキュリティリスク低下
  • クリーンな環境:不要なファイルがない = 情報漏洩リスク低下

4-2. 含まれるパッケージ数の比較

❌ シングルステージ

含まれるパッケージ:
• gcc, g++, make
• build-essential
• curl, wget
• git
• その他開発ツール
合計:約500パッケージ

✅ マルチステージ

含まれるパッケージ:
• Python本体
• 必要なライブラリのみ
• 実行時依存関係のみ

合計:約100パッケージ

4-3. セキュリティベストプラクティス

💡 セキュリティベストプラクティス
  • ビルドツールは実行ステージに含めない
  • 実行ステージは軽量ベースイメージを使う
  • 非rootユーザーで実行する
  • 定期的にイメージの脆弱性スキャンを実行
# 非rootユーザーで実行する例 FROM python:3.9-slim WORKDIR /app COPY –from=builder /root/.local /root/.local COPY app.py . ENV PATH=/root/.local/bin:$PATH # 非rootユーザーを作成して切り替え RUN useradd -m appuser && \ chown -R appuser:appuser /app USER appuser CMD [“python”, “app.py”]

🐍 5. 実践例:Pythonアプリの最適化

5-1. numpy/pandasを使うアプリ

データ分析用のライブラリは、ビルドに時間がかかります。
マルチステージビルドで最適化しましょう。

# Dockerfile(マルチステージ) # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ビルドステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS builder WORKDIR /app # ビルドに必要なパッケージ RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ g++ \ gfortran \ libopenblas-dev \ liblapack-dev && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . # ユーザーディレクトリにインストール RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # 実行ステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9-slim WORKDIR /app # 実行に必要な依存関係のみ RUN apt-get update && \ apt-get install -y –no-install-recommends \ libopenblas-base \ libgomp1 && \ rm -rf /var/lib/apt/lists/* # ビルドステージからパッケージをコピー COPY –from=builder /root/.local /root/.local # アプリケーションコード COPY app.py . COPY data_processor.py . # PATHを設定 ENV PATH=/root/.local/bin:$PATH # 非rootユーザーで実行 RUN useradd -m appuser && \ chown -R appuser:appuser /app USER appuser CMD [“python”, “app.py”]
🎯 最適化のポイント
  • ビルドステージ:gcc、g++などでnumpy/pandasをビルド
  • 実行ステージ:ビルドツールは不要、実行時依存だけインストール
  • サイズ削減:1.5GB → 600MB(60%削減)
  • セキュリティ:非rootユーザーで実行

5-2. Flaskアプリケーション

# Dockerfile(Flask + gunicorn) # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ビルドステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS builder WORKDIR /app COPY requirements.txt . # 依存関係をビルド RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # 実行ステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9-slim WORKDIR /app # ビルド済みパッケージをコピー COPY –from=builder /root/.local /root/.local # アプリケーションコード COPY app.py . COPY config.py . COPY templates/ templates/ COPY static/ static/ # PATHを設定 ENV PATH=/root/.local/bin:$PATH ENV FLASK_APP=app.py ENV FLASK_ENV=production # 非rootユーザー RUN useradd -m flaskuser && \ chown -R flaskuser:flaskuser /app USER flaskuser EXPOSE 5000 CMD [“gunicorn”, “–bind”, “0.0.0.0:5000”, “app:app”]

🛠️ 6. 実践演習

6-1. 演習の目標

実際にマルチステージビルドを実装して、シングルステージと比較してみましょう。

📁 プロジェクト構成
multistage-demo/ ├── Dockerfile.single # シングルステージ(比較用) ├── Dockerfile.multi # マルチステージ ├── requirements.txt ├── app.py └── data_processor.py

6-2. 演習ファイルの作成

# 作業ディレクトリを作成 mkdir -p ~/docker-practice/multistage-demo cd ~/docker-practice/multistage-demo # requirements.txt を作成 cat > requirements.txt << ‘EOF’ numpy==1.21.0 pandas==1.3.0 requests==2.26.0 EOF # app.py を作成 cat > app.py << ‘EOF’ import pandas as pd import numpy as np from data_processor import process_data def main(): print(“データ処理を開始します…”) # データの読み込み data = pd.DataFrame({ ‘name’: [‘Alice’, ‘Bob’, ‘Charlie’], ‘score’: [85, 90, 78] }) # データ処理 result = process_data(data) print(“処理結果:”) print(result) print(“\nデータ処理が完了しました!”) if __name__ == “__main__”: main() EOF # data_processor.py を作成 cat > data_processor.py << ‘EOF’ import pandas as pd import numpy as np def process_data(df): “””データ処理関数””” # 平均を計算 df[‘average’] = df[‘score’].mean() # ランクを追加 df[‘rank’] = df[‘score’].rank(ascending=False) return df EOF

6-3. シングルステージDockerfileを作成

# Dockerfile.single を作成 cat > Dockerfile.single << ‘EOF’ # シングルステージ(比較用) FROM python:3.9 WORKDIR /app # ビルドツールをインストール RUN apt-get update && \ apt-get install -y gcc g++ gfortran && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt COPY . . CMD [“python”, “app.py”] EOF

6-4. マルチステージDockerfileを作成

# Dockerfile.multi を作成 cat > Dockerfile.multi << ‘EOF’ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ビルドステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS builder WORKDIR /app # ビルドに必要なパッケージ RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ g++ \ gfortran && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . # ユーザーディレクトリにインストール RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # 実行ステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9-slim WORKDIR /app # ビルドステージからパッケージをコピー COPY –from=builder /root/.local /root/.local # アプリケーションコード COPY app.py . COPY data_processor.py . # PATHを設定 ENV PATH=/root/.local/bin:$PATH CMD [“python”, “app.py”] EOF

6-5. ビルドして比較

# シングルステージをビルド docker build -f Dockerfile.single -t dataapp:single . # マルチステージをビルド docker build -f Dockerfile.multi -t dataapp:multi . # サイズを比較 docker images | grep dataapp
REPOSITORY TAG IMAGE ID CREATED SIZE dataapp single abc123def456 2 minutes ago 1.2GB dataapp multi def456abc789 1 minute ago 300MB # マルチステージは約75%削減!

6-6. 両方を実行して動作確認

# シングルステージを実行 docker run –rm dataapp:single # マルチステージを実行 docker run –rm dataapp:multi
データ処理を開始します… 処理結果: name score average rank 0 Alice 85 84.3 2.0 1 Bob 90 84.3 1.0 2 Charlie 78 84.3 3.0 データ処理が完了しました!

6-7. 後片付け

# 作成したイメージを削除 docker rmi dataapp:single dataapp:multi
✅ 演習のまとめ
  • 両方のイメージが同じように動作する
  • マルチステージは約75%小さい
  • ビルドツールは最終イメージに含まれない
  • セキュリティも向上している

🚀 7. 高度なテクニック

7-1. 複数のビルドステージ

3つ以上のステージを使うこともできます。

# 複数ステージの例 # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ1: テストステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS tester WORKDIR /app COPY requirements.txt requirements-dev.txt ./ RUN pip install -r requirements.txt -r requirements-dev.txt COPY . . # テストを実行(失敗したらビルドが止まる) RUN pytest tests/ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ2: ビルドステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS builder WORKDIR /app RUN apt-get update && \ apt-get install -y gcc g++ && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ3: 実行ステージ # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9-slim WORKDIR /app COPY –from=builder /root/.local /root/.local COPY app.py . ENV PATH=/root/.local/bin:$PATH CMD [“python”, “app.py”]

7-2. 特定のステージだけビルド

# テストステージだけビルド(本番イメージは作らない) docker build –target tester -t myapp:test . # ビルドステージまでビルド(デバッグ用) docker build –target builder -t myapp:builder . # 最終ステージまでビルド(通常) docker build -t myapp:latest .
📝 –target オプションの活用
  • テスト実行--target testerでテストだけ実行
  • デバッグ--target builderでビルド環境を確認
  • CI/CD:テストステージをCI、最終ステージをCDで使い分け

💪 8. 練習問題

練習問題 1 基礎

マルチステージビルドの利点を3つ挙げてください。

【解答例】
  1. イメージサイズの削減:ビルドツールや中間ファイルを含めないため、最終イメージが50〜90%小さくなる
  2. セキュリティの向上:不要なパッケージやツールがないため、攻撃面が縮小し、脆弱性のリスクが減る
  3. クリーンな構成:実行に必要なものだけが含まれるため、イメージがシンプルで管理しやすい
練習問題 2 基礎

次のDockerfileで、COPY --from=builderは何をしていますか?

FROM python:3.9 AS builder RUN pip install –user numpy FROM python:3.9-slim COPY –from=builder /root/.local /root/.local
【解答】

COPY --from=builderは、builderステージからファイルをコピーしています。

具体的には:
• builderステージでインストールされたnumpyパッケージ
/root/.localディレクトリ全体を、実行ステージの同じパスにコピー

これにより、ビルドツール(gcc等)は含めずに、ビルド済みパッケージだけを実行ステージに持ってくることができます。

練習問題 3 応用

次のシングルステージDockerfileをマルチステージに書き換えてください。

FROM python:3.9 WORKDIR /app RUN apt-get update && \ apt-get install -y gcc g++ COPY requirements.txt . RUN pip install -r requirements.txt COPY app.py . CMD [“python”, “app.py”]
【マルチステージ版】
# ビルドステージ FROM python:3.9 AS builder WORKDIR /app RUN apt-get update && \ apt-get install -y gcc g++ && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # 実行ステージ FROM python:3.9-slim WORKDIR /app # ビルド済みパッケージをコピー COPY –from=builder /root/.local /root/.local # アプリケーションコード COPY app.py . # PATHを設定 ENV PATH=/root/.local/bin:$PATH CMD [“python”, “app.py”]
練習問題 4 応用

Flask + gunicornのアプリケーション用マルチステージDockerfileを作成してください。

要件:
• requirements.txt: Flask, gunicorn
• アプリケーション: app.py, config.py, templates/
• 非rootユーザーで実行
• イメージサイズを最小化

【解答】
# ビルドステージ FROM python:3.9 AS builder WORKDIR /app COPY requirements.txt . RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # 実行ステージ FROM python:3.9-slim WORKDIR /app # ビルド済みパッケージをコピー COPY –from=builder /root/.local /root/.local # アプリケーションファイル COPY app.py . COPY config.py . COPY templates/ templates/ # 環境変数 ENV PATH=/root/.local/bin:$PATH ENV FLASK_APP=app.py ENV FLASK_ENV=production # 非rootユーザー RUN useradd -m flaskuser && \ chown -R flaskuser:flaskuser /app USER flaskuser EXPOSE 5000 CMD [“gunicorn”, “–bind”, “0.0.0.0:5000”, “app:app”]
練習問題 5 発展

次の要件を満たすマルチステージDockerfileを作成してください。

  • ステージ1:テストを実行(pytest)
  • ステージ2:依存関係をビルド
  • ステージ3:実行環境(最小構成)
  • テストが失敗したらビルドを中止
【解答】
# ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ1: テスト # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS tester WORKDIR /app # テスト用の依存関係 COPY requirements.txt requirements-dev.txt ./ RUN pip install –no-cache-dir -r requirements.txt -r requirements-dev.txt # テストコード COPY tests/ tests/ COPY app.py . COPY data_processor.py . # テストを実行(失敗したらここでビルドが止まる) RUN pytest tests/ -v # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ2: ビルド # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9 AS builder WORKDIR /app RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ g++ && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # ステージ3: 実行 # ━━━━━━━━━━━━━━━━━━━━━━━━━━ FROM python:3.9-slim WORKDIR /app # ビルド済みパッケージをコピー COPY –from=builder /root/.local /root/.local # アプリケーションコード COPY app.py . COPY data_processor.py . ENV PATH=/root/.local/bin:$PATH # 非rootユーザー RUN useradd -m appuser && \ chown -R appuser:appuser /app USER appuser CMD [“python”, “app.py”]

ビルド方法:

# 通常のビルド(全ステージ実行、テスト含む) docker build -t myapp:latest . # テストステージだけ実行(デバッグ用) docker build –target tester -t myapp:test .
練習問題 6 応用

マルチステージビルドで、イメージサイズが1.5GB→300MBになりました。削減率は何%ですか?

【解答】

削減率の計算式:
(元のサイズ - 新しいサイズ) ÷ 元のサイズ × 100

(1.5GB – 300MB) ÷ 1.5GB × 100 = (1500MB – 300MB) ÷ 1500MB × 100 = 1200MB ÷ 1500MB × 100 = 0.8 × 100 = 80%

答え:80%削減
元のサイズの20%まで小さくなったということです。

練習問題 7 発展

–target オプションの使い方と用途を説明してください。

【解答】

–target オプションとは:

マルチステージビルドで、特定のステージまでビルドするオプションです。

# 構文 docker build –target ステージ名 -t イメージ名 .

用途:

  • テスト実行:--target testerでテストステージだけ実行し、テストが通るか確認
  • デバッグ:--target builderでビルド環境に入り、問題を調査
  • CI/CD:CIではテストステージ、CDでは最終ステージを使い分け
  • 開発効率化:必要なステージだけビルドして時間を節約
# 例:テストステージだけ実行 docker build –target tester -t myapp:test . # 例:ビルドステージまで実行(デバッグ用) docker build –target builder -t myapp:debug . docker run -it myapp:debug bash
練習問題 8 発展

scikit-learnを使うデータサイエンスアプリのマルチステージDockerfileを作成してください。実行時に必要なライブラリ(libopenblas等)も考慮すること。

【解答】
# ビルドステージ FROM python:3.9 AS builder WORKDIR /app # ビルドに必要なツール RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ g++ \ gfortran \ libopenblas-dev \ liblapack-dev && \ rm -rf /var/lib/apt/lists/* # requirements.txt # numpy==1.21.0 # pandas==1.3.0 # scikit-learn==0.24.2 COPY requirements.txt . RUN pip install –user –no-cache-dir -r requirements.txt # ━━━━━━━━━━━━━━━━━━━━━━━━━━ # 実行ステージ FROM python:3.9-slim WORKDIR /app # 実行時に必要な依存関係(重要!) RUN apt-get update && \ apt-get install -y –no-install-recommends \ libopenblas-base \ libgomp1 && \ rm -rf /var/lib/apt/lists/* # ビルド済みパッケージ COPY –from=builder /root/.local /root/.local # アプリケーションコード COPY *.py ./ ENV PATH=/root/.local/bin:$PATH RUN useradd -m dsuser && \ chown -R dsuser:dsuser /app USER dsuser CMD [“python”, “train.py”]

ポイント:

  • libopenblas-base:numpy/scikit-learnの実行に必要
  • libgomp1:OpenMPの実行時ライブラリ(並列処理に必要)
  • ビルドツール(gcc等)は実行ステージに含まれない
  • サイズ:約1.5GB → 約600MB(60%削減)

📝 STEP 14 のまとめ

✅ このステップで学んだこと
  • マルチステージビルド:ビルド用と実行用のステージを分離
  • FROM … AS name:ステージに名前を付ける
  • COPY –from=:前のステージからファイルをコピー
  • イメージサイズ削減:ビルドツールを含めないことで50〜90%削減
  • セキュリティ向上:不要なパッケージがない = 脆弱性が少ない
  • –target:特定のステージだけビルド
📊 マルチステージビルドのパターン
パターン ビルドステージ 実行ステージ
Pythonアプリ python:3.9 + gcc python:3.9-slim
データサイエンス python:3.9 + gcc/gfortran python:3.9-slim + libopenblas
Node.js(フロント) node:16(npm build) nginx:alpine(静的配信)
Go言語 golang:1.17(コンパイル) scratch / alpine(バイナリのみ)
💡 重要ポイント
  • マルチステージビルドは本番環境では必須のテクニック
  • イメージサイズを劇的に削減できる(80〜90%も可能)
  • セキュリティとパフォーマンスが大幅に向上する
  • Dockerfileが1つで管理できるため、メンテナンスが楽
🎯 次のステップの予告

次のSTEP 15では、「Docker Composeとは」を学びます。

  • 複数のコンテナを簡単に管理
  • docker-compose.ymlの基本構造
  • サービスの定義と起動
  • PostgreSQL、Airflow、Sparkなどを連携

複数コンテナの世界へ踏み出しましょう!

📝

学習メモ

Docker・コンテナ技術入門 - Step 14

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE