feat: 交付官方 Docker 运行时,外观改背景图并下线自定义 CSS/JS

站点/后台分轨背景与用户列表排序一并落地;生产 CORS 改走 SITE_URL,健康检查带版本号。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-18 05:27:33 +08:00
parent 5f7193042f
commit d784b0ea7a
68 changed files with 2588 additions and 768 deletions

View File

@@ -25,6 +25,89 @@
---
## 官方运行时(用户 2026-09-18 冻结,跨会话必须延续,未开工)
管理员可在后台一键更新 **不做本期**。先做「官方运行时」:一种可替换的交付形态。运行时契约冻住后很少改;论坛功能走新镜像 / 新包。用户主路径是 Docker `pull` + `up`。有空再按下列阶段开发,未轮到的阶段不要提前做。
### 已对齐的产品结论
- **两层分开**:运行时 = Dockerfile / Compose / volume / 环境变量;应用 = Go + Next。反代不进官方 Compose,由部署方自备。用户日常更新应用,不重装运行时。
- **官方运行时 = Docker Compose 一体交付**(`web` + `api` + Postgres)。预编译包是同一目录布局的第二种皮,排在 Docker 之后。
- **真 SSR 不能扔**:Next.js 16 必须有 Node 进程,禁止 `output:'export'` 塞进 Go 当静态站。
- **必须同一 Host**:页面、`/api/`、`/api/ws`、`/uploads` 同域;`__Host-` cookie 与 WS Origin 不允许 API 另开子域。
- **数据与程序分离**:Postgres volume、`data/`(上传与 JWT 密钥)、配置(env / 挂载的 `app.ini`)一律不进镜像。
- **本地开发不动**:仓库根现有 `docker-compose.yml` 只起 Postgres,配合 `start.bat` / `cd backend && go run ./cmd/jiang13` + `frontend` `npm run dev`。官方运行时用另一份 Compose(如 `deploy/docker-compose.yml`),禁止把开发流程改成「本地也必须打应用镜像」。
- **更新方式**:Docker 用户 `docker compose pull && docker compose up -d`;启动时既有 `AutoMigrate` 即可。接受短暂停机,上线前仍禁止为双版本并存写兼容垫片。
- **明确不做**:源码机上 `git pull` + `go build` / `next build` 当官方路径;把 Docker socket 交给 Web 进程;Cloudflare Workers 拆分部署当官方运行时(可当高级可选项,不走一键更新);后台一键替换进程(等运行时契约冻住且确有非 Docker 用户再单独立项)。
### 目标拓扑(官方 Compose)
```
浏览器 ──同 Host──► 宿主机反代(Nginx/Caddy,自备)
├─ 页面 / RSC → 127.0.0.1:3000(web)
├─ /api /api/ws → 127.0.0.1:3001(api)
└─ /uploads → 127.0.0.1:3001(api)
Postgres volume ──► postgres:17
data volume ──► Go 的 dataDir(与本地 backend/data 语义一致)
```
- Go 工作目录 / `JIANG13_WORK_PATH` 对准容器内数据根,启动日志须含 `workPath` + `dataDir`。
- `DEV_MODE=false`;`JWT_SECRET`、DSN、站点 URL 走环境变量,镜像不含真实 `app.ini`。
- 健康检查:Go `/health` 与 Next `/healthz`;反代须透传 `Upgrade` / `Connection`,保留 `Host` / `Origin`。
- Compose **不**跑 Nginx/Caddy。示例配置:`deploy/nginx.example.conf`。
### 落地进度(2026-09-18)
阶段 1–3 已落地:`deploy/` 为 `web` + `api` + `postgres`,不含反代;宿主机 Nginx 示例见 `deploy/nginx.example.conf`。仓库根 `docker-compose.yml` / `start.bat` 未改。阶段 4–6 仍未做。
### 开发阶段(按序,未点名不做)
**阶段 1 — 版本与契约(开工第一步)**
- 前后端同一 semver:Go `ldflags` 注入;前端构建期写入(勿再用页脚空占位当正式版本)。
- 写死运行时契约:服务名、端口、volume 名、环境变量表、数据目录含义。契约变更视为运行时大版本,须 changelog。
- Release 产物:带 tag 的镜像 + 校验和;changelog;**最低可升级版本**(跨大版本禁止跳迁)。
**阶段 2 — 官方 Docker 运行时(主交付)**
- 多阶段 Dockerfile:编 Go 二进制、编 Next `standalone`,运行镜像不含源码与工具链。
- `deploy/docker-compose.yml`:`web` + `api` + `postgres`。反代不进 Compose,由部署方用 Nginx 等同源反代。
- volume:`pgdata`、`appdata`(映射到 Go `dataDir`)。配置只挂 env / 可选 `app.ini`。
- 首次 `up` 即迁移 + 可登录;文档只写 Compose 步骤,不要求宿主机装 Go/Node。
- 回归:同 Host cookie、WS 握手、头像 `/uploads`、重启容器数据还在。
**阶段 3 — 文档化更新(Docker 用户的官方升级)**
- 标准命令:`docker compose pull && docker compose up -d`。
- 说明:短暂停机、备份(pg dump + `appdata`)、失败则改回上一 tag。
- Compose 文件本身尽量向前兼容(新 env 有默认);真要改文件时 changelog 写「请合并 compose」,与「只 pull 应用镜像」分开。
**阶段 4 — 预编译包(可选,布局与镜像内一致)**
- 包内:`jiang13`(或 `.exe`)、Next standalone、示例配置、watchdog/supervisor。
- Windows 不能覆盖正在运行的 exe,必须靠外层 watchdog 换进程;Linux 可 `exec` 或 systemd。
- 与 Docker 共用版本号与数据目录语义;更新仍是换文件 + 重启,不是本机编译。
**阶段 5 — 后台「检查更新」(只读,非一键)**
- 仅 `owner`:当前版本、频道(稳定/测试)、changelog、最低可升级版本。
- Docker 用户展示官方 `pull && up` 说明;不支持的部署方式如实说「请按文档升级」。
- 不做下载、不做替换、不暴露 Docker socket。
**阶段 6 — 面板一键更新(明确延后,勿提前做)**
- 仅官方 Docker(updater sidecar,禁止 app 挂 docker.sock)或官方 watchdog 包。
- 站长 + CSRF + 验签 + 审计;先备份再切;健康检查失败回滚。
- 源码部署 / Workers / 用户自管 systemd:永远只显示「当前部署不支持在线更新」。
### 开工时注意
- 先改契约与 `deploy/`,不要改 `jiang13-bbs-local-dev` 的 cwd / 端口铁律。
- 镜像构建在 CI 或维护者机器;不要把 `node_modules`、`.next`、`backend/data`、真实 `app.ini` 打进 git 或镜像。
- 生产 `DEV_MODE=false`;反代必须同源。Workers 前端不是官方运行时验收范围。
---
## Next.js 16 关键约束
- params/searchParams/cookies()/headers()/draftMode() 必须 await