# 🚀 部署文档

## 目录

- [快速开始](#快速开始)
- [2.4.1 Mock 模式](#241-mock-模式)
- [2.4.2 Dev 模式](#242-dev-模式)
- [2.4.3 Up 模式](#243-up-模式)
- [环境变量配置](#环境变量配置)
- [故障排查](#故障排查)

---

## 快速开始

### 三种部署模式

| 模式 | 命令 | Backend | 数据库 | 热重载 | 适用场景 |
|------|------|---------|--------|--------|----------|
| **Mock** | `make mock` | 本地 | 内存 | ✅ | 快速开发、API 测试 |
| **Dev** | `make db-up`<br>`make dev` | 本地 | Docker | ✅ | 日常开发 ⭐ 推荐 |
| **Up** | `make up` | Docker | Docker | ❌ | 集成测试、生产预演 |

### 使用 Makefile

```bash
# 查看所有命令
make help

# Mock 模式（零依赖，最快启动）
make mock

# Dev 模式（推荐日常开发）
make db-up   # 启动数据库
make dev     # 启动 Backend（热重载）

# Up 模式（完全容器化）
make up

# 管理服务
make logs    # 查看日志
make stop    # 停止服务
```

### 验证服务

```bash
# 健康检查
curl http://localhost:8080/health

# 测试 API
curl http://localhost:8080/api/v1/registries | jq

# 访问 Swagger UI
open http://localhost:8080/api/docs
```

---

# 2.4.1 Mock 模式

## 概述

Mock 模式使用内存存储，无需任何外部依赖，适合快速开发和测试。

**特点**:
- ✅ **零依赖** - 无需数据库、Docker 等
- ✅ **快速启动** - 3 秒内启动
- ✅ **热重载** - 支持 Air 自动重载
- ✅ **自带测试数据** - Bootstrap 预注入
- ✅ **无需容器** - 本地直接运行
- ❌ **数据不持久** - 重启后数据丢失

**适用场景**:
- 🚀 快速功能开发
- 🧪 API 接口测试
- 🎨 前端开发联调
- 📝 编写单元测试

**架构**:

```
┌─────────────────────────────────────────┐
│     Mock 模式（本地直接运行）            │
│                                         │
│  ┌──────────────────────────────────┐  │
│  │   OCDP Backend (Go Process)      │  │
│  │   Port: 8080                     │  │
│  │                                  │  │
│  │   ┌─────────────────────────┐   │  │
│  │   │  Air (Hot Reload)       │   │  │
│  │   │  监听文件变化自动重载     │   │  │
│  │   └─────────────────────────┘   │  │
│  │                                  │  │
│  │   Adapter: Mock                 │  │
│  │   Storage: Memory               │  │
│  └──────────────────────────────────┘  │
│                                         │
│  无外部依赖 ✨                          │
└─────────────────────────────────────────┘
```

---

## 环境准备

```bash
# 1. 确保已安装 Go
go version  # 需要 Go 1.21+

# 2. 安装 Air（热重载工具）
go install github.com/air-verse/air@latest

# 3. 验证安装
air -v
```

---

## 运行方式

### 方式 1: 使用 Makefile（推荐）

```bash
make mock
```

### 方式 2: 使用 Air

```bash
# 1. 设置环境变量
export ADAPTER_MODE=mock
export PORT=8080
export JWT_SECRET=dev-secret-key

# 2. 启动 Air
air -c .air.toml

# 输出示例:
#   __    _   ___
#  / /\  | | | |_)
# /_/--\ |_| |_| \_ v1.49.0
# 
# watching .
# building...
# running...
# 🚀 Starting OCDP Backend (mode=mock)
# 🌐 Server starting on :8080
```

### 方式 3: 直接运行 Go

```bash
# 设置环境变量
export ADAPTER_MODE=mock
export PORT=8080
export JWT_SECRET=dev-secret-key

# 运行
go run cmd/api/main.go
```

---

## 热重载演示

修改任何 `.go` 文件后，Air 会自动检测并重启：

```
main.go has changed
building...
running...
🚀 Starting OCDP Backend (mode=mock)
🌐 Server starting on :8080
```

**支持的文件类型**:
- `.go` - Go 源文件
- `.yaml`, `.json` - 配置文件
- `.toml` - Air 配置文件

---

## 配置文件

Air 配置文件 `.air.toml` 已包含在项目中：

```toml
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
  cmd = "go build -o ./tmp/main cmd/api/main.go"
  bin = "./tmp/main"
  include_ext = ["go", "tpl", "tmpl", "html", "yaml", "json"]
  exclude_dir = ["assets", "tmp", "vendor", "testdata"]
  exclude_regex = ["_test.go"]
  delay = 1000
```

---

## 测试数据

Mock 模式自动加载 `config/bootstrap.json` 中的测试数据：

```json
{
  "enabled": true,
  "users": [
    {
      "username": "admin",
      "password": "admin123",
      "email": "admin@example.com"
    }
  ],
  "registries": [
    {
      "name": "Harbor Production",
      "url": "https://harbor.example.com",
      "username": "admin",
      "password": "secret"
    }
  ],
  "clusters": [
    {
      "name": "Production Cluster",
      "host": "https://k8s.example.com:6443",
      "description": "生产环境集群"
    }
  ]
}
```

---

## 测试 API

```bash
# 登录
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}' | jq

# 响应:
# {
#   "accessToken": "eyJhbGciOiJIUzI1NiIs...",
#   "userId": "user-123",
#   "username": "admin"
# }

# 查看 Registries
curl http://localhost:8080/api/v1/registries | jq

# 查看 Clusters
curl http://localhost:8080/api/v1/clusters | jq
```

---

## 环境变量

| 变量 | 说明 | 默认值 | 必需 |
|------|------|--------|------|
| `ADAPTER_MODE` | 适配器模式 | `mock` | ✅ |
| `PORT` | 服务端口 | `8080` | ❌ |
| `JWT_SECRET` | JWT 密钥 | - | ✅ |

---

## 优势与限制

### ✅ 优势

1. **启动极快** - 3 秒内启动，无需等待数据库
2. **零配置** - 无需配置数据库连接、证书等
3. **自带数据** - Bootstrap 自动注入测试数据
4. **热重载** - 代码修改立即生效
5. **易于调试** - 本地运行，支持 IDE 断点调试
6. **完美测试** - 适合 API 测试和前端联调

### ❌ 限制

1. **数据不持久** - 重启后数据丢失
2. **功能简化** - 某些功能（如真实 K8s 操作）被模拟
3. **不适合生产** - 仅用于开发调试

---

# 2.4.2 Dev 模式

## 概述

Dev 模式使用 Docker 运行 PostgreSQL 数据库，Backend 在本地热重载运行，适合日常开发。

**特点**:
- ✅ **隔离的依赖服务** - 数据库在容器中，避免污染本地环境
- ✅ **本地热重载** - Backend 支持 Air 自动重载
- ✅ **完整的 IDE 支持** - 断点调试、代码补全、性能分析
- ✅ **快速迭代** - 代码修改立即生效，无需重新构建镜像
- ✅ **数据持久化** - PostgreSQL 数据持久保存
- ✅ **最佳开发体验** - 兼顾隔离性和开发效率

**适用场景**:
- 📝 **日常功能开发** ⭐ 最推荐
- 🐛 **代码调试** - 支持 IDE 断点
- 🔄 **快速迭代** - 热重载提升效率
- 🧪 **数据持久化测试** - 验证数据库操作

**架构**:

```
┌──────────────────────────────────────────────────────────┐
│       Dev 模式（部分容器化，推荐日常开发）                 │
│                                                          │
│  ┌────────────────────────┐    ┌────────────────────┐  │
│  │  OCDP Backend          │    │   PostgreSQL       │  │
│  │  (本地进程)             │───▶│   (Docker 容器)     │  │
│  │  Port: 8080            │    │   Port: 5432       │  │
│  │                        │    │                    │  │
│  │  ┌─────────────────┐  │    │  Volume:           │  │
│  │  │  Air (Hot Reload) │  │    │  postgres_data     │  │
│  │  └─────────────────┘  │    └────────────────────┘  │
│  └────────────────────────┘                            │
│                                                          │
│  Backend: 本地运行（热重载）                              │
│  Database: Docker 容器（隔离环境）                        │
└──────────────────────────────────────────────────────────┘
```

---

## 环境准备

```bash
# 1. 确保已安装 Docker 和 Docker Compose
docker --version
docker compose version

# 2. 安装 Air（热重载工具）
go install github.com/air-verse/air@latest

# 3. 验证安装
air -v
```

---

## 运行步骤

### 步骤 1: 启动数据库

```bash
# 使用 Makefile（推荐）
make db-up

# 或手动启动
docker compose up -d postgres

# 等待数据库启动（查看健康状态）
docker compose ps

# 预期输出:
# NAME              IMAGE                  STATUS                    PORTS
# ocdp-postgres     postgres:17-alpine     Up 10s (healthy)          0.0.0.0:5432->5432/tcp
```

**验证数据库连接**:

```bash
# 方式 1: 使用 psql
psql -h localhost -U postgres -d ocdp

# 方式 2: 使用 Docker
docker exec -it ocdp-postgres psql -U postgres -d ocdp

# 测试查询
SELECT current_database();
\q
```

---

### 步骤 2: 启动 Backend（热重载）

**选项 A: 使用 Makefile（推荐）**

```bash
# 设置环境变量（首次）
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable"
export ENCRYPTION_KEY="12345678901234567890123456789012"

# 启动 Backend
make dev

# 输出:
# 🚀 启动 Dev 模式 - Backend（本地热重载）...
# 🔌 Connecting to database...
# ✅ Database connected
# 🌱 Bootstrap seeding...
# 🌐 Server starting on :8080
```

**选项 B: 使用 Air**

```bash
# 设置环境变量
export ADAPTER_MODE=production
export PORT=8080
export JWT_SECRET=dev-secret-key
export ENCRYPTION_KEY=12345678901234567890123456789012
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable"

# 启动 Air
air -c .air.toml
```

**选项 C: 直接运行 Go**

```bash
export ADAPTER_MODE=production
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable"
export JWT_SECRET=dev-secret-key
export ENCRYPTION_KEY=12345678901234567890123456789012

go run cmd/api/main.go
```

---

## 验证服务

```bash
# 健康检查
curl http://localhost:8080/health
# 输出: {"status":"healthy"}

# 注册用户
curl -X POST http://localhost:8080/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "username": "testuser",
    "password": "test123",
    "email": "test@example.com"
  }'

# 登录
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "testuser",
    "password": "test123"
  }' | jq
```

---

## 热重载演示

修改代码后，Air 会自动检测并重启：

```bash
# 终端 1: Air 运行中
# 修改文件: internal/domain/service/cluster_service.go

# Air 输出:
# cluster_service.go has changed
# building...
# running...
# 🚀 Starting OCDP Backend (mode=production)
# 🔌 Connecting to database...
# ✅ Database connected
# 🌐 Server starting on :8080

# 终端 2: 测试
curl http://localhost:8080/api/v1/clusters | jq
```

---

## 开发工作流

```bash
# 1. 启动数据库（首次或停止后）
make db-up

# 2. 启动 Backend（热重载）
make dev

# 3. 修改代码
vim internal/domain/service/cluster_service.go
# Air 自动检测并重启

# 4. 测试 API
curl http://localhost:8080/api/v1/clusters | jq

# 5. 查看数据库
make db
SELECT * FROM users;
\q

# 6. 停止服务
# - Backend: Ctrl+C
# - Database: make stop
```

---

## 管理服务

**查看服务状态**:

```bash
# 查看所有容器
docker compose ps

# 查看 PostgreSQL 日志
docker compose logs -f postgres

# 查看 Backend 日志（在 Air 终端中）
```

**停止服务**:

```bash
# 停止 Backend: 在 Air 终端按 Ctrl+C

# 停止数据库
docker compose stop postgres

# 停止并删除容器（数据保留）
docker compose down

# 停止并删除容器和数据卷（⚠️ 数据丢失）
docker compose down -v
```

**重启服务**:

```bash
# 重启数据库
docker compose restart postgres

# 重启 Backend: 在 Air 终端按 Ctrl+C 后重新运行 make dev
```

---

## 数据库管理

**连接数据库**:

```bash
# 使用 Makefile
make db

# 使用 psql
psql -h localhost -U postgres -d ocdp

# 或使用 Docker
docker exec -it ocdp-postgres psql -U postgres -d ocdp
```

**常用查询**:

```sql
-- 查看所有表
\dt

-- 查看用户
SELECT id, username, email, created_at FROM users;

-- 查看 Registry
SELECT id, name, url, created_at FROM registries;

-- 查看集群
SELECT id, name, host, created_at FROM clusters;

-- 清空测试数据
TRUNCATE users, registries, clusters, instances CASCADE;

-- 退出
\q
```

**数据库备份与恢复**:

```bash
# 备份
docker exec ocdp-postgres pg_dump -U postgres ocdp > backup-$(date +%Y%m%d).sql

# 恢复
docker exec -i ocdp-postgres psql -U postgres ocdp < backup.sql

# 压缩备份
docker exec ocdp-postgres pg_dump -U postgres ocdp | gzip > backup.sql.gz

# 从压缩文件恢复
gunzip -c backup.sql.gz | docker exec -i ocdp-postgres psql -U postgres ocdp
```

---

## IDE 调试配置

### VS Code (launch.json)

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch OCDP Backend (Dev Mode)",
      "type": "go",
      "request": "launch",
      "mode": "auto",
      "program": "${workspaceFolder}/cmd/api/main.go",
      "env": {
        "ADAPTER_MODE": "production",
        "PORT": "8080",
        "JWT_SECRET": "dev-secret-key",
        "ENCRYPTION_KEY": "12345678901234567890123456789012",
        "DATABASE_URL": "postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable"
      },
      "args": []
    }
  ]
}
```

### GoLand / IntelliJ IDEA

1. Run → Edit Configurations
2. Add New → Go Build
3. 配置：
   - **Files**: `cmd/api/main.go`
   - **Working directory**: 项目根目录
   - **Environment**:
     ```
     ADAPTER_MODE=production
     PORT=8080
     JWT_SECRET=dev-secret-key
     ENCRYPTION_KEY=12345678901234567890123456789012
     DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable
     ```

---

## 环境变量

| 变量 | 说明 | 示例 | 必需 |
|------|------|------|------|
| `ADAPTER_MODE` | 适配器模式 | `production` | ✅ |
| `PORT` | 服务端口 | `8080` | ❌ |
| `JWT_SECRET` | JWT 密钥 | `dev-secret` | ✅ |
| `ENCRYPTION_KEY` | 加密密钥（32字节） | `12345678901234567890123456789012` | ✅ |
| `DATABASE_URL` | 数据库连接 | `postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable` | ✅ |

**生成密钥**:

```bash
# JWT Secret
openssl rand -base64 32

# Encryption Key（32 字节）
openssl rand -base64 32
```

---

## 故障排查

**问题 1: 数据库连接失败**

```bash
# 错误: connection refused

# 检查数据库是否启动
docker compose ps postgres

# 检查端口
netstat -tuln | grep 5432
# 或
lsof -i :5432

# 测试连接
psql -h localhost -U postgres -d ocdp -c "SELECT 1;"
```

**问题 2: 数据库未初始化**

```bash
# 重新初始化数据库
docker compose down postgres
docker compose up -d postgres

# 等待健康检查通过
docker compose ps postgres
```

**问题 3: 端口冲突**

```bash
# 修改 docker-compose.yml 中的端口映射
# ports:
#   - "5433:5432"  # 使用 5433 而不是 5432

# 更新 DATABASE_URL
export DATABASE_URL="postgresql://postgres:postgres@localhost:5433/ocdp?sslmode=disable"
```

---

# 2.4.3 Up 模式

## 概述

Up 模式使用 Docker Compose 完全容器化部署，PostgreSQL 和 Backend 都在容器中运行。

**特点**:
- ✅ **完全容器化** - 一致的运行环境
- ✅ **一键部署** - 简单快速
- ✅ **接近生产** - 与生产环境高度一致
- ✅ **易于分享** - 团队成员快速启动相同环境
- ❌ **无热重载** - 代码修改需重新构建镜像
- ❌ **调试受限** - 需要通过日志调试

**适用场景**:
- 🧪 **集成测试** - 测试完整系统
- 🎯 **生产预演** - 验证部署流程
- 👥 **团队协作** - 快速搭建统一环境
- 📦 **交付演示** - 向客户展示系统

**架构**:

```
┌──────────────────────────────────────────────────────────┐
│           Up 模式（完全容器化）                           │
│                                                          │
│  ┌────────────────────────────────────────────────────┐ │
│  │         Docker Compose Network                     │ │
│  │                                                    │ │
│  │  ┌──────────────────┐    ┌──────────────────┐   │ │
│  │  │  OCDP Backend    │    │   PostgreSQL     │   │ │
│  │  │  (Docker 容器)    │───▶│   (Docker 容器)   │   │ │
│  │  │  Port: 8080      │    │   Port: 5432     │   │ │
│  │  └──────────────────┘    └──────────────────┘   │ │
│  │                                                    │ │
│  └────────────────────────────────────────────────────┘ │
│                                                          │
│  ┌────────────────────────────────────────────────────┐ │
│  │         Persistent Volumes                         │ │
│  │         postgres_data: /var/lib/postgresql/data    │ │
│  └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```

---

## 环境准备

```bash
# 确保已安装 Docker 和 Docker Compose
docker --version
docker compose version
```

---

## 目录结构

```
backend/
├── docker-compose.yml       # Docker Compose 配置
├── Dockerfile              # Backend 镜像
├── .env                    # 环境变量
├── env.example             # 环境变量示例
└── config/
    └── bootstrap.json      # 初始数据（可选）
```

---

## 部署步骤

### 步骤 1: 准备环境变量

```bash
# 复制示例文件
cp env.example .env

# 编辑环境变量
nano .env
```

**.env 文件内容**:

```bash
# 适配器模式
ADAPTER_MODE=production

# 端口配置
BACKEND_PORT=8080
POSTGRES_PORT=5432

# 安全密钥（⚠️ 生产环境必须修改）
JWT_SECRET=your-jwt-secret-change-in-production
ENCRYPTION_KEY=your-32-character-encryption-key-here

# 数据库配置
POSTGRES_DB=ocdp
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your-postgres-password-change-it

# 数据库连接 URL（容器内部使用）
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
```

**生成安全密钥**:

```bash
# 生成随机 JWT Secret
openssl rand -base64 32

# 生成随机 Encryption Key（32 字节）
openssl rand -base64 32

# 生成随机数据库密码
openssl rand -base64 16
```

---

### 步骤 2: 启动服务

**使用 Makefile（推荐）**:

```bash
make up

# 查看服务状态
docker compose ps

# 预期输出:
# NAME              IMAGE                  STATUS              PORTS
# ocdp-backend      backend:latest         Up 30s (healthy)    0.0.0.0:8080->8080/tcp
# ocdp-postgres     postgres:17-alpine     Up 40s (healthy)    0.0.0.0:5432->5432/tcp
```

**手动启动**:

```bash
# 使用 profile 启动完整服务
docker compose --profile backend up -d

# 查看日志
docker compose logs -f backend postgres
```

---

### 步骤 3: 验证部署

```bash
# 健康检查
curl http://localhost:8080/health
# 输出: {"status":"healthy"}

# 测试 API
curl http://localhost:8080/api/v1/registries | jq

# 访问 Swagger UI
open http://localhost:8080/api/docs

# 查看容器状态
docker compose ps

# 进入 Backend 容器
docker compose exec backend sh

# 连接数据库
make db
```

---

## 管理服务

**停止服务**:

```bash
# 停止所有服务
make stop

# 或
docker compose down

# 停止并删除数据卷（⚠️ 会删除数据）
docker compose down -v

# 仅停止 Backend
docker compose stop backend
```

**重启服务**:

```bash
# 重启所有服务
make restart

# 或
docker compose restart

# 重启 Backend
docker compose restart backend

# 重启数据库
docker compose restart postgres
```

**查看日志**:

```bash
# 查看所有日志
make logs

# 或
docker compose logs -f

# 查看 Backend 日志
docker compose logs -f backend

# 查看最近 100 行
docker compose logs --tail=100 backend
```

---

## 重新构建镜像

**代码修改后需要重新构建**:

```bash
# 方式 1: 使用 Makefile
make up-build

# 方式 2: 手动构建
docker compose build backend
docker compose --profile backend up -d

# 方式 3: 强制重新构建（不使用缓存）
make up-rebuild

# 或
docker compose build --no-cache backend
docker compose --profile backend up -d
```

---

## 数据备份和恢复

```bash
# 备份数据库
docker compose exec postgres pg_dump -U postgres ocdp > backup-$(date +%Y%m%d).sql

# 恢复数据库
docker compose exec -T postgres psql -U postgres ocdp < backup.sql

# 导出为压缩文件
docker compose exec postgres pg_dump -U postgres ocdp | gzip > backup-$(date +%Y%m%d).sql.gz

# 从压缩文件恢复
gunzip -c backup.sql.gz | docker compose exec -T postgres psql -U postgres ocdp
```

---

## docker-compose.yml 配置

```yaml
version: '3.8'

services:
  # PostgreSQL 数据库
  postgres:
    image: postgres:17-alpine
    container_name: ocdp-postgres
    environment:
      - POSTGRES_DB=${POSTGRES_DB:-ocdp}
      - POSTGRES_USER=${POSTGRES_USER:-postgres}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    ports:
      - "${POSTGRES_PORT:-5432}:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ${INIT_DB_SQL_PATH:-./scripts/init-db.sql}:/docker-entrypoint-initdb.d/01-init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-ocdp}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - ocdp-network

  # Backend 服务（需要 --profile backend 才启动）
  backend:
    profiles: ["backend"]
    build:
      context: .
      dockerfile: Dockerfile
    container_name: ocdp-backend
    ports:
      - "${BACKEND_PORT:-8080}:8080"
    environment:
      - ADAPTER_MODE=${ADAPTER_MODE:-production}
      - PORT=8080
      - JWT_SECRET=${JWT_SECRET}
      - ENCRYPTION_KEY=${ENCRYPTION_KEY}
      - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
    depends_on:
      postgres:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - ocdp-network
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s

networks:
  ocdp-network:
    driver: bridge

volumes:
  postgres_data:
    driver: local
```

> 💡 **提示**  
> 如果与仓库根目录下的 `docker-compose.yml` 联合使用（例如通过 `docker compose -f docker-compose.yml -f backend/docker-compose.yml --profile backend ...`），请确保设置环境变量 `INIT_DB_SQL_PATH=./backend/scripts/init-db.sql`（或绝对路径），以便 PostgreSQL 容器挂载到正确的初始化脚本。

---

## Dockerfile 配置

```dockerfile
# 多阶段构建，优化镜像大小

# 构建阶段
FROM golang:1.21-alpine AS builder

WORKDIR /app

# 复制依赖文件
COPY go.mod go.sum ./
RUN go mod download

# 复制源代码
COPY . .

# 编译（静态链接）
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w -s' -o ocdp-backend cmd/api/main.go

# 运行阶段
FROM alpine:latest

# 安装 CA 证书
RUN apk --no-cache add ca-certificates tzdata wget

# 设置时区
ENV TZ=Asia/Shanghai

WORKDIR /root/

# 复制二进制文件
COPY --from=builder /app/ocdp-backend .

# 复制配置文件（如果有）
COPY config/ config/

# 暴露端口
EXPOSE 8080

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

# 运行
CMD ["./ocdp-backend"]
```

---

## 环境变量

| 变量 | 说明 | 示例 | 必需 |
|------|------|------|------|
| `ADAPTER_MODE` | 适配器模式 | `production` | ✅ |
| `BACKEND_PORT` | Backend 端口 | `8080` | ❌ |
| `POSTGRES_PORT` | PostgreSQL 端口 | `5432` | ❌ |
| `JWT_SECRET` | JWT 密钥 | `随机字符串` | ✅ |
| `ENCRYPTION_KEY` | 加密密钥（32字节） | `随机字符串` | ✅ |
| `POSTGRES_DB` | 数据库名 | `ocdp` | ✅ |
| `POSTGRES_USER` | 数据库用户 | `postgres` | ✅ |
| `POSTGRES_PASSWORD` | 数据库密码 | `随机字符串` | ✅ |
| `DATABASE_URL` | 数据库连接 | `postgresql://...` | ✅ |

---

## 故障排查

**问题 1: Backend 容器无法启动**

```bash
# 查看容器日志
docker compose logs backend

# 查看容器状态
docker compose ps

# 重新构建镜像
docker compose build --no-cache backend
docker compose --profile backend up -d
```

**问题 2: 数据库连接失败**

```bash
# 检查数据库健康状态
docker compose exec postgres pg_isready -U postgres

# 查看数据库日志
docker compose logs postgres

# 检查网络连接
docker compose exec backend ping postgres

# 等待数据库完全启动后重启 Backend
sleep 10
docker compose restart backend
```

**问题 3: 端口冲突**

```bash
# 修改 .env 文件中的端口
BACKEND_PORT=8081
POSTGRES_PORT=5433

# 重新启动
docker compose down
docker compose --profile backend up -d
```

**问题 4: 完全重置**

```bash
# 停止所有服务
docker compose down

# 删除数据卷（⚠️ 会删除数据）
docker compose down -v

# 清理 Docker 系统
docker system prune -a --volumes

# 重新部署
make up
```

---

# 环境变量配置

## 环境变量对比

| 变量 | Mock | Dev | Up | 说明 |
|------|------|-----|-----|------|
| `ADAPTER_MODE` | `mock` | `production` | `production` | 适配器模式 |
| `PORT` | `8080` | `8080` | `8080` | 服务端口 |
| `JWT_SECRET` | 简单值 | 开发值 | 强随机值 | JWT 密钥 |
| `ENCRYPTION_KEY` | - | 开发值 | 强随机值 | 加密密钥 |
| `DATABASE_URL` | - | 本地 PostgreSQL | 容器内 PostgreSQL | 数据库连接 |

---

## 模式对比

| 特性 | Mock | Dev | Up |
|------|------|-----|-----|
| **Backend 运行位置** | 本地进程 | 本地进程 | Docker 容器 |
| **依赖服务** | 无 | Docker (PostgreSQL) | Docker (PostgreSQL) |
| **热重载** | ✅ Air | ✅ Air | ❌ 需重新构建 |
| **数据库** | ❌ 内存 | ✅ PostgreSQL | ✅ PostgreSQL |
| **数据持久化** | ❌ | ✅ | ✅ |
| **启动时间** | 3 秒 | 5-8 秒 | 15-30 秒 |
| **调试能力** | ✅ IDE 断点 | ✅ IDE 断点 | ⚠️ 日志调试 |
| **适用场景** | 快速开发、API 测试 | 日常开发 ⭐ 推荐 | 集成测试、生产预演 |
| **环境隔离** | ✅ 完全隔离 | ⚠️ 部分隔离 | ✅ 完全隔离 |
| **生产一致性** | ❌ 低 | ⚠️ 中 | ✅ 高 |

---

## 推荐使用场景

### 🚀 Mock 模式
- ✅ 快速功能开发
- ✅ API 接口测试
- ✅ 前端联调
- ✅ 单元测试

### ⭐ Dev 模式（推荐日常开发）
- ✅ 日常功能开发
- ✅ 代码调试
- ✅ 数据持久化测试
- ✅ 快速迭代

### 🎯 Up 模式
- ✅ 集成测试
- ✅ 生产环境预演
- ✅ 团队协作环境搭建
- ✅ 交付演示

---

# 故障排查

## 通用问题

### 1. 端口被占用

```bash
# 查找占用端口的进程
lsof -i :8080
# 或
netstat -tuln | grep 8080

# 关闭进程
kill -9 <PID>

# 或使用其他端口
export PORT=8081
```

### 2. Go 环境问题

```bash
# 检查 Go 版本
go version  # 需要 Go 1.21+

# 更新 Go 模块
go mod download
go mod tidy

# 清理 Go 缓存
go clean -cache -modcache
```

### 3. Air 找不到命令

```bash
# 确保 GOPATH/bin 在 PATH 中
export PATH=$PATH:$(go env GOPATH)/bin

# 重新安装 Air
go install github.com/air-verse/air@latest

# 验证安装
air -v
```

---

## Mock 模式问题

### 1. 服务无法启动

```bash
# 检查环境变量
echo $ADAPTER_MODE  # 应该是 mock
echo $PORT          # 应该是 8080
echo $JWT_SECRET    # 不应为空

# 手动运行查看详细错误
export ADAPTER_MODE=mock
export JWT_SECRET=test-secret
go run cmd/api/main.go
```

### 2. Bootstrap 数据未加载

```bash
# 检查 bootstrap.json 文件
cat config/bootstrap.json

# 确保 enabled 为 true
# {
#   "enabled": true,
#   ...
# }
```

---

## Dev 模式问题

### 1. 数据库连接失败

```bash
# 检查 PostgreSQL 是否运行
docker compose ps postgres

# 检查端口
lsof -i :5432

# 测试连接
psql -h localhost -U postgres -d ocdp -c "SELECT 1;"

# 重启数据库
docker compose restart postgres
```

### 2. 数据库未初始化

```bash
# 重新初始化数据库
docker compose down postgres
docker compose up -d postgres

# 等待健康检查通过
docker compose ps postgres
```

### 3. Air 热重载失败

```bash
# 清理临时文件
rm -rf tmp/

# 重新启动 Air
air -c .air.toml

# 检查 .air.toml 配置
cat .air.toml
```

---

## Up 模式问题

### 1. Backend 容器无法启动

```bash
# 查看容器日志
docker compose logs backend

# 查看容器状态
docker compose ps

# 重新构建镜像
make up-rebuild
```

### 2. 镜像构建失败

```bash
# 清理 Docker 缓存
docker builder prune -a

# 重新构建
docker compose build --no-cache backend

# 检查 Dockerfile
cat Dockerfile
```

### 3. 容器健康检查失败

```bash
# 查看容器日志
docker compose logs backend

# 手动执行健康检查
docker compose exec backend wget --no-verbose --tries=1 --spider http://localhost:8080/health

# 检查 healthcheck 配置
docker compose config | grep -A 5 healthcheck
```

---

## 数据库问题

### 1. 数据库连接超时

```bash
# 检查数据库是否启动完成
docker compose ps postgres

# 查看数据库日志
docker compose logs postgres

# 手动测试连接
docker compose exec postgres pg_isready -U postgres

# 等待更长时间
sleep 10
docker compose restart backend
```

### 2. 数据丢失

```bash
# 检查数据卷
docker volume ls | grep postgres

# 备份当前数据
docker compose exec postgres pg_dump -U postgres ocdp > backup.sql

# 恢复数据
docker compose exec -T postgres psql -U postgres ocdp < backup.sql
```

### 3. 权限问题

```bash
# 检查数据卷权限
docker volume inspect ocdp_postgres_data

# 重新创建数据卷
docker compose down -v
docker compose up -d postgres
```

---

## 健康检查

```bash
# 服务健康检查
curl http://localhost:8080/health
# 预期: {"status":"healthy"}

# 数据库健康检查
# Docker 方式
docker compose exec postgres pg_isready -U postgres

# 本地方式
pg_isready -h localhost -p 5432 -U postgres

# 检查所有服务状态
docker compose ps
```

---

## 资源监控

```bash
# 查看容器资源使用
docker stats

# 查看磁盘使用
docker system df

# 查看日志大小
du -sh $(docker inspect --format='{{.LogPath}}' ocdp-backend)
du -sh $(docker inspect --format='{{.LogPath}}' ocdp-postgres)

# 清理 Docker 资源
docker system prune -a --volumes
```

---

## 完全重置

### Mock 模式

```bash
# 清理临时文件
rm -rf tmp/

# 重新启动
make mock
```

### Dev 模式

```bash
# 停止服务
docker compose down

# 删除数据卷（⚠️ 数据丢失）
docker compose down -v

# 重新启动
make db-up
make dev
```

### Up 模式

```bash
# 停止所有服务
docker compose down

# 删除数据卷（⚠️ 数据丢失）
docker compose down -v

# 清理 Docker 系统
docker system prune -a --volumes

# 重新部署
make up
```

---

## 服务访问地址

| 服务 | Mock | Dev | Up | 说明 |
|------|------|-----|-----|------|
| **Backend API** | http://localhost:8080/api/v1 | http://localhost:8080/api/v1 | http://localhost:8080/api/v1 | REST API |
| **Health Check** | http://localhost:8080/health | http://localhost:8080/health | http://localhost:8080/health | 健康检查 |
| **Swagger UI** | http://localhost:8080/api/docs | http://localhost:8080/api/docs | http://localhost:8080/api/docs | API 文档 |
| **PostgreSQL** | - | localhost:5432 | localhost:5432 | 数据库 |

---

## 相关文档

- [架构文档](architecture.md) - 六边形架构、技术选型
- [API 与测试](api-and-test.md) - API 文档、测试指南
- [主 README](../README.md) - 项目概览

---

**Last Updated**: 2025-11-09  
**Version**: v3.0.0
