# 機能設計書 63-コンテナレジストリ

## 概要

本ドキュメントは、GitLabにおけるコンテナレジストリ機能の設計仕様を記載する。Dockerイメージおよび OCI（Open Container Initiative）互換イメージの保存・管理・配布を行うプライベートコンテナレジストリ機能を提供する。

### 本機能の処理概要

コンテナレジストリ機能は、Docker/OCI互換のコンテナイメージをGitLabプロジェクト内でホスティングするための機能である。Docker Distribution V2 API（Docker Registry HTTP API V2）に準拠し、標準的なDockerコマンドでのプッシュ・プルをサポートする。

**業務上の目的・背景**：コンテナ化されたアプリケーション開発において、ビルドしたコンテナイメージを安全に保存・配布する仕組みは必須である。従来はDocker Hub、Amazon ECR、Google Container Registryなどの外部サービスを利用する必要があったが、本機能によりGitLab内でソースコードとコンテナイメージを統合管理できる。これにより、アクセス制御の一元化、CI/CDパイプラインとのシームレスな連携、セキュリティスキャンとの統合が可能となる。

**機能の利用シーン**：
- CI/CDパイプラインでビルドしたDockerイメージの保存・タグ付け
- 開発・ステージング・本番環境へのコンテナイメージ配布
- マイクロサービスアーキテクチャにおけるサービスイメージの管理
- コンテナイメージのバージョン管理と履歴追跡
- イメージタグの保護（push/delete制限）

**主要な処理内容**：
1. コンテナリポジトリの一覧表示・詳細表示
2. Dockerイメージのプッシュ（docker push）
3. Dockerイメージのプル（docker pull）
4. タグの一覧表示・削除
5. コンテナリポジトリの削除
6. 有効期限ポリシーによる自動クリーンアップ

**関連システム・外部連携**：
- Docker CLI / Docker Engine
- Kubernetes（イメージプル）
- CI/CDパイプライン（docker build & push）
- GitLab Container Registryサーバー（別プロセス）
- GitLab API（認証用JWTトークン発行）

**権限による制御**：
- `read_container_image`権限：イメージの閲覧・プル
- `update_container_image`権限：リポジトリの削除
- `destroy_container_image_tag`権限：タグの削除
- タグ保護ルールによるpush/delete制限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 96 | コンテナレジストリ | 主機能 | Dockerコンテナレジストリの表示 |
| 97 | Harbor連携 | 主機能 | Harbor連携リポジトリの表示 |
| 115 | パッケージ設定 | 補助機能 | コンテナレジストリ設定 |
| 158 | コンテナレジストリ（グループ） | 主機能 | グループコンテナレジストリの表示 |
| 159 | Harbor連携（グループ） | 主機能 | グループHarbor連携の表示 |

## 機能種別

CRUD操作 / ファイルストレージ / データ連携 / 認証連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id（リポジトリ一覧） | Integer | Yes | プロジェクトID | 存在確認 |
| repository_id | Integer | タグ操作時Yes | コンテナリポジトリID | 存在確認 |
| ids（バルク削除） | Array[String] | バルク削除時Yes | 削除対象タグ名の配列 | 最大15件 |

### 入力データソース

- Docker CLI（docker push/pull/login）
- Web UI（コンテナレジストリ画面）
- CI/CDジョブからのDocker操作
- Kubernetesからのイメージプル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | コンテナリポジトリID |
| name | String | リポジトリ名 |
| path | String | フルパス（registry.gitlab.com/group/project/name） |
| location | String | レジストリURL |
| tags | Array | タグ一覧 |
| tags_count | Integer | タグ数 |
| size | Integer | サイズ（バイト） |
| status | String | ステータス（delete_scheduled, delete_failed, delete_ongoing） |

### 出力先

- HTTPレスポンス（JSON）
- Docker Registry API レスポンス
- コンテナイメージのブロブストレージ

## 処理フロー

### 処理シーケンス

```
1. コンテナリポジトリ一覧取得
   └─ プロジェクトのcontainer_feature有効化確認
   └─ ルートリポジトリの存在確認・作成
   └─ リポジトリ一覧をJSON返却

2. タグ一覧取得
   └─ リポジトリIDでContainer Repository取得
   └─ GitLab Registry APIまたはmanifestからタグ取得
   └─ ページネーション適用
   └─ JSON返却

3. タグ削除
   └─ destroy_container_image_tag権限チェック
   └─ タグ保護ルールチェック
   └─ DeleteTagsService呼び出し
   └─ レジストリAPIでタグ削除

4. リポジトリ削除
   └─ update_container_image権限チェック
   └─ delete_scheduled ステータスに更新
   └─ 非同期ワーカーで実際の削除処理

5. 有効期限ポリシークリーンアップ
   └─ 対象リポジトリの抽出
   └─ ポリシーに基づくタグ選定
   └─ 対象タグの削除
```

### フローチャート

```mermaid
flowchart TD
    A[Docker push/pull] --> B[GitLab JWT認証]
    B --> C{認証成功?}
    C -->|No| D[401 Unauthorized]
    C -->|Yes| E[Container Registry サーバー]
    E --> F{操作種別}

    F -->|push| G{タグ保護チェック}
    G -->|保護対象| H[403 Forbidden]
    G -->|OK| I[イメージ保存]
    I --> J[メタデータ更新]

    F -->|pull| K[イメージ取得]
    K --> L[レスポンス返却]

    M[Web UI] --> N{認証・権限チェック}
    N -->|失敗| O[アクセス拒否]
    N -->|成功| P{操作種別}

    P -->|一覧| Q[リポジトリ一覧取得]
    P -->|タグ削除| R[DeleteTagsService]
    R --> S{削除成功?}
    S -->|Yes| T[200 OK]
    S -->|No| U[400 Bad Request]

    P -->|リポジトリ削除| V[delete_scheduled設定]
    V --> W[非同期削除ワーカー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | リポジトリ名一意性 | プロジェクト内でリポジトリ名は一意 | リポジトリ作成時 |
| BR-02 | タグ保護 | 保護ルールに該当するタグはpush/delete制限 | タグ操作時 |
| BR-03 | 削除リトライ | 削除失敗時は指数バックオフでリトライ（最大10回） | リポジトリ削除時 |
| BR-04 | ルートリポジトリ | プロジェクトパス直下のリポジトリを自動作成 | 初回アクセス時 |
| BR-05 | タグページング | タグ取得は最大2000ページ | タグ一覧取得時 |
| BR-06 | バルク削除上限 | 一度に削除できるタグは最大15件 | バルクタグ削除時 |
| BR-07 | 有効期限ポリシー | 設定に基づき古いタグを自動削除 | スケジュール実行時 |

### 計算ロジック

- 削除リトライ間隔: `2^failed_deletion_count` 分
- JWTトークンキャッシュ: `container_registry_token_expire_delay * 60 - 5` 秒

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リポジトリ作成 | container_repositories | INSERT | 新規リポジトリレコードの作成 |
| リポジトリ取得 | container_repositories | SELECT | リポジトリ情報の取得 |
| リポジトリ削除 | container_repositories | UPDATE | status=delete_scheduled へ更新 |
| 物理削除 | container_repositories | DELETE | レコードの完全削除 |
| クリーンアップステータス更新 | container_repositories | UPDATE | expiration_policy_cleanup_status の更新 |

### テーブル別操作詳細

#### container_repositories

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | project_id | 対象プロジェクトID | 外部キー |
| INSERT | name | リポジトリ名 | 空文字でルートリポジトリ |
| UPDATE | status | 0:delete_scheduled, 1:delete_failed, 2:delete_ongoing | enum |
| UPDATE | delete_started_at | Time.zone.now | 削除開始時刻 |
| UPDATE | failed_deletion_count | +1 | 失敗カウント（最大10） |
| UPDATE | next_delete_attempt_at | 次回リトライ時刻 | 指数バックオフ |
| UPDATE | expiration_policy_cleanup_status | 0-3 | クリーンアップステータス |
| UPDATE | expiration_policy_started_at | Time.zone.now | クリーンアップ開始時刻 |
| UPDATE | last_cleanup_deleted_tags_count | 削除タグ数 | クリーンアップ結果 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | Docker認証失敗 | docker loginを再実行 |
| 403 | Forbidden | 権限不足、タグ保護違反 | 権限を確認、保護ルールを確認 |
| 404 | Not Found | リポジトリ/タグが存在しない | 名前を確認 |
| 400 | Bad Request | タグ名未指定、バルク削除上限超過 | リクエストを修正 |

### リトライ仕様

- リポジトリ削除失敗時: 指数バックオフ（2^n分）で最大10回リトライ
- 10回失敗後: delete_failedステータスに遷移

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

- リポジトリ削除は論理削除（ステータス変更）後、非同期ワーカーで物理削除
- タグ削除はレジストリAPIへの直接呼び出し（トランザクション外）

## パフォーマンス要件

- タグ一覧はページネーション対応（デフォルト15件/ページ）
- タグページング上限: 2000ページ
- JWTトークンのキャッシュによるAPI呼び出し削減

## セキュリティ考慮事項

- JWTトークンによるDocker認証
- プロジェクト/グループの可視性に基づくアクセス制御
- タグ保護ルールによるpush/delete制限
- 管理者は保護ルールをバイパス可能

## 備考

- GitLab Container Registryは別プロセス（Dockerレジストリサーバー）として動作
- GitLab API経由でタグ情報取得可能（GitLab Registry APIサポート時）
- Harbor連携によりHarborレジストリとの統合も可能
- feature_category: `container_registry`

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

コンテナレジストリで使用される主要なデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | container_repository.rb | `app/models/container_repository.rb` | コンテナリポジトリのActiveRecordモデル。status enum、クリーンアップステータスを確認 |
| 1-2 | tag.rb | `lib/container_registry/tag.rb` | タグクラス。manifest、digest、保護ルールを確認 |

**読解のコツ**:
- **30-31行目（container_repository.rb）**: `status` と `expiration_policy_cleanup_status` の enum定義を把握
- **94-103行目（container_repository.rb）**: `registry`メソッドでJWTトークン取得・キャッシュを確認
- **137-154行目（container_repository.rb）**: `tags`メソッドでGitLab API/manifest両対応の実装を確認
- **156-180行目（container_repository.rb）**: `each_tags_page`でページング実装を確認

#### Step 2: エントリーポイントを理解する

Web UI経由でのリクエスト処理の起点となるファイルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | repositories_controller.rb | `app/controllers/projects/registry/repositories_controller.rb` | リポジトリコントローラー |
| 2-2 | tags_controller.rb | `app/controllers/projects/registry/tags_controller.rb` | タグコントローラー |

**主要処理フロー**:
1. **11-16行目（repositories_controller.rb）**: `index`アクション - ルートリポジトリ確保
2. **23-31行目（repositories_controller.rb）**: `destroy`アクション - delete_scheduled設定
3. **12-23行目（tags_controller.rb）**: `index`アクション - タグ一覧取得
4. **25-34行目（tags_controller.rb）**: `destroy`アクション - タグ削除
5. **36-51行目（tags_controller.rb）**: `bulk_destroy`アクション - バルクタグ削除

#### Step 3: サービス層を理解する

タグ削除のビジネスロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | delete_tags_service.rb | `app/services/projects/container_repository/delete_tags_service.rb` | タグ削除サービス |

**主要処理フロー**:
- **8-19行目**: `execute`メソッドで権限チェック、タグ名取得、削除実行
- **29-38行目**: `delete_service`でGitLab API/サードパーティAPIの分岐

#### Step 4: レジストリクライアントを理解する

Container Registryサーバーとの通信を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | client.rb | `lib/container_registry/client.rb` | レジストリクライアント（Docker Registry API） |
| 4-2 | gitlab_api_client.rb | `lib/container_registry/gitlab_api_client.rb` | GitLab Registry APIクライアント |

### プログラム呼び出し階層図

```
Docker CLI / Web UI
    │
    ├─ docker push/pull
    │      └─ JWT認証（Auth::ContainerRegistryAuthenticationService）
    │             └─ Container Registry Server
    │                    └─ ブロブストレージ
    │
    ├─ GET /projects/:id/registry/repositories
    │      └─ RepositoriesController#index
    │             └─ ensure_root_container_repository!
    │                    └─ ContainerRepository.build_from_path
    │
    ├─ GET /projects/:id/registry/repositories/:repository_id/tags
    │      └─ TagsController#index
    │             └─ ContainerRepository#tags
    │                    ├─ gitlab_api_client.tags (GitLab API)
    │                    └─ client.repository_tags (Docker API)
    │
    ├─ DELETE /projects/:id/registry/repositories/:repository_id/tags/:id
    │      └─ TagsController#destroy
    │             └─ DeleteTagsService#execute
    │                    ├─ Gitlab::DeleteTagsService (GitLab API)
    │                    └─ ThirdParty::DeleteTagsService (Docker API)
    │
    └─ DELETE /projects/:id/registry/repositories/:id
           └─ RepositoriesController#destroy
                  └─ container_repository.delete_scheduled!
                         └─ DeleteContainerRepositoryWorker（非同期）
```

### データフロー図

```
[入力]                    [処理]                           [出力]

Docker CLI ─────────▶ GitLab JWT認証 ──────────────▶ Container Registry
(docker push/pull)      (JWTトークン発行)               Server
                              │                              │
                              ▼                              ▼
                    Auth::ContainerRegistry          Blob Storage
                    AuthenticationService            (S3/Local)
                              │
                              ▼
Web UI ─────────────▶ Projects::Registry::        HTTP Response
(リポジトリ一覧等)     RepositoriesController      (JSON)
                              │
                              ▼
                    ContainerRepository
                    (ActiveRecord)
                              │
                              ▼
                    container_repositories
                    (PostgreSQL)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| container_repository.rb | `app/models/container_repository.rb` | モデル | コンテナリポジトリのモデル |
| repositories_controller.rb | `app/controllers/projects/registry/repositories_controller.rb` | コントローラー | リポジトリ操作 |
| tags_controller.rb | `app/controllers/projects/registry/tags_controller.rb` | コントローラー | タグ操作 |
| delete_tags_service.rb | `app/services/projects/container_repository/delete_tags_service.rb` | サービス | タグ削除 |
| tag.rb | `lib/container_registry/tag.rb` | ライブラリ | タグクラス |
| client.rb | `lib/container_registry/client.rb` | ライブラリ | Docker Registry APIクライアント |
| gitlab_api_client.rb | `lib/container_registry/gitlab_api_client.rb` | ライブラリ | GitLab Registry APIクライアント |
| registry.rb | `lib/container_registry/registry.rb` | ライブラリ | レジストリラッパー |
| path.rb | `lib/container_registry/path.rb` | ライブラリ | パス解析 |
| blob.rb | `lib/container_registry/blob.rb` | ライブラリ | ブロブクラス |
| config.rb | `lib/container_registry/config.rb` | ライブラリ | イメージ設定 |
| application_controller.rb | `app/controllers/projects/registry/application_controller.rb` | コントローラー | ベースコントローラー |
