# バッチ設計書 33-docker-image-tool.sh

## 概要

本ドキュメントは、SparkのDockerイメージをビルド・プッシュするスクリプト `bin/docker-image-tool.sh` のバッチ設計書である。本スクリプトはKubernetes上でSparkを実行するためのDockerイメージ（JVM用、PySpark用、SparkR用）をビルドし、Dockerレジストリへのプッシュを行う。docker buildxによるクロスビルド（マルチアーキテクチャ）にも対応する。

### 本バッチの処理概要

本スクリプトは、Sparkのリリースビルドまたは開発ビルドからKubernetes向けのDockerイメージを生成するツールである。

**業務上の目的・背景**：Apache SparkはKubernetes上でのネイティブ実行をサポートしており、そのためにはSparkランタイムを含むDockerイメージが必要である。本スクリプトは、JVM Sparkイメージ（ベースイメージ）、PySparkイメージ（Python依存関係付き）、SparkRイメージ（R依存関係付き）の3種類のイメージを効率的にビルドする機能を提供する。開発ビルドとリリースビルドの両方に対応し、開発ビルド時にはDockerデーモンに送信するビルドコンテキストのサイズを最小化する最適化が組み込まれている。

**バッチの実行タイミング**：Kubernetes環境へのSparkデプロイ準備時に手動実行される。CI/CDパイプラインによるイメージ自動ビルド時にも使用される。

**主要な処理内容**：
1. SPARK_HOMEの設定とload-spark-env.shによる環境変数読み込み
2. コマンドライン引数の解析（リポジトリ、タグ、Dockerfile指定、ビルドオプション等）
3. リリースビルド/開発ビルドの判定（RELEASEファイルの有無）
4. 開発ビルド時：最小限のビルドコンテキスト作成（base/pyspark/sparkrの3種）
5. Spark JARの存在検証
6. ベースDockerイメージ（spark）のビルド
7. PySparkイメージ（spark-py）のビルド（-p オプション指定時）
8. SparkRイメージ（spark-r）のビルド（-R オプション指定時）
9. クロスビルド時（-X）：docker buildxによるマルチアーキテクチャビルドとプッシュ
10. プッシュコマンド：ビルド済みイメージのレジストリへのプッシュ

**前後の処理との関連**：ビルド前にSparkがビルド済み（assembly JARが存在する状態）であるか、リリースディストリビューションが作成済みである必要がある。make-distribution.shの出力を入力として使用することが一般的。ビルドされたDockerイメージはKubernetes上でのSpark実行に直接使用される。

**影響範囲**：ローカルのDockerデーモン上にDockerイメージが作成される。プッシュ操作を行った場合は指定されたDockerレジストリにイメージがアップロードされる。開発ビルド時にはtarget/tmp/docker配下に一時的なビルドコンテキストが作成され、終了時に自動クリーンアップされる。

## バッチ種別

ビルド・リリース（Dockerイメージビルド・プッシュ）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（Dockerイメージ作成時） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | 手動実行 / CI/CDパイプライン |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Docker | Dockerデーモンが起動済みであること |
| Sparkビルド済み | assembly JARが存在するか、リリースディストリビューションが作成済みであること |
| kubernetes/dockerfiles | Dockerfileディレクトリが存在すること |
| docker buildx（-X使用時） | クロスビルド時にdocker buildxがセットアップ済みであること |
| minikube（-m使用時） | minikubeが起動中であること |

### 実行可否判定

- kubernetes/dockerfilesディレクトリが存在しない場合はエラー終了する
- Spark JARファイル（jars/spark-*）が見つからない場合はエラー終了する
- pushコマンド実行時にリポジトリ（-r）が未指定の場合はエラー終了する

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| -f file | string | No | kubernetes/dockerfiles/spark/Dockerfile | JVMベースジョブ用Dockerfile |
| -p file | string | No | 未指定（スキップ） | PySpark用Dockerfile |
| -R file | string | No | 未指定（スキップ） | SparkR用Dockerfile |
| -r repo | string | No | 空 | Dockerレジストリのリポジトリアドレス |
| -t tag | string | No | 空 | Dockerイメージに付与するタグ |
| -m | フラグ | No | false | minikubeのDockerデーモンを使用する |
| -n | フラグ | No | false | --no-cacheでビルドする |
| -u uid | string | No | 空 | コンテナ内のSparkプロセス実行ユーザーUID |
| -X | フラグ | No | false | docker buildxでクロスビルドする（自動プッシュ） |
| -b arg | string | No | 空 | Dockerビルド引数（複数指定可能） |
| build/push | コマンド | Yes | N/A | 最後の引数としてbuildまたはpushを指定 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| kubernetes/dockerfiles/ | Dockerfile | Dockerイメージビルド用Dockerfile群 |
| assembly/target/scala-*/jars/ | JAR | SparkアセンブリJAR |
| examples/target/scala-*/jars/ | JAR | サンプルアプリケーションJAR |
| bin/, sbin/, data/ | スクリプト・データ | コンテナに含めるスクリプト・データ |
| python/ | Python | PySpark用イメージに含めるPythonライブラリ |
| R/ | R | SparkR用イメージに含めるRパッケージ |
| RELEASE | テキスト | リリースビルド判定に使用 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Docker デーモン（ローカル） | Dockerイメージ | sparkイメージ（JVMベース） |
| Docker デーモン（ローカル） | Dockerイメージ | spark-pyイメージ（PySpark用、-p指定時） |
| Docker デーモン（ローカル） | Dockerイメージ | spark-rイメージ（SparkR用、-R指定時） |
| Dockerレジストリ（push時） | Dockerイメージ | 指定リポジトリ/タグでプッシュされたイメージ |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| イメージ名（JVM） | [REPO/]spark[:TAG] |
| イメージ名（PySpark） | [REPO/]spark-py[:TAG] |
| イメージ名（SparkR） | [REPO/]spark-r[:TAG] |
| 一時ビルドコンテキスト | $SPARK_HOME/target/tmp/docker/（開発ビルド時、終了時自動削除） |

## 処理フロー

### 処理シーケンス

```
1. SPARK_HOME設定・環境読み込み
   └─ load-spark-env.shをsource
2. コマンドライン引数解析
   └─ -f, -p, -R, -r, -t, -m, -n, -u, -X, -b オプションの解析
3. コマンド判定（最後の引数）
   └─ build: ビルドフローへ
   └─ push: プッシュフローへ
   └─ その他: usage表示・終了

[buildフロー]
4. リリースビルド/開発ビルド判定
   └─ RELEASEファイルの有無で判定
5. [開発ビルド時] ビルドコンテキスト作成
   └─ base: jars, kubernetes, examples, bin, sbin, data
   └─ pyspark: kubernetes, python/lib, python/pyspark
   └─ sparkr: kubernetes, R
6. Dockerfileとspark JARの存在検証
   └─ kubernetes/dockerfilesディレクトリの存在確認
   └─ jars/spark-* ファイルの存在確認
7. ベースイメージ（spark）ビルド
   └─ docker build + [クロスビルド時] docker buildx build
8. [PySpark Dockerfile指定時] spark-pyイメージビルド
   └─ base_imgとしてsparkイメージを参照
9. [SparkR Dockerfile指定時] spark-rイメージビルド
   └─ base_imgとしてsparkイメージを参照

[pushフロー]
10. spark, spark-py, spark-rの順にdocker pushを実行
    └─ イメージが存在しない場合はスキップ
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[SPARK_HOME設定・環境読込]
    B --> C[引数解析]
    C --> D{コマンド?}
    D -->|build| E{開発ビルド?}
    D -->|push| P[docker push spark/spark-py/spark-r]
    D -->|その他| U[usage表示・終了]
    E -->|はい| F[ビルドコンテキスト作成]
    E -->|いいえ| G{Dockerfile・JAR存在?}
    F --> G
    G -->|いいえ| H[エラー終了]
    G -->|はい| I[sparkイメージビルド]
    I --> J{-X クロスビルド?}
    J -->|はい| K[docker buildx build + push]
    J -->|いいえ| L{PySpark Dockerfile指定?}
    K --> L
    L -->|はい| M[spark-pyイメージビルド]
    L -->|いいえ| N{SparkR Dockerfile指定?}
    M --> N
    N -->|はい| O[spark-rイメージビルド]
    N -->|いいえ| Q[終了]
    O --> Q
    P --> Q
```

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし。本スクリプトはDockerコマンドとファイルシステム操作のみを行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | Dockerfileディレクトリ不在 | kubernetes/dockerfilesが見つからない | Sparkをビルドするか、リリースディストリビューションから実行する |
| 1 | Spark JAR不在 | jars/spark-*ファイルが見つからない | Sparkをビルドしてからイメージビルドを実行する |
| 1 | ベースイメージビルド失敗 | docker buildが失敗 | Dockerビルドログを確認し問題を解消する |
| 1 | PySpark/SparkRイメージビルド失敗 | docker buildが失敗 | Dockerビルドログを確認し問題を解消する |
| 1 | イメージプッシュ失敗 | docker pushが失敗 | レジストリの認証・ネットワークを確認する |
| 1 | minikube不在/停止中 | -mオプション使用時にminikubeが見つからないか停止中 | minikubeをインストール・起動する |
| 1 | リポジトリ未指定 | pushコマンドで-rオプション未指定 | -rオプションでリポジトリを指定する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

- Dockerビルド失敗時：Dockerビルドのエラー出力を確認し、Dockerfileの構文やベースイメージの可用性を検証する
- プッシュ失敗時：レジストリへの認証情報（docker login）とネットワーク接続を確認する
- 開発ビルドのビルドコンテキストはtrapによるEXITハンドラで自動クリーンアップされる

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（Docker操作のみ） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 最大3イメージ（spark, spark-py, spark-r） |
| 目標処理時間 | 環境依存（Dockerビルドキャッシュの有無に大きく依存） |
| メモリ使用量上限 | Docker デーモンの設定に依存 |

## 排他制御

同一Dockerデーモンに対する同時ビルドはDocker側で制御される。ただし、開発ビルド時のビルドコンテキストディレクトリ（target/tmp/docker/）は同時実行で競合する可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| エラーログ | エラー発生時 | エラーメッセージ（stderr出力） |
| スキップログ | プッシュ対象イメージ不在時 | イメージが見つからないためスキップする旨のメッセージ |
| ビルドログ | ビルド中 | Dockerビルドの標準出力 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| Dockerビルド結果 | exit code != 0 | CI/CDシステム |
| Dockerプッシュ結果 | exit code != 0 | CI/CDシステム |

## 備考

- 開発ビルド（RELEASEファイルが存在しない状態）では、Dockerビルドコンテキストを最小化するために一時ディレクトリに必要なファイルのみをコピーする最適化が行われる。これはテストログ等の不要なファイルがDockerデーモンにアップロードされるのを防ぐためである
- クロスビルド（-X）使用時はdocker buildx buildが使用され、デフォルトでlinux/amd64およびlinux/arm64の2アーキテクチャに対応する。クロスビルドでは--pushフラグが自動的に付与されるため、別途pushコマンドは不要である
- minikubeオプション（-m）使用時は`eval $(minikube docker-env --shell bash)`によりminikubeのDockerデーモンに直接ビルドするため、イメージのプッシュは不要
- PySpark/SparkRイメージはベースのsparkイメージを`base_img`ビルド引数として参照する
- SPARK_UIDオプション（-u）によりコンテナ内のSpark実行ユーザーのUIDを変更可能
- `--provenance=false`がbuildxコマンドに付与されており、プロベナンス情報の生成を無効化している
