Skip to content

Docker ビルド トラブルシューティングガイド

EvoSpikeNet-Core の Docker ビルドで遭遇する一般的な問題と対応方法をまとめました。

目次

  1. ビルドの失敗
  2. イメージのサイズ問題
  3. 実行時エラー
  4. パフォーマンス問題
  5. セキュリティ関連
  6. レジストリの問題
  7. マルチプラットフォーム対応
  8. 快速検査ツール

ビルドの失敗

エラー: "Dockerfile: stage not found: runtime-wheel"

原因: Dockerfile が更新されていない、または Dockerfile に指定ターゲットがない

解決方法:

# Dockerfile で定義されているターゲットを確認
grep "^FROM.*AS runtime" Dockerfile

# 出力例:
# FROM runtime-base AS runtime-source
# FROM runtime-base AS runtime-wheel
# FROM runtime-base AS runtime-cython
# FROM runtime-base AS runtime-nuitka

# 4 つのターゲットすべてが定義されているか確認
docker build --target runtime -f Dockerfile . 2>&1 | head -20

修正例:

# Dockerfile が古い場合は最新版に更新
git pull
git checkout -- Dockerfile

# ビルド再試行
docker build --build-arg APP_IMAGE_MODE=wheel --target runtime-wheel .

エラー: "Cython compilation failed"

原因: 1. Cython がインストールされていない 2. C コンパイラがない 3. Python 開発ファイルがない

解決方法:

# Dockerfile のビルダーステージで Cython がインストールされているか確認
grep -A 5 "FROM python.*AS builder" Dockerfile | grep -i cython

# ローカルで問題を再現
docker build \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  --progress=plain \
  .

Dockerfile で必要な修正:

# ビルダーステージで Cython を明示的にインストール
RUN pip install --no-cache-dir cython>=3.0 patchelf setuptools wheel

# コンパイラのインストール(Debian/Ubuntu)
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    python3-dev \
    && rm -rf /var/lib/apt/lists/*

エラー: "Nuitka build failed: memory exhausted"

原因: Nuitka コンパイルにメモリ不足

解決方法:

# Docker デーモンのメモリ制限を確認
docker info | grep -i memory

# 制限を増やす場合は Docker 設定を編集
# ~/.docker/daemon.json
{
  "memory": "8g",
  "memory-swap": "8g"
}

# Docker デーモン再起動
systemctl restart docker

# 再ビルド試行
docker build \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  --memory=4g \
  .

代替案:

# メモリが限定的な場合は Cython モードで代用
docker build \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  -t evospikenet:cython \
  .

エラー: "No space left on device"

原因: ディスク容量が不足(Docker イメージレイヤーキャッシュがいっぱい)

解決方法:

# ディスク使用量確認
df -h /var/lib/docker/

# Docker ビルドキャッシュをクリア
docker builder prune -a

# または more aggressive に
docker image prune -a
docker volume prune
docker system prune -a

# 確認
df -h /var/lib/docker/

# ビルド再試行
docker build --no-cache -t evospikenet:fresh .

エラー: "ERROR: could not find a package with a matching specification"

原因: pip で指定されたパッケージが見つからない(依存バージョンの不一致)

解決方法:

# ビルドログで問題のあるパッケージを確認
docker build . 2>&1 | grep -i "not found\|error" | head -20

# pyproject.toml または requirements.txt で依存バージョン確認
cat pyproject.toml | grep -A 20 "dependencies ="

# 特定のパッケージバージョン修正例
# pyproject.toml で pin されたバージョンを柔軟に

# Before:
# torch==2.1.0

# After:
# torch>=2.0.0,<3.0

イメージのサイズ問題

問題: イメージサイズが異常に大きい

目安: - source: ~500MB(正常) - wheel: ~350MB(正常) - cython: ~400MB(正常) - nuitka: ~600MB(正常)

診断:

# イメージ全体のサイズ確認
docker images | grep evospikenet

# イメージの詳細分析
docker run --rm evospikenet:nuitka df -h /

# レイヤーごとのサイズ確認
docker history evospikenet:nuitka

# 不要なレイヤーを特定
docker run --rm evospikenet:nuitka du -sh /* 2>/dev/null | sort -h

解決方法:

# マルチステージビルドで中間ファイルを削除
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y build-essential \
    && apt-get clean && rm -rf /var/lib/apt/lists/*  #  ここが重要

FROM ubuntu:22.04 AS runtime
COPY --from=builder /opt /opt

キャッシュクリア:

# 特定イメージの中間ファイルを削除
docker image prune -a

# または Dockerfile で明示的にクリア
docker build --no-cache -t evospikenet:lean .

問題: イメージ内に不要なファイルがある

診断:

# イメージ内のファイル構成を確認
docker run --rm evospikenet:wheel find /opt/venv -type f -name "*.pyc" | wc -l
docker run --rm evospikenet:wheel find /opt/venv -type f -name "*.egg-info" -o -name "__pycache__" | wc -l

解決方法:

# Dockerfile でクリーンアップ
RUN pip install --no-cache-dir ... && \
    find /opt/venv -type d -name __pycache__ -exec rm -rf {} + ; \
    find /opt/venv -type d -name "*.egg-info" -exec rm -rf {} +

実行時エラー

エラー: "ImportError: cannot import name 'api'"

原因: Cython/Nuitka モードでモジュールが正しくコンパイルされていない

診断:

# イメージ内のモジュールを確認
docker run --rm evospikenet:cython python -c \
  "import sys; print(sys.path); import evospikenet.api"

# .so ファイルが生成されているか確認
docker run --rm evospikenet:cython find /opt/venv -name "api*.so"

# 詳細なエラーを取得
docker run --rm evospikenet:cython python -v -c \
  "import evospikenet.api" 2>&1 | tail -50

解決方法:

# スクリプトの実行ログを確認
docker build \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  --progress=plain \
  . 2>&1 | grep -A 10 "protect_with_cython.py"

scripts/protect_with_cython.py の確認:

# スクリプト内で対象モジュールが正しく指定されているか確認
TARGET_MODULES = [
    "evospikenet.api",           # ← これらが実際に存在するか確認
    "evospikenet.models",
    # ...
]

エラー: "Segmentation fault" (Nuitka)

原因: Nuitka バイナリがビルドシステムと異なる Linux で動作している

診断:

# ベースイメージを確認
docker inspect evospikenet:nuitka | grep -i "FROM\|baseimage"

# バイナリの依存ライブラリ確認
docker run --rm evospikenet:nuitka ldd /tmp/nuitka-dist/evospikenet-api

解決方法:

# ビルド環境と同じベースイメージを指定
docker build \
  --build-arg BASE_IMAGE=ubuntu:22.04 \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  .

# 異なる環境で実行する場合は再ビルドが必須
# 例: Ubuntu 20.04 で実行する場合
docker build \
  --build-arg BASE_IMAGE=ubuntu:20.04 \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  .

エラー: "Connection refused" (API)

原因: コンテナ内の API サーバーが起動していない、またはポートが公開されていない

診断:

# コンテナ内で API が起動しているか確認
docker run --rm -p 18000:8000 evospikenet:source &
sleep 5
curl -v http://localhost:18000/health

解決方法:

# ポート公開を確認
docker run --rm -p 18000:8000 evospikenet:source

# API ログを確認
docker run --rm -e LOG_LEVEL=DEBUG evospikenet:source 2>&1 | tail -50

# docker-compose で確認
docker compose up -d api
docker compose logs api | tail -100

パフォーマンス問題

問題: ビルドが非常に遅い

原因: 1. Nuitka コンパイルは本質的に遅い(40~50 分) 2. Docker レイヤーキャッシュが効いていない 3. ディスク I/O が遅い

診断:

# 各ステップの実行時間を確認
docker build --progress=plain --target runtime-nuitka . 2>&1 | \
  grep -E "^#[0-9]+ \[.*\] (DONE|RUN)" | head -20

解決方法:

# 1. キャッシュを活用
docker build --cache-from evospikenet:previous -t evospikenet:current .

# 2. 不要なステップをスキップ(開発中)
docker build \
  --build-arg APP_IMAGE_MODE=wheel \
  --target runtime-wheel \
  -t evospikenet:dev .

# 3. Linux の場合、TMPFS を使用
mkdir -p /mnt/tmpfs
sudo mount -t tmpfs -o size=10G tmpfs /mnt/tmpfs
# Docker を /mnt/tmpfs に移動(オプション)

問題: 実行時に遅い(起動時間が長い)

計測:

# 起動時間を計測
time docker run --rm evospikenet:source bash -c "python -c 'import evospikenet.api'"

# 実行結果例:
# source:  0.5 秒
# wheel:   0.5 秒
# cython:  0.5 秒
# nuitka:  3-5 秒 (バイナリ起動のオーバーヘッド)

nuitka の起動時間を削減:

# バイナリをキャッシュ(コンテナ内)
docker run --rm -v nuitka-cache:/tmp/nuitka-dist evospikenet:nuitka

# 次回起動時にキャッシュを使用
docker run --rm -v nuitka-cache:/tmp/nuitka-dist evospikenet:nuitka

セキュリティ関連

問題: ソースコードが露出している(source モード)

これは仕様です。source モードは開発用です。

本番環境では:

# Cython または Nuitka モードを使用
docker build \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  -t evospikenet:prod .

問題: Cython .so ファイルが逆コンパイルされた

現実的なセキュリティ評価:

  • .so ファイルは Python ソースよりも逆コンパイルが困難
  • 完全なセキュリティではなく難読化レベル
  • 最高レベルのセキュリティは Nuitka(スタンドアロンバイナリ)

追加保護:

# 1. コンテナを読み取り専用に設定
docker run --read-only -v /tmp evospikenet:cython

# 2. ファイルシステムを暗号化
# 本番環境での全ディスク暗号化を推奨

# 3. イメージに署名を検証
cosign verify --key cosign.pub $REGISTRY/$IMAGE:$VERSION

問題: API キーが漏洩している

原因: 環境変数やファイルが Docker イメージに埋め込まれている

診断:

# イメージに API キーが含まれていないか確認
docker run --rm evospikenet:prod env | grep -i key

# Dockerfile で確認
grep -n "ARG.*KEY\|ENV.*KEY" Dockerfile

解決方法:

# ❌ 危険: ビルド時に指定
ARG API_KEY=secret123
RUN export API_KEY=$API_KEY

# ✅ 正しい: 実行時に指定
# Dockerfile では指定しない
# 実行時:
docker run -e API_KEY=secret123 evospikenet:prod

レジストリの問題

エラー: "denied: authorization failed"

原因: レジストリ認証情報が間違っている、または権限がない

解決方法:

# ログイン状態を確認
docker info | grep -i registry

# 再ログイン
docker login $REGISTRY
# ユーザー名とパスワード(またはトークン)を入力

# プッシュ再試行
docker push $REGISTRY/$IMAGE:$TAG

GitHub Container Registry (GHCR):

# Personal Access Token を生成
# GitHub → Settings → Developer settings → Personal access tokens → Generate new token
# スコープ: write:packages, read:packages, delete:packages

# ログイン
echo $GITHUB_TOKEN | docker login ghcr.io -u $GITHUB_USERNAME --password-stdin

# プッシュ
docker push ghcr.io/$GITHUB_USERNAME/evospikenet:latest

エラー: "blob upload unknown"

原因: ネットワーク接続問題、レジストリのディスク容量不足

解決方法:

# ネットワーク接続確認
ping -c 5 $REGISTRY

# ローカルレジストリの場合、ディスク容量確認
docker exec registry df -h /var/lib/registry

# 再試行
docker push $REGISTRY/$IMAGE:$TAG --verbose

マルチプラットフォーム対応

問題: Linux ARM64 でビルドしたが AMD64 では動作しない

原因: プラットフォーム固有のバイナリ(Nuitka など)が混在している

診断:

# イメージのプラットフォーム確認
docker inspect evospikenet:nuitka | grep -i architecture

# ビルド対象プラットフォーム指定
docker build --platform linux/amd64 .

解決方法:

# マルチプラットフォーム対応ビルド
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  -t $REGISTRY/evospikenet:cython \
  --push \
  .

快速検査ツール

ビルド全モード検証スクリプト

scripts/validate-all-modes.sh:

#!/bin/bash
set -e

echo "🔍 Validating all Docker build modes..."
echo ""

MODES=(source wheel cython nuitka)
TARGETS=(runtime runtime-wheel runtime-cython runtime-nuitka)
RESULTS=()

for i in "${!MODES[@]}"; do
  mode=${MODES[$i]}
  target=${TARGETS[$i]}

  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  echo "📦 Building mode: $mode (target: $target)"
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

  start_time=$(date +%s)

  if docker build \
    --build-arg APP_IMAGE_MODE=$mode \
    --target $target \
    -t evospikenet:validate-$mode \
    ./EvoSpikeNet-Core > /tmp/build-$mode.log 2>&1; then

    end_time=$(date +%s)
    duration=$((end_time - start_time))

    echo "✅ Build succeeded (${duration}s)"

    # テスト実行
    if [[ "$mode" == "nuitka" ]]; then
      if docker run --rm evospikenet:validate-$mode \
        test -x /tmp/nuitka-dist/evospikenet-api; then
        echo "✅ Binary validation passed"
        RESULTS+=("$mode: ✅")
      else
        echo "❌ Binary not found or not executable"
        RESULTS+=("$mode: ❌")
      fi
    else
      if docker run --rm evospikenet:validate-$mode python -c \
        "import evospikenet.api; print('✓ Import OK')"; then
        echo "✅ Module import validation passed"
        RESULTS+=("$mode: ✅")
      else
        echo "❌ Module import failed"
        RESULTS+=("$mode: ❌")
      fi
    fi
  else
    echo "❌ Build failed"
    tail -20 /tmp/build-$mode.log
    RESULTS+=("$mode: ❌")
  fi

  echo ""
done

echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📊 Summary:"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
for result in "${RESULTS[@]}"; do
  echo "$result"
done

実行:

chmod +x scripts/validate-all-modes.sh
./scripts/validate-all-modes.sh

診断ツール

scripts/diagnose-docker.sh:

#!/bin/bash

echo "🔧 Docker Build Diagnosis"
echo ""

echo "1️⃣  Docker 環境"
docker --version
docker compose version
docker info | grep -E "Storage Driver|Runtimes"
echo ""

echo "2️⃣  ディスク容量"
df -h /var/lib/docker/
echo ""

echo "3️⃣  イメージキャッシュサイズ"
du -sh /var/lib/docker/image/
echo ""

echo "4️⃣  Dockerfile 確認"
echo "Targets found:"
grep "^FROM.*AS runtime" Dockerfile
echo ""

echo "5️⃣  ビルドスクリプト確認"
echo "Cython script:"
test -f scripts/protect_with_cython.py && echo "✓ Found" || echo "✗ Missing"
echo "Nuitka script:"
test -f scripts/build_nuitka_api_binary.py && echo "✓ Found" || echo "✗ Missing"
echo ""

echo "✅ Diagnosis complete"

実行:

chmod +x scripts/diagnose-docker.sh
./scripts/diagnose-docker.sh

関連リソース