Files
probably-rendering-one-more…/README.md
T
codex-bot 818b1894e7
PROMPT Docker CI and deployment / verify-and-deploy (push) Successful in 14m10s
Run the complete PROMPT stack and CI verification in Docker
2026-10-23 00:19:08 +08:00

110 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROMPT
仓库名:Probably Rendering One More Pixel Tonight。其余命名使用 PROMPT / `prompt`。
自己的素材与创作工作台:Next.js Pages Router、React、TypeScript、Tailwind CSS、Node.js 24。中文界面包含瀑布流、日期贡献热力图、素材导入、多媒体详情、分类管理、独立素材架与线条图形工具。没有创建作品的按钮;图文和动态作品由代码实现。
## 全 Docker 启动
本机只需 Docker Engine / Docker Desktop 和 Compose v2。Node、npm、FFmpeg、迁移程序、网站与后台处理都在镜像里。
```bash
cp .env.example .env
# 修改 .env 中的三个密码 / 密钥,不能使用示例值。
docker build --target runtime -t prompt:local .
docker compose --env-file .env up -d --wait postgres objects
docker compose --env-file .env run --rm migrate
docker compose --env-file .env up -d --wait web worker
```
访问 `http://localhost:18131`。图片与其他文件保存在 S3 对象卷,文字、分类、素材包引用和任务保存在 PostgreSQL 卷;停止、重建应用容器不会删除这些数据。
| 容器服务 | 职责 |
| --- | --- |
| `web` | Next.js 页面、API、素材上传/读取;宿主机 18131 → 容器 3000 |
| `worker` | FFmpeg 音画分离、封面与音轨处理;没有 HTTP 端口 |
| `postgres` | PostgreSQL 元数据和文字;兼容维护用回环端口 18132 |
| `objects` | RustFS 私有 S3 对象存储;兼容维护用回环端口 18133,控制台关闭 |
| `migrate` | 一次性数据库迁移与对象桶初始化,执行后退出 |
| `tests` | CI 的一次性集成测试执行器,执行后退出 |
四个常驻服务使用 `restart: unless-stopped`,Web 和 worker 以非 root 用户运行。worker 通过心跳检查存活;Web 健康检查同时验证当前版本、数据库和 S3。
## 页面与数据
- `/`:所有非空素材包与已注册代码作品,按创建时间倒序;顶部为过去一年的贡献汇总。
- `/images`、`/videos`、`/audio`:图片、视频、声音收藏。
- `/articles`、`/motion`:代码编写的图文与动态作品。
- 上述五类路径可以附加标签树路径,如 `/images/style/white-line`;父分类会包含后代分类的内容。
- `/p/<slug>`:素材包的稳定详情地址,不随标签改变。多图切换、多视频及其关联音轨、多声音均可展示。
- `/library/import`:导入同一类型的一组文件和说明,自动收为一份收藏。支持最多 16 个文件,单个 250 MB,总计 1 GB。
- `/library/assets`:查看每份独立素材及被引用次数,复制 ID 以复用。
- `/library/tags`:维护严格单父级分类树;同名 slug 只允许出现在不同分支。
- `/tools/doodle`:手绘线条造型参考,可选色、复制和下载透明 SVG。不是 AI 图片编辑器。
素材库不插入演示或占位帖子。空分类显示简洁的空状态;空素材包不进入任何瀑布流。分页游标由时间与 UUID 组成,重复时间戳下仍稳定。
详细模型见 `docs/data-model.md`。应用容器通过 Docker 网络的 `postgres:5432` 和 `objects:9000` 访问存储,不使用宿主机回环地址。浏览器通过应用访问媒体,支持 Range 分段读取。
视频原件保持不变,后台生成无声 MP4、封面,以及存在声音时的 M4A 音轨。音轨记录在 `asset_variants`,始终属于原视频;不会生成独立声音资产。后台单任务处理,使用数据库锁领取任务,失败重试三次,支持超时任务恢复。FFmpeg 禁止输入网络协议。
## 编程加入素材包与作品
`POST /api/posts` 接收 `kind`、`title`、可选 `slug`、`assets: [{id, role?}]`、`tags: [tagId]`、`text`、`coverAssetId` 和 `pageKey`。`role` 为 `content` 或 `caption`。素材和说明文字都可以通过 ID 引用已有资产;`text` 是创建新文字资产的快捷方式。引用不会复制原文件。
`POST /api/tags` 接收 `name`、`slug` 和可选 `parentId`。
图文或动态作品需要先在 `src/content/registry.tsx` 注册 React 组件与类型,再通过 API 创建引用对应 `pageKey` 的素材包。封面引用普通图片资产。动态作品的 React 组件就是画面本身,不会被强制套入视频播放器。未注册的页面不会出现在瀑布流中,也不会执行数据库中的任意路径或脚本。
当前不内置作品模板或视频导出引擎;后续一起确定设计系统和制作方案。
## 贡献记录
`contribution_events` 保存细分的 `kind`、对象类型、对象 ID、数量、发生时间、元数据和可选幂等键。显示时按上海时区汇总所有类型。当前没有将上传、分类或保存动作自动算作贡献;触发规则留待确定。没有随机或伪造热力图数据。
## CI/CD 与生产部署
`.gitea/workflows/ci.yml` 使用 `runs-on: ces-control`。依赖安装、类型检查、单元测试、生产构建、启动检查都在 Docker 构建阶段运行。集成测试启动隔离的完整容器栈,并由测试容器请求真实的非 root Web / worker 容器,验证 PostgreSQL、RustFS、上传、共享引用和音画分离。
main 上的 push 或手动运行,在全部检查通过后才发布。测试环境使用独立 Compose 项目、随机端口和随机凭据;测试结束只删除它自己的容器和卷。
生产使用固定 Compose project `prompt`,复用原有 `prompt_postgres_data` 和 `prompt_objects` 卷,以及 `/etc/prompt.env` 的凭据。由旧部署升级时,发布脚本会停用 `prompt.service`、`prompt-worker.service`,由容器接管运行;宿主机无需项目专用的 Node/FFmpeg 进程。旧发布目录留作首次迁移失败时的回退依据。
| 项目 | 值 |
| --- | --- |
| 生产运行 | Docker Compose:web、worker、postgres、objects |
| 网站端口 | `18131`,映射到 Web 容器 3000 |
| 应用镜像 | `prompt:<commit>`;回退使用上一版镜像 |
| 发布清单 | `/opt/prompt/releases/<commit>/compose.yml` 和 `release.env` |
| 当前发布 | `/opt/prompt/current` 原子软链接 |
| 密钥 | `/etc/prompt.env`,保留既有凭据,新建时随机生成;不进代码和日志 |
| 持久数据 | Docker named volumes,不随应用发布删除 |
| 数据库备份 | `/var/lib/prompt/backups`,每次发布前备份,保留最近 10 份 |
发布使用宿主机文件锁串行执行,自动跳过已落后的提交。先备份、迁移,再切换 Web / worker;新版本失败时恢复上一版容器,首次迁移失败时可恢复原先的宿主机服务。生产发布从不执行 `down -v`。对象卷需要独立快照,数据库 dump 不能代替对象备份。
在服务器上维护当前版本:
```bash
cd /opt/prompt/current
sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env ps
sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env logs --tail 100 web worker
sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env exec web node container-health.mjs
```
`GET /api/health` 返回应用版本;`GET /api/ready` 检查数据库与对象存储。
## 内网与公网访问
`172.31.212.211` 是服务器内网 IP,不能作为公网入口。Web 端口默认映射为 `0.0.0.0:18131:3000`;公网访问仍需要实例绑定公网 IP / EIP 或反向代理,并配置相应安全组和防火墙。Docker 化不会使内网 IP 自动变成公网 IP。本项目不会擅自修改云安全组或开放数据库/S3 的公网端口。
## 独立运行 CI 验证
```bash
docker build --target integration -t prompt:tests .
docker build --target runtime -t prompt:local .
PROMPT_IMAGE=prompt:local PROMPT_TEST_IMAGE=prompt:tests bash scripts/integration.sh
```
整个验证过程无需在宿主机安装 Node.js、PostgreSQL、S3 或 FFmpeg。runner 仅需 Docker Engine、Compose、Git、Bash、flock 和管理 Docker/旧服务所需的权限。