STEP 13:レイヤーキャッシュと最適化

🚀 STEP 13: レイヤーキャッシュと最適化

Dockerイメージのビルドを高速化し、サイズを最小化するテクニック

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

  • レイヤーキャッシュの仕組みを深く理解する
  • .dockerignoreファイルの活用方法
  • 命令の順序を最適化してビルド時間を短縮する
  • イメージサイズを最小化するテクニック
  • 不要なファイルを削除する正しい方法
  • 実践演習でイメージサイズを大幅に削減する

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

📚 STEP 11・12の復習

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

  • STEP 11:Dockerfileの基本命令(FROM、RUN、COPY、WORKDIR、CMD)
  • STEP 11:レイヤーの基本概念(各命令が1つのレイヤーを作成)
  • STEP 12:requirements.txtを先にコピーするパターン

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

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

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

【最適化前と最適化後の違い】 最適化前 最適化後 ───────────────────────── ───────────────────────── イメージサイズ: 1.2GB イメージサイズ: 250MB 初回ビルド: 5分 初回ビルド: 3分 コード変更後の再ビルド: 5分 コード変更後の再ビルド: 10秒 💡 このステップを学ぶと、イメージサイズを80%削減、 再ビルド時間を97%短縮できるようになります!

🎯 1. レイヤーキャッシュの仕組み

1-1. レイヤーキャッシュとは?

Dockerは、イメージをビルドする際に各命令の結果をキャッシュします。
同じ命令を再度実行する時は、キャッシュを再利用することでビルド時間を大幅に短縮できます。

📝 例え話:レゴブロックの組み立て

レゴブロックで家を作ることを想像してください。

キャッシュがない場合:
毎回、1階から作り直す必要があります。ちょっと2階の窓を変えたいだけなのに、全部バラして最初からやり直し…

キャッシュがある場合:
1階はそのまま使って、2階だけ作り直せばOK!とても効率的ですね。

Dockerのレイヤーキャッシュも同じ仕組みです。変更がない部分は再利用して、変更があった部分だけ作り直します。

1-2. レイヤーキャッシュの動作を図解

【レイヤーキャッシュの動作】 Dockerfile 1回目のビルド 2回目(app.pyのみ変更) ──────────────────── ────────────── ────────────────────── ① FROM python:3.9-slim → Layer 1 作成 → Layer 1 キャッシュ使用 ✓ ② WORKDIR /app → Layer 2 作成 → Layer 2 キャッシュ使用 ✓ ③ COPY requirements.txt → Layer 3 作成 → Layer 3 キャッシュ使用 ✓ ④ RUN pip install … → Layer 4 作成 → Layer 4 キャッシュ使用 ✓ ⑤ COPY . . → Layer 5 作成 → Layer 5 再作成(変更あり) ⑥ CMD [“python”, “app”] → Layer 6 作成 → Layer 6 再作成 【結果】 1回目:5〜10分(全レイヤー作成) 2回目:10秒(⑤⑥だけ再作成) 💡 ポイント:変更があったレイヤー以降は全て再作成される

1-3. 実際のDockerfileで確認

# Dockerfile(キャッシュが効きやすい構造) FROM python:3.9-slim # ① ベースイメージ(キャッシュされる) WORKDIR /app # ② 作業ディレクトリ設定(キャッシュされる) COPY requirements.txt . # ③ requirements.txtをコピー(変更がなければキャッシュ) RUN pip install -r requirements.txt # ④ ライブラリをインストール(③がキャッシュされれば、これもキャッシュ) COPY . . # ⑤ アプリケーションコードをコピー(変更があれば再実行) CMD [“python”, “app.py”]
🎯 キャッシュの動作パターン

【app.pyだけ変更した場合】

  • ①〜④はキャッシュを再利用
  • ⑤だけ再実行(10秒)

【requirements.txtを変更した場合】

  • ①②はキャッシュを再利用
  • ③〜⑤を再実行(5分)

1-4. キャッシュが無効になるケース

⚠️ キャッシュが使えなくなる条件
  • Dockerfileの命令を変更した
  • COPYするファイルの内容が変更された
  • 前の命令でキャッシュが無効になった(それ以降の命令もすべて再実行
  • --no-cacheオプションを使った
# キャッシュを使わずにビルド(問題解決時に使用) docker build –no-cache -t myapp:latest .

📁 2. .dockerignoreファイルの活用

2-1. .dockerignoreとは?

.dockerignoreファイルは、Dockerのビルド時に無視するファイルやディレクトリを指定するファイルです。
Gitの.gitignoreと同じような役割です。

【.dockerignoreの効果】 .dockerignoreなし .dockerignoreあり ──────────────────────── ──────────────────────── ビルドコンテキストに送信: ビルドコンテキストに送信: ├── .git/(50MB) ❌ ├── app.py(1KB) ✓ ├── node_modules/(200MB)❌ ├── requirements.txt ✓ ├── data/(100MB) ❌ └── utils.py(1KB) ✓ ├── .env(機密情報) ❌ 危険! ├── tests/(10MB) ❌ ├── app.py(1KB) ✓ └── requirements.txt ✓ 合計: 360MB 合計: 3KB ビルド時間: 3分 ビルド時間: 10秒
📝 なぜ必要?
  • ビルド時間の短縮:不要なファイルをコピーしない
  • イメージサイズの削減:無駄なファイルが含まれない
  • セキュリティ向上:.envなど秘密情報を含むファイルを除外
  • キャッシュの効率化:無関係なファイル変更でキャッシュが無効にならない

2-2. .dockerignoreの書き方

プロジェクトのルートディレクトリ(Dockerfileと同じ場所)に.dockerignoreファイルを作成します。

# .dockerignoreファイルの例 # Gitファイル .git .gitignore .gitattributes # Python関連 __pycache__ *.pyc *.pyo *.pyd .Python *.so *.egg *.egg-info dist build .venv venv/ ENV/ # ドキュメント README.md docs/ *.md # テストファイル tests/ test_*.py *_test.py # 開発用ツール .vscode/ .idea/ *.swp *.swo # ログファイル *.log logs/ # データファイル(大きいファイル) *.csv *.xlsx data/ # 環境変数ファイル(秘密情報) .env .env.local *.key *.pem # OS関連 .DS_Store Thumbs.db # Docker関連(Dockerfile自体はCOPYしない) Dockerfile* docker-compose*.yml .dockerignore

2-3. .dockerignoreの実践

# .dockerignoreファイルを作成 cat > .dockerignore << ‘EOF’ .git __pycache__ *.pyc .venv venv/ *.log .env tests/ *.md Dockerfile* .dockerignore data/ EOF # ファイルが作成されたか確認 cat .dockerignore
❌ .dockerignoreなし

問題点:
• 全ファイルがコピーされる
• イメージサイズ:500MB
• ビルド時間:3分
• .gitディレクトリも含まれる
• テストファイルも含まれる

✅ .dockerignoreあり

改善:
• 必要なファイルだけコピー
• イメージサイズ:200MB
• ビルド時間:1分
• クリーンなイメージ
• セキュリティも向上

⚡ 3. 命令の順序最適化

3-1. 最適化の基本原則

💡 キャッシュを最大限活用するルール

変更頻度が低いものを先に、高いものを後に配置する

変更が少ない命令を上に置くことで、キャッシュが有効に使われ、ビルド時間が短縮されます。

【変更頻度による配置順序】 上(先に実行) 変更頻度 ───────────────────────────────────────────── FROM python:3.9-slim ほぼ変更なし WORKDIR /app ほぼ変更なし RUN apt-get install … 月に1回程度 COPY requirements.txt . 月に1回程度 RUN pip install … 月に1回程度 COPY config.py . 週に1回程度 COPY app.py . 毎日変更 ───────────────────────────────────────────── 下(後で実行) 💡 頻繁に変更されるファイルを下に配置することで、 キャッシュが有効活用される

3-2. 悪い例:非効率な順序

# ❌ 悪い例 FROM python:3.9-slim WORKDIR /app # すべてのファイルを先にコピー(変更が多い) COPY . . # 依存関係のインストール(変更が少ない) RUN pip install -r requirements.txt CMD [“python”, “app.py”]
⚠️ 問題点

アプリケーションコード(app.py)を少し変更しただけで、requirements.txtは変わっていないのに、pip installが毎回実行されてしまいます。

理由:COPY . .でキャッシュが無効になり、それ以降の命令がすべて再実行されるため。

3-3. 良い例:最適化された順序

# ✅ 良い例 FROM python:3.9-slim WORKDIR /app # 依存関係ファイルだけ先にコピー(変更が少ない) COPY requirements.txt . # 依存関係のインストール(キャッシュされやすい) RUN pip install -r requirements.txt # アプリケーションコードは最後(変更が多い) COPY . . CMD [“python”, “app.py”]
✅ 改善点

app.pyだけ変更した場合:
• requirements.txtは変更なし → pip installはキャッシュを使う
• 最後のCOPY . .だけ再実行
• ビルド時間:5分 → 10秒に短縮!

3-4. さらに最適化:段階的なコピー

# 🚀 さらに最適化 FROM python:3.9-slim WORKDIR /app # ① システムレベルの依存関係(ほとんど変更しない) RUN apt-get update && apt-get install -y \ gcc \ && rm -rf /var/lib/apt/lists/* # ② Python依存関係(たまに変更) COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt # ③ 設定ファイル(時々変更) COPY config.py . # ④ アプリケーションコード(頻繁に変更) COPY app.py . COPY utils.py . CMD [“python”, “app.py”]
🎯 変更頻度による分類
変更頻度 ファイルの種類
ほぼ変更なし ベースイメージ、システムパッケージ
たまに変更 requirements.txt、package.json
時々変更 設定ファイル、環境変数
頻繁に変更 アプリケーションコード

📦 4. イメージサイズの最小化テクニック

4-1. なぜサイズを小さくするのか?

📝 小さいイメージのメリット
  • 高速ダウンロード:デプロイが速い
  • ストレージ節約:Docker Hubの容量制限に優しい
  • セキュリティ向上:不要なパッケージがない = 脆弱性が少ない
  • 起動が速い:コンテナの起動時間短縮

4-2. テクニック1:軽量ベースイメージを使う

Pythonベースイメージのサイズ比較
イメージ サイズ 特徴
python:3.9 約1GB フル版。開発・デバッグに便利
python:3.9-slim 約150MB 本番環境に推奨
python:3.9-alpine 約50MB 超軽量。一部ライブラリに注意
💡 ベースイメージの選び方
  • 開発環境:通常版(python:3.9)でOK
  • 本番環境:slimを推奨
  • 最小サイズ優先:alpineを検討(ただし、一部ライブラリが動かないことも)

4-3. テクニック2:複数のRUNをまとめる

# ❌ 悪い例:レイヤーが増える FROM python:3.9-slim RUN apt-get update RUN apt-get install -y gcc RUN apt-get install -y curl RUN apt-get install -y vim # 4つのレイヤーが作られる # 各レイヤーにキャッシュが残る
# ✅ 良い例:1つのレイヤー FROM python:3.9-slim RUN apt-get update && \ apt-get install -y \ gcc \ curl \ vim && \ rm -rf /var/lib/apt/lists/* # 1つのレイヤーのみ # キャッシュも削除される

4-4. テクニック3:不要なファイルを削除する

# ✅ ビルド時に不要ファイルを削除 FROM python:3.9-slim WORKDIR /app # パッケージインストール後、キャッシュを削除 RUN apt-get update && \ apt-get install -y gcc && \ rm -rf /var/lib/apt/lists/* # Pythonパッケージインストール後、キャッシュを削除 COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt COPY . . CMD [“python”, “app.py”]
🎯 削除すべきファイル
  • /var/lib/apt/lists/*:aptのキャッシュ
  • ~/.cache:各種キャッシュファイル
  • *.pyc:Pythonのコンパイル済みファイル
  • 一時ファイル、ログファイル

4-5. イメージサイズの確認方法

# イメージ一覧とサイズ確認 docker images # 出力例: # REPOSITORY TAG IMAGE ID CREATED SIZE # myapp latest abc123def456 5 minutes ago 200MB # myapp v1 def456abc789 1 day ago 500MB # 特定イメージの詳細 docker image inspect myapp:latest # レイヤーごとのサイズを確認 docker history myapp:latest

🧹 5. 不要なファイルの削除(重要)

5-1. 削除のタイミングが重要

💡 最重要ルール

ファイルは同じRUN命令内で削除する必要があります。

別のRUN命令で削除しても、イメージサイズは減りません!
なぜなら、Dockerのレイヤーは追加のみで、削除は「見えなくなる」だけだからです。

【レイヤーの仕組み】 RUN でファイルを作成 別の RUN で削除 ──────────────────── ──────────────────── ┌──────────────────┐ ┌──────────────────┐ │ Layer 2 │ │ Layer 3 │ │ bigfile.tar.gz │ │ (削除マーク) │ │ (100MB) │ │ │ └──────────────────┘ └──────────────────┘ ↓ ↓ 100MB追加 0MB追加 ※削除しても Layer 2は残る! 【結果】イメージサイズ = 100MB + 0MB = 100MB(減らない!)

5-2. 悪い例:削除が効果なし

# ❌ 悪い例 FROM python:3.9-slim # 大きなファイルをダウンロード(Layer 2: 100MB追加) RUN curl -o bigfile.tar.gz https://example.com/bigfile.tar.gz # 展開(Layer 3: 50MB追加) RUN tar -xzf bigfile.tar.gz # 削除(Layer 4: 0MB)でもレイヤー2には残ったまま! RUN rm bigfile.tar.gz # イメージサイズは減らない(150MB)

5-3. 良い例:同じRUN内で削除

# ✅ 良い例 FROM python:3.9-slim # ダウンロード→展開→削除を1つのRUNで RUN curl -o bigfile.tar.gz https://example.com/bigfile.tar.gz && \ tar -xzf bigfile.tar.gz && \ rm bigfile.tar.gz # この方法ならイメージサイズが小さくなる(50MB)

5-4. 実践例:ビルドツールのインストールと削除

# 開発用ツールをインストール→使用→削除 FROM python:3.9-slim WORKDIR /app # ビルドに必要なパッケージをインストール→使用→削除 RUN apt-get update && \ apt-get install -y gcc g++ make && \ # ここで何か処理(例:ライブラリのコンパイル) pip install numpy && \ # ビルドツールを削除 apt-get purge -y gcc g++ make && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt COPY . . CMD [“python”, “app.py”]
🎯 削除のベストプラクティス
  • ダウンロードしたアーカイブは展開後すぐ削除
  • ビルドツールはビルド完了後すぐ削除
  • apt-get autoremoveで不要な依存パッケージも削除
  • pip install --no-cache-dirでキャッシュを残さない

🛠️ 6. 実践演習:イメージサイズの削減

6-1. 演習の目標

実際に最適化前と最適化後のDockerfileを作って、効果を確認しましょう。

📁 演習用のプロジェクト構成
optimization-demo/ ├── Dockerfile.before # 最適化前 ├── Dockerfile.after # 最適化後 ├── requirements.txt ├── app.py ├── utils.py ├── .dockerignore └── data/ └── sample.csv

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

# 作業ディレクトリを作成 mkdir -p ~/docker-practice/optimization-demo cd ~/docker-practice/optimization-demo # app.py を作成 cat > app.py << ‘EOF’ import pandas as pd print(“Hello from optimized Docker!”) print(f”Pandas version: {pd.__version__}”) EOF # utils.py を作成 cat > utils.py << ‘EOF’ def helper(): return “Helper function” EOF # requirements.txt を作成 cat > requirements.txt << ‘EOF’ pandas==2.0.0 numpy==1.24.2 EOF # dataディレクトリとサンプルデータを作成 mkdir -p data echo “id,name,value” > data/sample.csv echo “1,Alice,100” >> data/sample.csv

6-3. 最適化前のDockerfile

# Dockerfile.before を作成 cat > Dockerfile.before << ‘EOF’ # Dockerfile.before(最適化前) # 大きいベースイメージ FROM python:3.9 # すべてのファイルを先にコピー COPY . /app WORKDIR /app # 複数のRUNに分割 RUN apt-get update RUN apt-get install -y gcc RUN apt-get install -y curl RUN pip install -r requirements.txt CMD [“python”, “app.py”] EOF

6-4. .dockerignoreファイルを作成

# .dockerignore を作成 cat > .dockerignore << ‘EOF’ __pycache__ *.pyc .git .vscode *.log data/ tests/ README.md Dockerfile* .dockerignore EOF

6-5. 最適化後のDockerfile

# Dockerfile.after を作成 cat > Dockerfile.after << ‘EOF’ # Dockerfile.after(最適化後) # 軽量ベースイメージ FROM python:3.9-slim WORKDIR /app # 依存関係ファイルだけ先にコピー COPY requirements.txt . # パッケージインストールを1つのRUNにまとめる RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ curl && \ pip install –no-cache-dir -r requirements.txt && \ # 不要なパッケージを削除 apt-get purge -y gcc && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* # アプリケーションコードは最後 COPY app.py . COPY utils.py . CMD [“python”, “app.py”] EOF

6-6. ビルドして比較

# 最適化前のイメージをビルド docker build -f Dockerfile.before -t myapp:before . # 最適化後のイメージをビルド docker build -f Dockerfile.after -t myapp:after . # サイズを比較 docker images | grep myapp
# 出力例: REPOSITORY TAG SIZE myapp before 1.2GB myapp after 250MB # サイズが約5分の1に削減!

6-7. ビルド時間を比較

# app.pyを少し変更 echo ‘print(“Modified!”)’ >> app.py # 最適化前を再ビルド(全部やり直し) time docker build -f Dockerfile.before -t myapp:before . # 結果:約5分 # 最適化後を再ビルド(最後だけ) time docker build -f Dockerfile.after -t myapp:after . # 結果:約10秒
✅ 最適化の効果まとめ
項目 最適化前 最適化後
イメージサイズ 1.2GB 250MB(約80%削減)
初回ビルド時間 5分 3分(少し改善)
コード変更後の再ビルド 5分 10秒(97%短縮!)

6-8. 後片付け

# 作成したイメージを削除 docker rmi myapp:before myapp:after

💪 7. 練習問題

練習問題 1 基礎

次のDockerfileの問題点を3つ指摘してください。

FROM python:3.9 COPY . /app WORKDIR /app RUN apt-get update RUN apt-get install -y gcc RUN pip install -r requirements.txt CMD [“python”, “app.py”]
【解答】
  1. ベースイメージが大きい:python:3.9ではなくpython:3.9-slimを使うべき
  2. コピーの順序が悪い:全ファイルを先にコピーしているため、キャッシュが効きにくい。requirements.txtだけ先にコピーすべき
  3. RUNが分割されている:複数のRUN命令を1つにまとめて、不要なレイヤーを削減すべき

改善例:

FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN apt-get update && \ apt-get install -y gcc && \ pip install –no-cache-dir -r requirements.txt && \ apt-get purge -y gcc && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* COPY . . CMD [“python”, “app.py”]
練習問題 2 基礎

.dockerignoreファイルに記述すべき項目を5つ挙げてください。

【解答例】
  1. .git:Gitの履歴ファイル(不要)
  2. __pycache__:Pythonのキャッシュファイル
  3. *.log:ログファイル
  4. .env:環境変数ファイル(秘密情報を含む)
  5. tests/:テストファイル(本番では不要)

他にも、.vscode/*.mddata/node_modules/venv/なども正解です。

練習問題 3 応用

次のDockerfileを最適化してください。イメージサイズとビルド時間の両方を考慮してください。

FROM python:3.9 COPY . /app WORKDIR /app RUN apt-get update RUN apt-get install -y gcc make RUN pip install numpy pandas RUN pip install -r requirements.txt RUN apt-get install -y curl wget CMD [“python”, “app.py”]
【最適化版】
FROM python:3.9-slim WORKDIR /app # requirements.txtだけ先にコピー COPY requirements.txt . # 必要なパッケージをまとめてインストール&削除 RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ make \ curl \ wget && \ # Pythonパッケージをインストール pip install –no-cache-dir numpy pandas && \ pip install –no-cache-dir -r requirements.txt && \ # ビルドツールを削除 apt-get purge -y gcc make && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* # アプリケーションコードは最後 COPY app.py . COPY utils.py . CMD [“python”, “app.py”]

最適化のポイント:

  • python:3.9-slimで軽量化
  • requirements.txtを先にコピーしてキャッシュ活用
  • すべてのインストールを1つのRUNにまとめる
  • ビルドツール(gcc, make)は使用後に削除
  • --no-cache-dirでpipキャッシュを残さない
  • 不要なaptキャッシュを削除
練習問題 4 応用

次の状況で、ビルド時間を最短にするには、Dockerfileをどう書けばよいでしょうか?

状況:
• app.pyは毎日変更される
• config.pyは週に1回変更される
• requirements.txtは月に1回変更される

【解答】

変更頻度が低いものを上に、高いものを下に配置します。

FROM python:3.9-slim WORKDIR /app # ① 月に1回変更:requirements.txt COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt # ② 週に1回変更:config.py COPY config.py . # ③ 毎日変更:app.py COPY app.py . CMD [“python”, “app.py”]

効果:

  • app.pyだけ変更した場合:①②はキャッシュ → 超高速
  • config.pyを変更した場合:①はキャッシュ → 高速
  • requirements.txtを変更した場合:全部再ビルド → 仕方ない
練習問題 5 発展

次のDockerfileで、イメージサイズが減らない理由を説明してください。

FROM python:3.9-slim WORKDIR /app # 大きなファイルをダウンロード RUN curl -o bigfile.tar.gz https://example.com/bigfile.tar.gz # 展開 RUN tar -xzf bigfile.tar.gz # 元のファイルを削除 RUN rm bigfile.tar.gz CMD [“python”, “app.py”]
【理由】

Dockerのレイヤーは追加のみで、削除は「見えなくなる」だけです。
別のRUN命令で削除しても、bigfile.tar.gzは2番目のレイヤーに残っているため、イメージサイズは減りません。

正しい方法:

FROM python:3.9-slim WORKDIR /app # ダウンロード→展開→削除を1つのRUNで RUN curl -o bigfile.tar.gz https://example.com/bigfile.tar.gz && \ tar -xzf bigfile.tar.gz && \ rm bigfile.tar.gz CMD [“python”, “app.py”]

この方法なら、最終的なレイヤーには展開後のファイルだけが含まれ、bigfile.tar.gzは残りません。

練習問題 6 応用

イメージサイズを確認するコマンドと、レイヤーごとのサイズを確認するコマンドをそれぞれ書いてください。

【解答】

1. イメージサイズの確認:

docker images # または特定のイメージのみ docker images myapp # サイズでソート docker images –format “table {{.Repository}}\t{{.Tag}}\t{{.Size}}” | sort -k3 -h

2. レイヤーごとのサイズ確認:

docker history myapp:latest # 省略なしで表示 docker history myapp:latest –no-trunc

3. 詳細情報:

docker image inspect myapp:latest
練習問題 7 発展

データサイエンス用のDockerfileを最適化してください。numpy、pandas、scikit-learnを含め、できるだけ小さくしてください。

【最適化版】
FROM python:3.9-slim WORKDIR /app # requirements.txtの内容 # numpy==1.21.0 # pandas==1.3.0 # scikit-learn==0.24.2 COPY requirements.txt . # ビルドに必要なパッケージをインストール→使用→削除 RUN apt-get update && \ apt-get install -y –no-install-recommends \ gcc \ g++ \ gfortran \ libopenblas-dev \ liblapack-dev && \ # Pythonパッケージをインストール pip install –no-cache-dir -r requirements.txt && \ # ビルドツールを削除 apt-get purge -y \ gcc \ g++ \ gfortran && \ apt-get autoremove -y && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ # Pythonキャッシュも削除 find /usr/local/lib/python3.9 -type d -name __pycache__ -exec rm -r {} + 2>/dev/null || true # アプリケーションコード COPY app.py . CMD [“python”, “app.py”]

ポイント:

  • slimベースで軽量化
  • ビルドツール(gcc, g++など)は使用後に削除
  • 実行時に必要なlibopenblasなどは残す
  • __pycache__も削除
  • すべて1つのRUNで実行

サイズ比較:

  • 最適化前:約1.5GB
  • 最適化後:約600MB(60%削減)
練習問題 8 発展

次の要件を満たすDockerfileを作成してください。

  • ベースイメージ:python:3.9-slim
  • 必要なパッケージ:Flask、requests
  • アプリケーションファイル:app.py、config.py、templates/ディレクトリ
  • ポート5000を公開
  • イメージサイズとビルド時間を最適化すること
【最適化版Dockerfile】
FROM python:3.9-slim WORKDIR /app # ポートを公開 EXPOSE 5000 # 環境変数の設定 ENV FLASK_APP=app.py ENV FLASK_ENV=production # requirements.txtを先にコピー COPY requirements.txt . # 依存関係をインストール RUN pip install –no-cache-dir -r requirements.txt # 設定ファイル(変更頻度:低) COPY config.py . # テンプレートディレクトリ(変更頻度:中) COPY templates/ templates/ # アプリケーションコード(変更頻度:高) COPY app.py . # 非rootユーザーで実行(セキュリティ向上) RUN useradd -m appuser && \ chown -R appuser:appuser /app USER appuser CMD [“flask”, “run”, “–host=0.0.0.0”]

requirements.txt:

Flask==2.0.1 requests==2.26.0

.dockerignore:

__pycache__ *.pyc .git .vscode *.log .env tests/ *.md

最適化のポイント:

  • 変更頻度順にファイルをコピー(キャッシュ活用)
  • --no-cache-dirでpipキャッシュを残さない
  • .dockerignoreで不要ファイルを除外
  • 非rootユーザーで実行(セキュリティ向上)
  • 環境変数を明示的に設定

📝 STEP 13 のまとめ

✅ このステップで学んだこと
  • レイヤーキャッシュ:変更がない命令はキャッシュを再利用してビルドを高速化
  • .dockerignore:不要なファイルを除外してサイズとビルド時間を削減
  • 命令の順序:変更頻度が低いものを上に配置してキャッシュを最大活用
  • イメージサイズ削減:軽量ベースイメージ、RUNのまとめ、不要ファイル削除
  • 削除のタイミング:同じRUN内で削除しないとサイズは減らない
📊 最適化テクニック一覧
テクニック 効果 実装方法
軽量ベースイメージ サイズ80%削減 python:3.9-slimを使用
命令の順序最適化 再ビルド97%高速化 変更頻度が低いものを先に
.dockerignore ビルド時間短縮 不要ファイルを除外
RUNをまとめる レイヤー数削減 &&で連結
キャッシュ削除 サイズ削減 --no-cache-dirrm -rf
💡 重要ポイント
  • 最適化により、イメージサイズを50〜80%削減できる
  • ビルド時間を数分から数秒に短縮できる
  • 小さいイメージは、デプロイが速く、セキュリティも向上する
  • 最適化は開発初期から意識することが大切
🎯 次のステップの予告

次のSTEP 14では、「マルチステージビルド」を学びます。

  • ビルド用と実行用のイメージを分離
  • さらに小さいイメージを作成
  • セキュリティの向上
  • 実践例:Pythonアプリの最適化

究極に小さく、セキュアなイメージを作りましょう!

📝

学習メモ

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

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