コンテンツにスキップ

Docker ビルドモード完全ガイド

[!NOTE] このガイドは EvoSpikeNet-Core の Python ソースコード非公開パブリッシング機能について説明しています。

概要

EvoSpikeNet-Core は Docker イメージをビルドする際に、4つの異なるモードをサポートしています。 既存の開発フロー(完全なソースツリーを含む)を維持しながら、リリース時にはソース露出を段階的に削減できます。

モード 用途 ソース公開 ビルド時間 実行時サイズ セキュリティ
source ローカル開発・テスト ✅ すべて 短い 大きい なし
wheel ステージング環境 ❌ なし 中程度 中程度 基本的
cython プリプロダクション ❌ .so 化 長い 中程度 中程度
nuitka 本番デプロイ ❌ バイナリ化 最長 大きい 高い

1. source モード(デフォルト)

完全なプロジェクトソースツリーを含むイメージです。既存のすべての開発ワークフロー・テストと互換性があります。

用途

  • ✅ ローカル開発・デバッグ
  • ✅ CI/CD テストパイプライン
  • ✅ 内部開発環境
  • ✅ 後方互換性が必須な環境

セキュリティ特性

  • リスク: Python ソースコードがコンテナ内で完全に公開される
  • 対策: なし(意図的に、開発効率を優先)
  • 推奨環境: 内部ネットワークのみ

ビルドコマンド

# 暗黙的(デフォルト)
docker build -t evospikenet:source .

# 明示的
docker build -t evospikenet:source \
  --build-arg APP_IMAGE_MODE=source \
  --target runtime \
  .

実行例

# API サーバー起動
docker run --rm -p 18000:8000 evospikenet:source

# 対話型シェル
docker run --rm -it evospikenet:source bash

# ボリュームマウントでホットリロード
docker run --rm -p 18000:8000 \
  -v $PWD/evospikenet:/opt/venv/lib/python3.10/site-packages/evospikenet \
  evospikenet:source

ビルド検証

# イメージサイズ確認
docker images | grep evospikenet:source

# ソースコード確認(確認用)
docker run --rm evospikenet:source ls -la /app/evospikenet/api.py

推奨される docker-compose.yml 使用方法

version: '3.8'
services:
  api:
    image: evospikenet:source
    ports:
      - "18000:8000"
    volumes:
      - ./logs:/opt/venv/var/logs
    environment:
      - LOG_LEVEL=DEBUG

2. wheel モード

Wheel(.whl)形式で Python パッケージをビルドし、プロジェクトソースツリーをコンテナにコピーしないモードです。

用途

  • ✅ ステージング環境への配布
  • ✅ 内部レジストリでの配布
  • ✅ ライセンス配布要件がある場合
  • ✅ 基本的なソース保護が必要な場合

セキュリティ特性

  • リスク: Python バイトコード(.pyc)からのデコンパイルが可能
  • 対策: プロジェクトソースツリーは除外される
  • 保護レベル: 低~中程度(逆コンパイル対策なし)

ビルドコマンド

docker build -t evospikenet:wheel \
  --build-arg APP_IMAGE_MODE=wheel \
  --target runtime-wheel \
  .

ビルド過程の詳細

  1. builder ステージで wheel を生成: pip wheel --wheel-dir /tmp/wheels .
  2. runtime-base から runtime-wheel ステージを構成
  3. wheels のみをインストール: pip install --no-index /tmp/wheels/*
  4. プロジェクトソースツリー (/app/evospikenet, /app/controllers など) をコピーしない

実行例

# API サーバー起動
docker run --rm -p 18000:8000 evospikenet:wheel

# インストール済みパッケージ確認
docker run --rm evospikenet:wheel pip list | grep evospikenet

ビルド検証

# ホイルのインストール確認
docker run --rm evospikenet:wheel python -c \
  "import evospikenet.api; print('✓ API module imported successfully')"

# ソースツリーが除外されていることを確認
docker run --rm evospikenet:wheel test -d /app/evospikenet && \
  echo "WARNING: Source tree found" || echo "✓ Source tree correctly excluded"

# イメージサイズ比較
docker images | grep "evospikenet:source\|evospikenet:wheel"

イメージサイズの目安

  • source: ~500MB (フルソースツリー含む)
  • wheel: ~350MB (ソースツリー除外)

推奨される docker-compose.yml 使用方法

version: '3.8'
services:
  api:
    image: evospikenet:wheel
    ports:
      - "18000:8000"
    read_only: true
    security_opt:
      - no-new-privileges:true

3. cython モード

選定されたモジュールを Cython でコンパイルし、.so(共有オブジェクト)ファイルに変換するモードです。 対応する .py ソースファイルはコンパイル後に削除されます。

用途

  • ✅ プリプロダクション環境
  • ✅ ソース難読化が必須な環境
  • ✅ パフォーマンス最適化が必要な場合
  • ✅ ライセンス保護が重要な場合

セキュリティ特性

  • リスク: .so ファイルは逆コンパイル困難(ただし完全ではない)
  • 対策:
  • 主要モジュールを C 拡張(.so)に変換
  • 元の .py ファイルを削除
  • C デバッグシンボルを取得困難にする
  • 保護レベル: 中程度(専門の逆算出には対応不可)

Cython コンパイル対象モジュール

scripts/protect_with_cython.py で定義:

evospikenet/api.py
evospikenet/api_modules/distributed_brain_api.py
evospikenet/models.py
controllers/placement_controller.py
controllers/resource_controller.py

ビルドコマンド

docker build -t evospikenet:cython \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  .

ビルド過程の詳細

  1. builder ステージで wheel を生成(wheel モード同様)
  2. wheel をインストール
  3. Cython コンパイル実行: scripts/protect_with_cython.py を実行
  4. 対象モジュールを検索
  5. cythonize -3 -i でコンパイル
  6. .so ファイルを生成
  7. 元の .py ファイルを削除
  8. runtime-cython ステージで保護されたモジュールのみを含む

実行例

# API サーバー起動
docker run --rm -p 18000:8000 evospikenet:cython

# Cython コンパイル済みモジュール確認
docker run --rm evospikenet:cython find /opt/venv -name "*.so" | head -5

ビルド検証

# API モジュール動作確認
docker run --rm evospikenet:cython python -c \
  "import evospikenet.api; print('✓ Cython-protected API module loaded')"

# .so ファイルの存在確認
docker run --rm evospikenet:cython python -c \
  "import evospikenet.api; print(evospikenet.api.__file__)"

# 元の .py ファイルが削除されていることを確認
docker run --rm evospikenet:cython test -f /opt/venv/lib/python3.10/site-packages/evospikenet/api.py && \
  echo "WARNING: Source file still exists" || echo "✓ Source file correctly removed"

ビルド時間

wheel コンパイル: ~5 分
+ Cython コンパイル: +10~15 分
= 合計: 15~20 分

イメージサイズの目安

  • wheel: ~350MB
  • cython: ~400MB (.so ファイルのため若干増加)

パフォーマンス影響

  • 起動時間: ほぼ変わらず (プリコンパイル済み)
  • 実行時: +5~10% 高速化の可能性 (Cython 最適化)
  • メモリ使用量: ほぼ同等

推奨される docker-compose.yml 使用方法

version: '3.8'
services:
  api:
    image: evospikenet:cython
    ports:
      - "18000:8000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          memory: 2G

4. nuitka モード

Nuitka コンパイラを使用して、API サーバーを スタンドアロンバイナリに変換するモードです。 最高レベルのソース保護を提供しますが、ビルド時間と結果のイメージサイズが最大になります。

用途

  • ✅ 本番環境での最大保護
  • ✅ 商用デプロイメント
  • ✅ ソースコード機密保持が最優先
  • ✅ 規制環境での配布要件

セキュリティ特性

  • リスク: コンパイル済みバイナリからのソース復元はほぼ不可能
  • 対策:
  • Python ランタイムをスタンドアロンバイナリ化
  • すべての依存を embed
  • 実行時のみ .so ファイルが生成される(一時領域)
  • 保護レベル: 高い(パッチングには再ビルドが必須)

ビルドコマンド

docker build -t evospikenet:nuitka \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  .

ビルド過程の詳細

  1. builder ステージで wheel を生成(wheel モード同様)
  2. scripts/build_nuitka_api_binary.py を実行
  3. 小型 Python ランチャーを作成
  4. Nuitka でコンパイル: nuitka --onefile フラグ
  5. スタンドアロンバイナリ生成: /tmp/nuitka-dist/evospikenet-api
  6. runtime-nuitka ステージでバイナリのみを含む
  7. /app/launch.sh がバイナリ起動

実行例

# API サーバー起動
docker run --rm -p 18000:8000 evospikenet:nuitka

# バイナリの存在確認
docker run --rm evospikenet:nuitka file /tmp/nuitka-dist/evospikenet-api

ビルド検証

# API バイナリが実行可能か確認
docker run --rm evospikenet:nuitka test -x /tmp/nuitka-dist/evospikenet-api && \
  echo "✓ API binary is executable" || echo "ERROR: Binary not executable"

# イメージ内でのバイナリサイズ確認
docker run --rm evospikenet:nuitka du -sh /tmp/nuitka-dist/

# 起動時間を計測
time docker run --rm evospikenet:nuitka bash -c "timeout 5 /tmp/nuitka-dist/evospikenet-api || true"

ビルド時間

wheel コンパイル: ~5 分
+ Nuitka バイナリ化: +30~45 分
= 合計: 35~50 分

イメージサイズの目安

  • wheel: ~350MB
  • nuitka: ~600MB (バイナリとランタイムのため大きい)

パフォーマンス影響

  • 起動時間: +2~3 秒(バイナリの起動オーバーヘッド)
  • 実行時: +3~5% 高速化の可能性(Nuitka コンパイル最適化)
  • メモリ使用量: +50~100MB (スタンドアロンランタイム)

注意事項

1. バイナリの可搬性

Nuitka バイナリはビルドシステムに依存します。異なる Ubuntu バージョンやアーキテクチャでは再ビルドが必須です。

# 事例: Ubuntu 22.04 でビルドしたバイナリは
# Ubuntu 20.04 では動作しない可能性がある
docker build --build-arg BASE_IMAGE=ubuntu:20.04 \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  .

2. パッチング戦略

Nuitka バイナリの脆弱性修正には再ビルドが必須です。

# 依存パッケージ更新後は再ビルド必須
pip install --upgrade <vulnerable-package>
docker build ... --no-cache --target runtime-nuitka ...

3. デバッグ機能の制限

スタンドアロンバイナリはデバッグが困難です。ログレベルを上げてデバッグしてください。

docker run --rm -e LOG_LEVEL=DEBUG evospikenet:nuitka

推奨される docker-compose.yml 使用方法

version: '3.8'
services:
  api:
    image: evospikenet:nuitka
    ports:
      - "18000:8000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    tmpfs:
      - /tmp
      - /var/tmp
    deploy:
      resources:
        limits:
          memory: 3G
        reservations:
          memory: 2G

モード選択フローチャート

┌─────────────────────────────────────┐
│ Docker イメージ用途を決定           │
└─────────────────────────────────────┘
         │
         ├─→ ローカル開発?
         │   └─→ YES: source モード
         │
         ├─→ 社内ステージング?
         │   └─→ YES: wheel モード
         │
         ├─→ ソース難読化が必須?
         │   ├─→ YES: cython モード
         │   └─→ NO: 次へ
         │
         └─→ 本番/商用デプロイ?
             └─→ YES: nuitka モード

ビルドモード比較表(詳細)

項目 source wheel cython nuitka
ビルドコマンド 明示的 --build-arg APP_IMAGE_MODE=wheel --target runtime-wheel --build-arg APP_IMAGE_MODE=cython --target runtime-cython --build-arg APP_IMAGE_MODE=nuitka --target runtime-nuitka
ビルド時間 ~2 分 ~7 分 ~20 分 ~50 分
イメージサイズ 500MB 350MB 400MB 600MB
起動時間 <1s <1s <1s 3-5s
実行速度 100% 100% 105% 105%
デバッグ容易性 ✅ 容易 ⚠️ 困難 ❌ 困難 ❌ 困難
ホットリロード ✅ 可能 ❌ 不可 ❌ 不可 ❌ 不可
パッチング ✅ 簡単 ✅ 簡単 ✅ 簡単 ❌ 再ビルド必須
ソース露出 完全 なし .so 化 なし
セキュリティ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
推奨環境 開発 ステージング プリプロ 本番

トラブルシューティング

ビルドエラー: "permission denied while trying to connect to Docker daemon"

# Docker デーモン確認
docker ps

# 必要に応じて Docker 再起動
systemctl restart docker

ビルドエラー: "No space left on device"

Docker イメージビルドのためのディスク容量が不足しています。

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

# クリーンアップ
docker builder prune -a

Cython モード: "cythonize not found"

Cython はビルドステージでのみ使用されます。docker build が正常に完了していない可能性があります。

# ビルドログ確認
docker build ... --build-arg APP_IMAGE_MODE=cython 2>&1 | tail -50

Nuitka モード: "Binary segmentation fault"

スタンドアロンバイナリが異なる Linux 環境で動作していない可能性があります。

# BASE_IMAGE を一致させて再ビルド
docker build --build-arg BASE_IMAGE=ubuntu:22.04 \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  .

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

Nuitka モード時に --onefile オプション処理が正常に完了していない可能性があります。

# イメージ内容確認
docker run --rm evospikenet:nuitka du -sh /tmp/nuitka-dist/
docker run --rm evospikenet:nuitka du -sh /opt/venv/

ベストプラクティス

1. 開発フロー

# ローカル: source モード
docker compose up -d api

# テスト環境: wheel モード
docker build -t myregistry.azurecr.io/evospikenet:wheel \
  --build-arg APP_IMAGE_MODE=wheel \
  --target runtime-wheel \
  .
docker push myregistry.azurecr.io/evospikenet:wheel

2. リリースプロセス

# ステージング検証: wheel
# → OK なら cython へ移行
# → OK なら nuitka で最終ビルド
# → 本番環境へデプロイ

docker build -t evospikenet:v1.0-cython \
  --build-arg APP_IMAGE_MODE=cython \
  --target runtime-cython \
  .

docker build -t evospikenet:v1.0-nuitka \
  --build-arg APP_IMAGE_MODE=nuitka \
  --target runtime-nuitka \
  .

3. レジストリタグ戦略

# ビルドモードを明確にタグ付け
docker tag evospikenet:wheel myregistry/evospikenet:latest-wheel
docker tag evospikenet:cython myregistry/evospikenet:latest-cython
docker tag evospikenet:nuitka myregistry/evospikenet:latest-nuitka

# バージョン + モードで管理
docker tag evospikenet:nuitka myregistry/evospikenet:v1.0.0-nuitka

4. セキュリティ設定

# docker-compose.yml(本番環境推奨)
services:
  api:
    image: evospikenet:nuitka
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    tmpfs:
      - /tmp
      - /var/tmp

関連ドキュメント