# インフラ構成図

## OSS版（単一サーバー構成）

```mermaid
graph TB
    subgraph Internet
        User[ユーザー]
    end

    subgraph Server["アプリケーションサーバー"]
        subgraph Container["Docker Container"]
            Thruster["Thruster<br/>(HTTP/2 Proxy)"]
            Puma["Puma<br/>(App Server)"]
            SolidQueue["Solid Queue<br/>(Background Jobs)"]
            SolidCable["Solid Cable<br/>(WebSocket)"]
            SolidCache["Solid Cache"]
        end

        subgraph Storage["ストレージ"]
            SQLite[("SQLite3<br/>または<br/>MySQL")]
            FileStorage["Active Storage<br/>(ローカル/S3)"]
            Volume["Docker Volume<br/>(fizzy_storage)"]
        end
    end

    subgraph External["外部サービス"]
        SMTP["SMTP Server"]
        S3["S3 Storage<br/>(オプション)"]
    end

    User -->|HTTPS:443| Thruster
    Thruster --> Puma
    Puma --> SQLite
    Puma --> SolidCache
    Puma --> SolidQueue
    Puma --> SolidCable
    Puma --> FileStorage
    FileStorage --> Volume
    FileStorage -.->|オプション| S3
    Puma -->|メール送信| SMTP

    style Container fill:#e1f5fe
    style Storage fill:#fff3e0
    style External fill:#f3e5f5
```

## SaaS版（マルチデータセンター構成）

```mermaid
graph TB
    subgraph Internet
        Users[ユーザー]
    end

    subgraph DC_IAD["DF-IAD (Ashburn) - プライマリ"]
        LB_IAD1["fizzy-lb-101<br/>(kamal-proxy:lb)"]
        LB_IAD2["fizzy-lb-102<br/>(kamal-proxy:lb)"]

        subgraph App_IAD["アプリケーション層"]
            App_IAD1["fizzy-app-101"]
            App_IAD2["fizzy-app-102"]
        end

        subgraph Jobs_IAD["ジョブ層"]
            Job_IAD1["fizzy-jobs-101"]
            Job_IAD2["fizzy-jobs-102"]
        end

        CacheDB_IAD[("fizzy-solidcache-db-101<br/>(Solid Cache)")]
    end

    subgraph DC_CHI["SC-CHI (Chicago)"]
        LB_CHI1["fizzy-lb-01<br/>(kamal-proxy:lb)"]
        LB_CHI2["fizzy-lb-02<br/>(kamal-proxy:lb)"]

        subgraph App_CHI["アプリケーション層"]
            App_CHI1["fizzy-app-01"]
            App_CHI2["fizzy-app-02"]
        end

        CacheDB_CHI[("fizzy-solidcache-db-01<br/>(Solid Cache)")]
    end

    subgraph DC_AMS["DF-AMS (Amsterdam)"]
        LB_AMS1["fizzy-lb-401<br/>(kamal-proxy:lb)"]
        LB_AMS2["fizzy-lb-402<br/>(kamal-proxy:lb)"]

        subgraph App_AMS["アプリケーション層"]
            App_AMS1["fizzy-app-401"]
            App_AMS2["fizzy-app-402"]
        end

        CacheDB_AMS[("fizzy-solidcache-db-401<br/>(Solid Cache)")]
    end

    subgraph SharedDB["共有データベース"]
        MySQLPrimary[("fizzy-mysql-primary<br/>(Primary DB)")]
        MySQLReplica[("fizzy-mysql-replica<br/>(Replica DB)")]
        SolidQueueDB[("fizzy-solidqueue<br/>(Queue DB)")]
        SolidCableDB[("fizzy-solidcable<br/>(Cable DB)")]
    end

    subgraph SharedStorage["共有ストレージ"]
        PureStorage["PureStorage FlashBlade<br/>(S3互換)"]
        NFSCerts["NFS<br/>(証明書共有)"]
    end

    subgraph External["外部サービス"]
        Stripe["Stripe"]
        Sentry["Sentry"]
        SignalID["Signal ID"]
    end

    Users --> LB_IAD1
    Users --> LB_IAD2
    Users --> LB_CHI1
    Users --> LB_CHI2
    Users --> LB_AMS1
    Users --> LB_AMS2

    LB_IAD1 --> App_IAD1
    LB_IAD1 --> App_IAD2
    LB_IAD2 --> App_IAD1
    LB_IAD2 --> App_IAD2

    LB_CHI1 --> App_CHI1
    LB_CHI1 --> App_CHI2
    LB_CHI2 --> App_CHI1
    LB_CHI2 --> App_CHI2

    LB_AMS1 --> App_AMS1
    LB_AMS1 --> App_AMS2
    LB_AMS2 --> App_AMS1
    LB_AMS2 --> App_AMS2

    App_IAD1 --> MySQLPrimary
    App_IAD1 --> MySQLReplica
    App_IAD1 --> CacheDB_IAD
    App_IAD2 --> MySQLPrimary
    App_IAD2 --> MySQLReplica
    App_IAD2 --> CacheDB_IAD

    App_CHI1 --> MySQLPrimary
    App_CHI1 --> MySQLReplica
    App_CHI1 --> CacheDB_CHI
    App_CHI2 --> MySQLPrimary
    App_CHI2 --> MySQLReplica
    App_CHI2 --> CacheDB_CHI

    App_AMS1 --> MySQLPrimary
    App_AMS1 --> MySQLReplica
    App_AMS1 --> CacheDB_AMS
    App_AMS2 --> MySQLPrimary
    App_AMS2 --> MySQLReplica
    App_AMS2 --> CacheDB_AMS

    Job_IAD1 --> MySQLPrimary
    Job_IAD1 --> SolidQueueDB
    Job_IAD2 --> MySQLPrimary
    Job_IAD2 --> SolidQueueDB

    App_IAD1 --> SolidCableDB
    App_IAD2 --> SolidCableDB
    App_CHI1 --> SolidCableDB
    App_CHI2 --> SolidCableDB
    App_AMS1 --> SolidCableDB
    App_AMS2 --> SolidCableDB

    App_IAD1 --> PureStorage
    App_IAD2 --> PureStorage
    App_CHI1 --> PureStorage
    App_CHI2 --> PureStorage
    App_AMS1 --> PureStorage
    App_AMS2 --> PureStorage

    LB_IAD1 --> NFSCerts
    LB_IAD2 --> NFSCerts
    LB_CHI1 --> NFSCerts
    LB_CHI2 --> NFSCerts
    LB_AMS1 --> NFSCerts
    LB_AMS2 --> NFSCerts

    App_IAD1 -.-> Stripe
    App_IAD1 -.-> Sentry
    App_IAD1 -.-> SignalID

    MySQLPrimary --> MySQLReplica

    style DC_IAD fill:#e3f2fd
    style DC_CHI fill:#e8f5e9
    style DC_AMS fill:#fff8e1
    style SharedDB fill:#fce4ec
    style SharedStorage fill:#f3e5f5
    style External fill:#efebe9
```

## コンテナ内部構成

```mermaid
graph LR
    subgraph Container["Docker Container (アプリケーション)"]
        direction TB

        subgraph Process["プロセス構成"]
            Entrypoint["docker-entrypoint<br/>(初期化スクリプト)"]
            Thruster["Thruster<br/>Port: 80/443"]
            Puma["Puma<br/>(Rails Server)"]
        end

        subgraph Libs["ライブラリ"]
            jemalloc["jemalloc<br/>(メモリ最適化)"]
            Bootsnap["Bootsnap<br/>(起動高速化)"]
        end

        subgraph Rails["Rails アプリケーション"]
            ActionCable["Action Cable<br/>(WebSocket)"]
            ActiveStorage["Active Storage<br/>(ファイル管理)"]
            ActiveJob["Active Job<br/>(ジョブ)"]
        end

        subgraph Adapters["アダプター"]
            SolidQueue["Solid Queue"]
            SolidCable["Solid Cable"]
            SolidCache["Solid Cache"]
            Trilogy["Trilogy<br/>(MySQL)"]
            SQLite["SQLite3"]
        end
    end

    Entrypoint -->|"db:prepare"| Puma
    Puma --> Thruster
    Puma --> Rails
    Rails --> Adapters
    Process --> Libs

    style Container fill:#e1f5fe
    style Process fill:#bbdefb
    style Rails fill:#c8e6c9
    style Adapters fill:#fff9c4
```

## デプロイメントフロー

```mermaid
sequenceDiagram
    participant Dev as 開発者
    participant GH as GitHub
    participant GA as GitHub Actions
    participant GHCR as GHCR
    participant Kamal as Kamal
    participant Server as サーバー

    Dev->>GH: git push (main/tag)
    GH->>GA: Trigger workflow

    par ビルド (amd64)
        GA->>GA: Build linux/amd64
    and ビルド (arm64)
        GA->>GA: Build linux/arm64
    end

    GA->>GHCR: Push images (arch suffix)
    GA->>GA: Create multi-arch manifest
    GA->>GA: Cosign sign images
    GA->>GHCR: Push manifest

    Note over Dev,Server: デプロイ実行

    Dev->>Kamal: kamal deploy
    Kamal->>Server: Pull image
    Kamal->>Server: Stop old container
    Kamal->>Server: Start new container
    Server->>Server: docker-entrypoint (db:prepare)
    Server->>Server: Thruster + Puma start

    Kamal->>Server: Health check
    Kamal->>Dev: Deploy complete
```

## ネットワーク構成（SaaS版）

```mermaid
graph TB
    subgraph Public["パブリックネットワーク"]
        Internet((インターネット))
    end

    subgraph LoadBalancers["ロードバランサー層"]
        LB1["LB-IAD"]
        LB2["LB-CHI"]
        LB3["LB-AMS"]
    end

    subgraph AppNetwork["アプリケーションネットワーク<br/>*.37signals.com"]
        subgraph Web["Webサーバー群"]
            Web1["Web (IAD)"]
            Web2["Web (CHI)"]
            Web3["Web (AMS)"]
        end

        subgraph Jobs["ジョブサーバー群"]
            Job1["Jobs (IAD)"]
        end
    end

    subgraph DBNetwork["データベースネットワーク"]
        MySQL_P["MySQL Primary"]
        MySQL_R["MySQL Replica"]
        Cache1["Cache (IAD)"]
        Cache2["Cache (CHI)"]
        Cache3["Cache (AMS)"]
    end

    subgraph StorageNetwork["ストレージネットワーク"]
        S3["PureStorage<br/>(S3 API)"]
        NFS["NFS<br/>(証明書)"]
    end

    Internet -->|"80/443"| LB1
    Internet -->|"80/443"| LB2
    Internet -->|"80/443"| LB3

    LB1 -->|"80"| Web1
    LB2 -->|"80"| Web2
    LB3 -->|"80"| Web3

    Web1 -->|"3306"| MySQL_P
    Web1 -->|"3306 (RO)"| MySQL_R
    Web1 -->|"3306"| Cache1

    Web2 -->|"3306"| MySQL_P
    Web2 -->|"3306 (RO)"| MySQL_R
    Web2 -->|"3306"| Cache2

    Web3 -->|"3306"| MySQL_P
    Web3 -->|"3306 (RO)"| MySQL_R
    Web3 -->|"3306"| Cache3

    Job1 -->|"3306"| MySQL_P

    Web1 -->|"HTTPS"| S3
    Web2 -->|"HTTPS"| S3
    Web3 -->|"HTTPS"| S3

    LB1 -->|"NFS"| NFS
    LB2 -->|"NFS"| NFS
    LB3 -->|"NFS"| NFS

    MySQL_P -.->|"Replication"| MySQL_R

    style Public fill:#ffebee
    style LoadBalancers fill:#e3f2fd
    style AppNetwork fill:#e8f5e9
    style DBNetwork fill:#fff3e0
    style StorageNetwork fill:#f3e5f5
```
