# 生产部署说明

目标访问地址：

```text
https://hfb.221329.cc.cd
```

生产部署使用 Caddy 作为公网入口，只暴露宿主机 `80`、`443` 端口。Caddy 会自动申请和续签 HTTPS 证书，并直接托管前端静态资源（前端 `dist` 在构建 Caddy 镜像时打入）；后端、MySQL、Redis、MinIO 均通过 Docker 内网通信。

部署前请确认：

- 域名 A 记录已解析到服务器公网 IP。
- 服务器安全组或防火墙已放行 `80/tcp` 和 `443/tcp`。
- 服务器上没有其他服务占用 `80`、`443`。
- 国内服务器如需对外访问，请先确认域名备案和云厂商限制。

## 1. 准备环境变量

```bash
cp backend/.env.prod.example backend/.env
```

编辑 `backend/.env`，至少替换以下占位值：

```text
CADDY_DOMAIN
CADDY_EMAIL
MYSQL_ROOT_PASSWORD
MYSQL_PASSWORD
MYSQL_DSN
JWT_SECRET
MINIO_ROOT_USER
MINIO_ROOT_PASSWORD
STORAGE_ACCESS_KEY_ID
STORAGE_SECRET_ACCESS_KEY
```

如果正式对外运营，还需要配置真实短信和实名服务，避免继续使用测试配置。

## 2. 一键部署

```bash
./scripts/deploy-prod.sh
```

脚本会自动完成：

- 检查 `backend/.env` 是否仍指向 `127.0.0.1`、`localhost` 或占位值。
- 使用内置 MinIO 时，检查 `STORAGE_ACCESS_KEY_ID` / `STORAGE_SECRET_ACCESS_KEY` 是否和 `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` 一致。
- 构建并启动生产容器。
- 通过 Caddy 自动申请或续签 HTTPS 证书。
- 等待 MySQL、Redis、MinIO 就绪。
- 按顺序执行尚未应用的数据库迁移。
- 重启后端并检查 `https://你的域名/api/health`。

如需部署完成后直接跟随查看后端日志：

```bash
./scripts/deploy-prod.sh --logs
```

后端运行日志会同时输出到 Docker 控制台，并写入宿主机：

```text
backend/logs/app-YYYY-MM-DD.log
```

测试阶段需要清空并重建数据库时：

```bash
./scripts/deploy-prod.sh --reset-db
```

## 3. 手动启动服务

```bash
set -a
source backend/.env
set +a
docker compose -f deploy/docker-compose.prod.yml up -d --build
```

手动执行 `docker compose` 时需要先导出 `CADDY_DOMAIN` 和 `CADDY_EMAIL`，否则 Caddy 无法读取证书域名配置。优先推荐使用一键部署脚本，它会自动从 `backend/.env` 导出这两个变量。

## 4. 手动执行数据库迁移

通常直接使用一键部署脚本即可。确实需要手动迁移时，使用后端镜像内置的 goose：

```bash
MYSQL_DSN="$(awk -F= '$1=="MYSQL_DSN"{sub(/^[^=]*=/,""); print; exit}' backend/.env)"
case "$MYSQL_DSN" in
  *multiStatements=*) GOOSE_DSN="$MYSQL_DSN" ;;
  *\?*) GOOSE_DSN="${MYSQL_DSN}&multiStatements=true" ;;
  *) GOOSE_DSN="${MYSQL_DSN}?multiStatements=true" ;;
esac

docker compose -f deploy/docker-compose.prod.yml run --rm --no-deps backend \
  /app/goose -dir /app/migrations mysql "$GOOSE_DSN" up
```

## 5. 验证

```bash
curl https://你的域名/health
curl https://你的域名/api/health
```

浏览器访问：

```text
https://你的域名
https://你的域名/你配置的后台入口/login
```

Caddy 证书和 ACME 账号数据保存在 Docker 卷 `caddy_data`、`caddy_config` 中。不要随意删除这两个卷，否则 Caddy 会重新申请证书，频繁重建可能触发证书签发频率限制。
