STEP 24:トラブルシューティングとベストプラクティス

🔧 STEP 24: トラブルシューティングとベストプラクティス

よくある問題の解決とプロダクション環境への準備

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

  • よくあるエラーと対処法
  • コンテナが起動しない問題の診断
  • ネットワーク接続の問題
  • ボリュームマウントの問題
  • セキュリティのベストプラクティス
  • リソース制限の設定
  • 次のステップ:Kubernetes入門

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

📚 これまでの学習の復習
  • Docker基礎:コンテナ、イメージ、ボリューム(STEP 1-10)
  • Dockerfile:イメージのビルド(STEP 11-14)
  • Docker Compose:マルチコンテナ管理(STEP 15-18)
  • データエンジニアリング:PostgreSQL、Airflow、Spark(STEP 19-22)
  • CI/CD:GitHub Actions(STEP 23)

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

mkdir -p ~/docker-practice/step24 cd ~/docker-practice/step24 pwd

0-2. トラブルシューティングのフロー

【問題解決の基本フロー】 ┌─────────────────────────────────────────────────────────────────────┐ │ 問題発生 │ └─────────────────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ 1️⃣ 状態確認 │ │ docker ps -a ← コンテナの状態 │ │ docker-compose ps ← Composeサービスの状態 │ └─────────────────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ 2️⃣ ログ確認 │ │ docker logs コンテナ名 ← エラーメッセージ │ │ docker-compose logs ← 全サービスのログ │ └─────────────────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ 3️⃣ 詳細調査 │ │ docker inspect コンテナ名 ← 設定の詳細 │ │ docker exec -it … bash ← コンテナ内部調査 │ └─────────────────────────────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ 4️⃣ 修正・再起動 │ │ 設定を修正 → docker-compose down → docker-compose up -d │ └─────────────────────────────────────────────────────────────────────┘

0-3. よくあるエラーの種類

カテゴリ症状主な原因
起動エラーコンテナが即座に停止CMD/ENTRYPOINT、依存関係、設定ミス
ポートエラーBind failedポート重複、権限不足
イメージエラーImage not foundイメージ名ミス、ビルド未実行
ネットワークエラー接続できないネットワーク設定、DNS、ファイアウォール
ボリュームエラーPermission denied権限、パス間違い、マウント設定
リソースエラーOOM Killedメモリ不足、リソース制限

0-4. 診断コマンド早見表

目的コマンド
コンテナ一覧docker ps -a
ログ確認docker logs コンテナ名
リアルタイムログdocker logs -f コンテナ名
詳細情報docker inspect コンテナ名
コンテナ内部docker exec -it コンテナ名 bash
リソース使用量docker stats
ネットワーク確認docker network ls
ボリューム確認docker volume ls
イベント確認docker events
システム情報docker system df

🔍 1. よくあるエラーと対処法

1-1. コンテナが起動直後に停止する

❌ 症状
# コンテナが表示されない $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS # -a で確認すると Exited している $ docker ps -a CONTAINER ID IMAGE STATUS abc123 myapp Exited (1) 2s ago
✅ 原因と解決策
【原因1】CMDがフォアグラウンドで実行されていない → バックグラウンドで終了するコマンド(例: service start) 【原因2】アプリケーションエラー → 依存ライブラリ不足、設定ファイルエラー 【原因3】環境変数の不足 → 必須の環境変数が設定されていない
# 解決手順 # 1. ログを確認 docker logs abc123 # 2. 直近100行を確認 docker logs –tail 100 abc123 # 3. 詳細情報を確認 docker inspect abc123 | grep -A 5 “State” # 4. デバッグモードで起動 docker run -it myapp /bin/bash # 5. 環境変数を確認して起動 docker run -it -e DEBUG=true myapp /bin/bash

1-2. ポートが使用中

❌ 症状
Error: Bind for 0.0.0.0:8080 failed: port is already allocated
✅ 解決策
# 使用中のプロセスを確認(Linux/Mac) sudo lsof -i :8080 # 使用中のプロセスを確認(Windows PowerShell) netstat -ano | findstr :8080 # 使用中のコンテナを確認 docker ps –filter “publish=8080” # 既存のコンテナを停止 docker stop $(docker ps -q –filter “publish=8080”) # または別のポートを使用 docker run -p 8081:80 myapp

1-3. イメージが見つからない

❌ 症状
Error: Unable to find image ‘myapp:latest’ locally
✅ 解決策
# イメージ一覧を確認 docker images | grep myapp # イメージ名のスペルを確認 docker images # ローカルでビルド docker build -t myapp:latest . # Docker Hubから取得 docker pull myapp:latest # タグを指定して確認 docker images myapp

1-4. ビルドが失敗する

❌ 症状
COPY failed: file not found in build context # または RUN pip install … returned a non-zero code: 1
✅ 解決策
# ビルドコンテキストの確認 ls -la # .dockerignore を確認(除外されていないか) cat .dockerignore # Dockerfileのパスを確認 cat Dockerfile | head -20 # キャッシュなしでビルド docker build –no-cache -t myapp . # 詳細ログでビルド docker build –progress=plain -t myapp .

🚫 2. コンテナが起動しない問題の診断

2-1. 診断手順

# ステップ1: コンテナの状態確認 docker ps -a # ステップ2: 終了コードを確認 docker inspect コンテナ名 –format='{{.State.ExitCode}}’ # 終了コードの意味 # 0: 正常終了 # 1: 一般エラー # 137: SIGKILL(メモリ不足など) # 139: SIGSEGV(セグメンテーション違反) # 143: SIGTERM(正常停止) # ステップ3: ログを確認 docker logs コンテナ名 docker logs –tail 50 コンテナ名 # 直近50行 # ステップ4: 詳細情報を確認 docker inspect コンテナ名 # ステップ5: Dockerデーモンのイベント docker events –since ’10m’

2-2. よくある原因チェックリスト

📋 起動しない場合のチェックリスト
CMD/ENTRYPOINTフォアグラウンドで実行しているか
依存サービスDBなど依存先は起動しているか
環境変数必須の環境変数は設定されているか
ポートポート番号が重複していないか
ボリュームマウント先のパスは正しいか
権限ファイルの読み書き権限はあるか
リソースメモリ/CPU制限に達していないか

2-3. デバッグ用コンテナ起動

# 方法1: シェルで起動(ENTRYPOINTを上書き) docker run -it –entrypoint /bin/bash myapp # 方法2: 別のコマンドで起動 docker run -it myapp /bin/sh # 方法3: 既存の停止コンテナのファイルを確認 docker cp コンテナ名:/app/config.yml ./ # 方法4: 環境変数を確認 docker run -it myapp env # 方法5: 実行中のコンテナに接続 docker exec -it コンテナ名 /bin/bash

🌐 3. ネットワーク接続の問題

3-1. コンテナ間通信ができない

【コンテナ間通信の仕組み】 ┌──────────────────────────────────────────────────────────────┐ │ Docker Network (bridge) │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ webapp │ ──DNS──→│ postgres │ │ │ │ (コンテナ名) │ │ (コンテナ名) │ │ │ └─────────────┘ └─────────────┘ │ │ │ │ │ │ webapp:5000 postgres:5432 │ │ │ └──────────────────────────────────────────────────────────────┘ ※ 同じネットワーク内ではコンテナ名で通信可能
# 疎通確認 docker exec webapp ping postgres # ネットワーク一覧 docker network ls # ネットワーク詳細確認 docker network inspect ネットワーク名 # コンテナが参加しているネットワーク確認 docker inspect コンテナ名 –format='{{.NetworkSettings.Networks}}’ # DNS確認 docker exec コンテナ名 cat /etc/resolv.conf docker exec コンテナ名 nslookup postgres # ポート確認 docker exec コンテナ名 netstat -tulpn

3-2. 外部ネットワークに接続できない

# インターネット接続確認 docker exec コンテナ名 ping 8.8.8.8 docker exec コンテナ名 curl -I https://google.com # DNS解決確認 docker exec コンテナ名 nslookup google.com # ホスト側のファイアウォール確認(Linux) sudo iptables -L -n sudo ufw status # Docker のネットワーク設定確認 docker network inspect bridge

3-3. ネットワークのリセット

# コンテナを全停止 docker-compose down # 未使用ネットワークを削除 docker network prune -f # カスタムネットワークを再作成 docker network create mynetwork # 再起動 docker-compose up -d

💾 4. ボリュームマウントの問題

4-1. ファイルが見つからない

# コンテナ内のファイル確認 docker exec コンテナ名 ls -la /app # マウント情報確認 docker inspect コンテナ名 –format='{{json .Mounts}}’ | jq # ボリューム一覧 docker volume ls # ボリュームの詳細(実際のパス) docker volume inspect ボリューム名 # ホスト側のパスを確認 ls -la $(docker volume inspect ボリューム名 –format='{{.Mountpoint}}’)

4-2. 権限の問題(Permission denied)

❌ 症状
PermissionError: [Errno 13] Permission denied: ‘/app/data/file.txt’
【権限問題の原因】 ホスト側 コンテナ内 ┌─────────────┐ ┌─────────────┐ │ UID: 1000 │ │ UID: 0 │ ← 異なるUID │ (ユーザー) │ ──────→ │ (root) │ │ ./data/ │ │ /app/data/ │ │ 権限: 755 │ │ 書き込み不可 │ └─────────────┘ └─────────────┘
✅ 解決策
# 方法1: ホスト側の権限を変更(非推奨) chmod -R 777 ./data # 方法2: Dockerfileでユーザーを作成 cat > Dockerfile << ‘EOF’ FROM python:3.9-slim RUN useradd -m -u 1000 appuser WORKDIR /app COPY –chown=appuser:appuser . . USER appuser CMD [“python”, “app.py”] EOF # 方法3: docker-compose.ymlでユーザー指定 # services: # webapp: # user: “1000:1000” # 方法4: 名前付きボリュームを使用(推奨) # volumes: # – mydata:/app/data

4-3. データが消える問題

⚠️ コンテナ削除時にデータが消える

バインドマウントや名前付きボリュームを使用しないと、コンテナ削除時にデータも消えます。

# 名前付きボリュームを使用(docker-compose.yml) services: postgres: image: postgres:15 volumes: – pgdata:/var/lib/postgresql/data # 名前付きボリューム volumes: pgdata: # ボリューム定義 # バックアップ方法 docker run –rm \ -v pgdata:/data \ -v $(pwd):/backup \ ubuntu tar czf /backup/pgdata-backup.tar.gz /data # リストア方法 docker run –rm \ -v pgdata:/data \ -v $(pwd):/backup \ ubuntu tar xzf /backup/pgdata-backup.tar.gz -C /

🔒 5. セキュリティのベストプラクティス

5-1. セキュリティチェックリスト

【Dockerセキュリティ チェックリスト】 ┌─────────────────────────────────────────────────────────────────────┐ │ カテゴリ │ 項目 │ 状態 │ ├─────────────────────────────────────────────────────────────────────┤ │ イメージ │ 公式イメージを使用 │ □ │ │ │ 軽量イメージ(alpine/slim) │ □ │ │ │ 脆弱性スキャン実施 │ □ │ │ │ イメージを定期更新 │ □ │ ├─────────────────────────────────────────────────────────────────────┤ │ ランタイム │ 非rootユーザーで実行 │ □ │ │ │ 読み取り専用ファイルシステム │ □ │ │ │ 不要なケーパビリティを削除 │ □ │ │ │ リソース制限を設定 │ □ │ ├─────────────────────────────────────────────────────────────────────┤ │ シークレット │ 環境変数で注入 │ □ │ │ │ .envファイルを.gitignore │ □ │ │ │ Docker Secretsを使用 │ □ │ ├─────────────────────────────────────────────────────────────────────┤ │ ネットワーク │ 内部ネットワークを分離 │ □ │ │ │ 不要なポートを公開しない │ □ │ └─────────────────────────────────────────────────────────────────────┘

5-2. 非rootユーザーで実行

# セキュアなDockerfile例 cat > Dockerfile.secure << ‘EOF’ FROM python:3.9-slim # アプリケーション用ユーザー作成 RUN useradd -m -u 1000 -s /bin/bash appuser WORKDIR /app # 依存関係インストール(rootで実行) COPY requirements.txt . RUN pip install –no-cache-dir -r requirements.txt # アプリケーションコードをコピー(所有者を変更) COPY –chown=appuser:appuser . . # 非rootユーザーに切り替え USER appuser # ヘルスチェック HEALTHCHECK –interval=30s –timeout=3s \ CMD curl -f http://localhost:5000/health || exit 1 CMD [“python”, “app.py”] EOF

5-3. イメージの脆弱性スキャン

# Trivyでスキャン docker run –rm \ -v /var/run/docker.sock:/var/run/docker.sock \ aquasec/trivy image myapp:latest # Docker Scoutでスキャン(Docker Desktop) docker scout cves myapp:latest # 重大な脆弱性のみ表示 docker run –rm \ -v /var/run/docker.sock:/var/run/docker.sock \ aquasec/trivy image –severity CRITICAL,HIGH myapp:latest

5-4. シークレット管理

# ❌ 悪い例:Dockerfileに直接書く ENV DATABASE_PASSWORD=mysecret # 絶対ダメ! # ❌ 悪い例:docker-compose.ymlに直接書く environment: – DATABASE_PASSWORD=mysecret # 絶対ダメ! # ✅ 良い例:.envファイルで管理 # .env(.gitignoreに追加) DATABASE_PASSWORD=mysecret # docker-compose.yml services: webapp: env_file: – .env # ✅ 良い例:実行時に注入 docker run -e DATABASE_PASSWORD=$DB_PASSWORD myapp

5-5. 最小権限の原則

# docker-compose.yml でセキュリティ強化 services: webapp: image: myapp:latest # すべてのケーパビリティを削除 cap_drop: – ALL # 必要なものだけ追加 cap_add: – NET_BIND_SERVICE # ファイルシステムを読み取り専用 read_only: true # 一時ファイル用のtmpfs tmpfs: – /tmp # セキュリティオプション security_opt: – no-new-privileges:true

⚙️ 6. リソース制限の設定

6-1. リソース制限の図解

【リソース制限の概念】 ホストマシン(メモリ: 16GB、CPU: 8コア) ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Container A │ │ Container B │ │ Container C │ │ │ │ │ │ │ │ │ │ │ │ Memory: 512MB │ │ Memory: 1GB │ │ Memory: 2GB │ │ │ │ CPU: 0.5 │ │ CPU: 1.0 │ │ CPU: 2.0 │ │ │ │ (limit) │ │ (limit) │ │ (limit) │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ │ 制限を超えると → OOM Killed(メモリ)/ スロットリング(CPU) │ └─────────────────────────────────────────────────────────────────────┘

6-2. メモリ制限

# docker run での制限 docker run -m 512m myapp # 512MB制限 docker run –memory=1g myapp # 1GB制限 docker run –memory-reservation=256m myapp # ソフト制限 # docker-compose.yml での制限 services: webapp: image: myapp:latest deploy: resources: limits: memory: 512M # ハード制限 reservations: memory: 256M # 最小確保量

6-3. CPU制限

# docker run での制限 docker run –cpus=”1.5″ myapp # 1.5コア相当 docker run –cpu-shares=512 myapp # 相対的な優先度 # docker-compose.yml での制限 services: webapp: image: myapp:latest deploy: resources: limits: cpus: ‘1.5’ # 1.5コア制限 reservations: cpus: ‘0.5’ # 最小確保量

6-4. リソース使用状況の監視

# リアルタイム監視 docker stats # 出力例: # CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % # abc123 webapp 0.50% 128MiB / 512MiB 25.00% # def456 postgres 1.20% 256MiB / 1GiB 25.00% # 特定のコンテナのみ docker stats webapp postgres # 一回だけ取得 docker stats –no-stream # フォーマット指定 docker stats –format “table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}”

6-5. 推奨リソース設定例

サービスメモリ制限CPU制限備考
PostgreSQL1-2GB1-2shared_buffersに応じて
Redis256MB-1GB0.5-1キャッシュサイズに応じて
Airflow Webserver512MB-1GB0.5-1同時接続数に応じて
Airflow Scheduler1-2GB1-2DAG数に応じて
Spark Worker2-8GB2-4処理データ量に応じて
Python ETL512MB-2GB0.5-1データサイズに応じて

📚 7. ベストプラクティスまとめ

📄 Dockerfile
  • 軽量ベースイメージ(alpine、slim)
  • マルチステージビルド
  • .dockerignoreで不要ファイル除外
  • レイヤーキャッシュを活用
  • 非rootユーザーで実行
  • HEALTHCHECKを設定
📋 docker-compose.yml
  • .envファイルで環境変数管理
  • 名前付きボリュームでデータ永続化
  • depends_on + healthcheckで依存関係
  • restart: unless-stoppedで自動再起動
  • リソース制限を設定
  • ネットワークを分離
🔒 セキュリティ
  • 公式イメージを使用
  • 定期的な脆弱性スキャン
  • シークレットを環境変数で注入
  • 最小権限の原則
  • ネットワークを分離
  • 読み取り専用ファイルシステム
🔧 運用
  • 定期的なイメージ更新
  • ログの集約と監視
  • バックアップの自動化
  • CI/CDパイプラインの構築
  • リソース使用量の監視
  • 不要なリソースの定期削除

🚀 8. 次のステップ:Kubernetes入門

8-1. Kubernetesとは

Kubernetes(K8s)は、コンテナのオーケストレーションプラットフォームです。 複数のホストにまたがるコンテナを効率的に管理できます。

【Docker Compose と Kubernetes の比較】 Docker Compose(単一ホスト) ┌─────────────────────────────────────────────────────────────────────┐ │ 1台のサーバー │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Container│ │ Container│ │ Container│ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────────────┘ Kubernetes(クラスター) ┌─────────────────────────────────────────────────────────────────────┐ │ 複数のサーバー(ノード) │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ │ │ Pod │ │ │ │ Pod │ │ │ │ Pod │ │ │ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ │ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ │ │ Pod │ │ │ │ Pod │ │ │ │ Pod │ │ │ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ※ 自動スケーリング、自動復旧、ローリングアップデートが可能

8-2. Docker Compose vs Kubernetes

項目Docker ComposeKubernetes
対象単一ホスト複数ホスト(クラスター)
スケール小〜中規模大規模
自動復旧restart: always自動(高機能)
スケーリング手動自動(HPA)
学習コスト
設定ファイルdocker-compose.yml複数のYAMLマニフェスト
用途開発環境、小規模本番大規模本番環境

8-3. Kubernetesを学ぶべきタイミング

🎯 こんな時にKubernetesを検討
  • データパイプラインを複数サーバーで運用したい
  • Sparkクラスターを動的にスケールしたい
  • AirflowのWorkerを自動スケールしたい
  • 高可用性が必要な本番環境
  • 複数チームで共有基盤を運用したい

8-4. 学習リソース

📚 Kubernetesを学ぶには
  • 公式チュートリアル:kubernetes.io/ja/docs/tutorials/
  • Minikube:ローカルでKubernetesを試せる
  • Docker Desktop:Kubernetes機能が統合
  • kind:Docker内でKubernetesクラスターを起動

💪 9. 練習問題

練習問題 1 基礎

コンテナが起動直後に停止した場合、最初に確認すべきコマンドは何ですか?

docker logs コンテナ名

ログを確認することで、エラーメッセージや終了原因がわかります。

練習問題 2 基礎

ポート8080が既に使用中の場合の対処法を2つ挙げてください。

  1. 使用中のプロセス/コンテナを停止
    docker stop $(docker ps -q –filter “publish=8080”)
  2. 別のポートを使用
    docker run -p 8081:80 myapp
練習問題 3 基礎

コンテナのリソース使用量をリアルタイムで監視するコマンドは何ですか?

docker stats

CPU使用率、メモリ使用量、ネットワークI/Oなどをリアルタイムで確認できます。

練習問題 4 応用

Dockerfileで非rootユーザーを作成して実行する設定を書いてください。

FROM python:3.9-slim # ユーザー作成 RUN useradd -m -u 1000 appuser WORKDIR /app COPY –chown=appuser:appuser . . # 非rootユーザーに切り替え USER appuser CMD [“python”, “app.py”]
練習問題 5 応用

docker-compose.ymlでメモリ512MB、CPU1コアに制限する設定を書いてください。

services: webapp: image: myapp:latest deploy: resources: limits: memory: 512M cpus: ‘1.0’ reservations: memory: 256M cpus: ‘0.5’
練習問題 6 応用

コンテナの終了コード137は何を意味しますか?

137 = 128 + 9(SIGKILL)

通常、OOM Killer(Out Of Memory Killer)によってメモリ不足でプロセスが強制終了されたことを意味します。

対策:メモリ制限を増やす、またはアプリケーションのメモリ使用量を削減する。

練習問題 7 発展

セキュリティを強化したdocker-compose.ymlの設定(cap_drop、read_only、security_opt)を書いてください。

services: webapp: image: myapp:latest # すべてのケーパビリティを削除 cap_drop: – ALL # 必要なものだけ追加 cap_add: – NET_BIND_SERVICE # ファイルシステムを読み取り専用 read_only: true # 一時ファイル用 tmpfs: – /tmp # 特権昇格を禁止 security_opt: – no-new-privileges:true
練習問題 8 発展

Docker ComposeとKubernetesの主な違いを3つ挙げてください。

  1. 対象規模:Docker Composeは単一ホスト、Kubernetesは複数ホストのクラスター
  2. スケーリング:Docker Composeは手動、Kubernetesは自動スケーリング(HPA)対応
  3. 自動復旧:Docker Composeはrestart policyのみ、Kubernetesは高度な自動復旧機能

📝 STEP 24 のまとめ

✅ このステップで学んだこと
  • トラブルシューティング:ログ確認、デバッグ方法
  • ネットワーク問題:コンテナ間通信、DNS、ファイアウォール
  • ボリューム問題:権限、パス、データ永続化
  • セキュリティ:非root実行、脆弱性スキャン、シークレット管理
  • リソース制限:メモリ、CPU制限と監視
  • Kubernetes:次のステップとして学ぶべきタイミング
🎉 Part 5 完了!

Part 5では、データエンジニアリングに特化した実践的なDockerスキルを習得しました。

  • PostgreSQL + Airflowのコンテナ化
  • Sparkクラスターの構築
  • 環境変数とシークレット管理
  • データパイプラインの統合
  • CI/CD統合(GitHub Actions)
  • トラブルシューティングとベストプラクティス
🎯 次のステップの予告

Part 6(STEP 25〜27)では、これまで学んだ知識を統合して実践的なプロジェクトを構築します!

  • STEP 25: ローカルデータ基盤構築
  • STEP 26: ETLパイプラインのコンテナ化
  • STEP 27: 本番環境デプロイシミュレーション
📝

学習メモ

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

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