# 部署启动与数据库重建

本文记录本地开发、数据库迁移、重建库和 Ubuntu 服务器部署的常用命令。

## 数据库迁移策略

项目使用 `node-pg-migrate`，迁移目录：

```text
apps/backend/src/db/migrations/
  001_init.sql          空库基线（完整结构）
  002_xxx.sql           后续增量（示例命名）
  003_xxx.sql
  ...
```

记录表：`schema_migrations`。

| 场景 | 行为 |
| --- | --- |
| 全新空库 | 按序号执行 `001_init` → 全部增量 |
| 已有库升级 | 只执行尚未记录的增量文件 |
| 改历史迁移文件内容 | **不会**自动重跑；已应用文件禁止修改 |

约定：

1. `001_init.sql` 只作为基线；上线后结构变更不要改它。
2. 每次 schema 变更新增 `NNN_name.sql`（三位序号）。
3. 迁移与业务代码同一变更一起提交。
4. 后端启动会自动 `up`；也可用命令手动执行。

### 开发常用命令

```bash
# 查看本地文件与库内已应用记录
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate:status

# 手动执行未应用迁移
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate

# 创建下一份增量迁移模板
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate:create -- add_column_example
```

宿主机直连（`postgres` 主机名仅在 Docker 网络内有效）：

```bash
cd apps/backend
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site npm run db:migrate:status
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site npm run db:migrate
```

## 本地开发启动

首次：

```bash
cp .env.mac-docker.example .env
docker compose -f docker-compose.dev.yml up -d --build
```

日常：

```bash
docker compose -f docker-compose.dev.yml up -d
```

状态与日志：

```bash
docker compose -f docker-compose.dev.yml ps
docker compose -f docker-compose.dev.yml logs -f backend
docker compose -f docker-compose.dev.yml logs -f frontend
```

本地入口：

- 前端、后台、领取页：`http://localhost`
- 健康检查：`http://localhost/health`
- 就绪检查：`http://localhost/health/ready`

## 本地重建数据库

仅在需要清空开发数据，或本地库与迁移历史严重不一致时使用。

只重建开发库 volume：

```bash
docker compose -f docker-compose.dev.yml down
docker volume rm order_site_postgres_dev_data
docker compose -f docker-compose.dev.yml up -d --build
```

volume 名称不确定时：

```bash
docker volume ls | grep postgres_dev_data
```

删除当前 dev compose 全部 volume（会重装 node_modules volume）：

```bash
docker compose -f docker-compose.dev.yml down -v
docker compose -f docker-compose.dev.yml up -d --build
```

确认迁移记录：

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate:status
```

或：

```bash
docker compose -f docker-compose.dev.yml exec -T backend node --input-type=module -e '
const { query, closeDb } = await import("./src/db/client.ts");
try {
  const result = await query("SELECT COALESCE(filename, name) AS name FROM schema_migrations ORDER BY COALESCE(filename, name)");
  console.log(result.rows.map((row) => row.name).join("\n"));
} finally {
  await closeDb();
}
'
```

## 本地验证

```bash
docker compose -f docker-compose.dev.yml exec -T backend npm test
docker compose -f docker-compose.dev.yml exec -T backend npm run typecheck
docker compose -f docker-compose.dev.yml exec -T backend npm run build
docker compose -f docker-compose.dev.yml exec -T frontend npm run typecheck
docker compose -f docker-compose.dev.yml exec -T frontend npm run build
```

## 服务器首次部署

建议 Ubuntu + Docker Compose。

```bash
cp .env.server.example .env
```

至少配置：

```text
CADDY_SITE_ADDR
WORKER_SITE_ADDR
CLAIM_BASE_URL
POSTGRES_PASSWORD
DATABASE_URL
ADMIN_SESSION_SECRET
ADMIN_DEFAULT_USERS_JSON
```

容器内连接 Compose PostgreSQL 时，主机名用 `postgres`：

```text
DATABASE_URL=postgres://postgres:你的数据库密码@postgres:5432/order_site
```

不要写成容器内的 `127.0.0.1`（那会指向后端容器自己）。

部署：

```bash
bash deploy/ubuntu-deploy.sh
```

脚本会：检查 Docker、检查 `.env` 占位值、检查 `DATABASE_URL`、修正 `apps/backend/data` 权限、构建启动、等待健康检查、打印已应用迁移。

```bash
docker compose ps
docker compose logs -f backend
```

## 服务器日常更新

```bash
bash deploy/ubuntu-deploy.sh
```

后端启动时自动执行未应用的增量迁移，一般不必单独跑迁移。

确认：

```bash
docker compose exec -T backend node --input-type=module -e '
const { query, closeDb } = await import("./dist/db/client.js");
try {
  const result = await query("SELECT COALESCE(filename, name) AS name FROM schema_migrations ORDER BY COALESCE(filename, name)");
  console.log(result.rows.map((row) => row.name).join("\n"));
} finally {
  await closeDb();
}
'
```

## 服务器重建数据库

**会删除生产数据**。仅适合新环境、测试机或确认可丢数据的场景。

```bash
docker compose down
docker volume rm order_site_postgres_data
bash deploy/ubuntu-deploy.sh
```

或：

```bash
bash deploy/ubuntu-deploy.sh --reset-db
```

volume 名不确定时：

```bash
docker volume ls | grep postgres_data
```

不要随手：

```bash
docker compose down -v
```

这会连同 `caddy_data` / `caddy_config` 一起删掉，可能触发证书重签。

## 常见问题

### 后端一直未 ready

```bash
docker compose ps
docker compose logs --tail=120 backend
```

常见原因：

- `.env` 仍有 `change-me` 占位值
- `DATABASE_URL` 密码与已有 PostgreSQL volume 初始化密码不一致
- 容器部署里 `DATABASE_URL` 误写 `127.0.0.1`
- 某次增量迁移 SQL 失败

### 改了 `001_init.sql` 但旧库没变

已应用过的迁移不会因文件内容变更而重跑。正确做法是 **新增** `002_xxx.sql` 写增量。

仅本地可丢数据时，才用重建 volume 的方式对齐。

### 如何新增字段 / 索引

```bash
docker compose -f docker-compose.dev.yml exec -T backend \
  npm run db:migrate:create -- add_orders_note

# 编辑生成的 apps/backend/src/db/migrations/00N_add_orders_note.sql
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate
docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate:status
```

### 宿主机手动跑迁移连不上 `postgres`

`.env` 里的 `postgres` 只在 Docker 网络有效。宿主机请临时改为 `127.0.0.1` 并映射端口。
