Files
2026-10-23 10:02:09 +08:00

144 lines
12 KiB
Markdown
Raw Permalink 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.
# Doodle 云端部署准备
更新时间:2026-10-22。用户已确认 `doodle_prod` 数据库准备完成;本轮未现场重新核验云端数据,未部署 API 或修改旧线上云开发链路。
下一步按 [服务端首次部署操作手册](../docs/v3.5/服务端首次部署操作手册.md) 操作。已补齐 `Dockerfile.server`、`compose.api.yaml` 和两份环境配置模板,采用本机构建 `linux/amd64` 镜像、1Panel 上传导入、复用现有 PostgreSQL 与 OpenResty 的流程。下文的早期计划与状态记录如有差异,以该手册及本段最新状态为准。
## 已确认条件
- 云平台:腾讯云;主机名 `VM-16-14-ubuntu`。
- 系统:Ubuntu 24.04,内核 `6.8.0-71-generic`,架构 x86_64;应用镜像目标为 `linux/amd64`。
- 1Panel:2.3.2。
- 用户提供的地址 `10.0.16.14` 是内网地址;公网域名还需确认实际公网 IP。
- CPU、内存、磁盘余量、现有网站、OpenResty 网络模式及端口占用尚未核查。历史文档中的“2 核 4 GB”不能视为本轮已确认。
## 环境边界
当前采用本地开发 + 单套云端业务环境;未来确有需要时再启用独立 staging,不预先常驻第二套云端系统。
| 小程序包 | 接口选择 |
| -------- | ---------------------------------------------------------- |
| develop | 默认 local,可在 Debug 页切换 local / staging / production |
| trial | 固定 production,与正式版使用同一套后端和数据库 |
| release | 固定 production |
小程序配置位于 `doodle-mini/miniprogram/config/api.ts`。按用户要求,当前三个环境地址暂时都填写本地接口,客户端会话/缓存隔离不代表服务端数据已隔离;云端验收就绪后再单独替换相应地址。
现有已发布小程序继续使用原云开发。保留全部旧云函数、预拉取模式、地址、生成/发布与定时链路。开发版跳过旧线上预拉取,体验/正式包保留原有预拉取行为;本次不关闭旧服务。
## 本次数据库迁移范围(2026-10-20 更新)
最新来源策略为:本地 `doodle_dev` 提供已整理的分类、题型、内容关联和七牛映射;CloudBase 提供最新用户、收藏、下载记录及题型真实计数。这取代此前“只导内容”和“直接全量复制本地库”的约定。
建议先在本机独立迁移库整合,再统一导入 `doodle_prod`,保留 `doodle_dev` 作为内容来源。`worksheets` 的内容/seed 与真实计数分字段合并;用户头像以线上最新绑定核验七牛映射;新后端页面配置和任务状态重新生成或初始化。完整逐表规则及依赖、身份、计数和补导处理见 [生产数据整合与导入方案](../docs/v3.5/生产数据整合与导入方案.md)。
保留正式表结构、约束、索引和真实 Prisma 迁移历史;数据库集群账号/密码及服务端运行密钥单独配置。旧 CloudBase 服务持续保留,一次快照导入不代表实时同步。当前只整理方案,尚未执行导出、整合或云端导入。
第一阶段的具体命令与试导结果见 [分类与题型首次导入操作手册](../docs/v3.5/分类与题型首次导入操作手册.md),配套 SQL 位于 `deploy/postgres/content/`。文档验证仅在本地隔离库执行,不表示云端已导入。
云端空库也可先通过 Adminer 执行 [initialize-doodle-prod.sql](./postgres/initialize-doodle-prod.sql) 初始化结构,无需先解决本机 DBX/SSH 连接。该文件由独立空库的正式迁移结果生成,含真实 Prisma 历史,不含开发业务数据;已验证恢复及 Prisma 接续兼容。按 [首次建表指南](../docs/v3.5/云端数据库首次建表指南.md) 操作,当前尚未在云端执行。
PostgreSQL 已由用户选择通过 1Panel 安装管理,2026-10-20 核查为 `postgres:18.6-alpine`,容器名 `1Panel-postgresql-RqP6`。不再启动本目录先前准备的 `compose.database.yaml` 创建第二套数据库实例;下文关于项目管理 PostgreSQL 编排的早期建议以此决策为准。
## 建议部署结构
采用“1Panel 管理入口,项目维护应用编排”的组合方式:
```text
小程序 / Web
→ HTTPS 域名
→ 现有 1Panel OpenResty(统一管理 80/443 和证书)
→ Doodle API 容器(容器内 8800)
→ 独立 PostgreSQL 容器(持久化数据卷,不发布公网端口)
预览图、字体与头像 → 现有七牛资源域名
```
API、PostgreSQL 的 Docker Compose、镜像版本、环境变量示例和备份流程保存在项目仓库;1Panel 可用于观察容器状态和管理入口,不要求将应用制作成 1Panel 商店应用,也不额外部署一套 Node.js 运行环境。
1Panel 与项目脚本不能同时维护同一份容器编排。既有服务不为本项目被替换或重装,也不另启 Nginx/Caddy 抢占 80/443。
反向代理的上游地址要依据实际网络模式确定:若 OpenResty 使用 host 网络,可访问宿主机回环地址;若使用 bridge 网络,容器内的 `127.0.0.1` 是 OpenResty 自身,应使用经过核查的共享 Docker 网络连接 API 服务。数据库只与 API 在内部网络通信。应用信任代理的地址范围也据此配置,不直接信任任意来源的转发头。
## 域名选择
以下为建议名称,尚未创建 DNS:
| 用途 | 建议域名 |
| -------- | ----------------------- |
| 未来 Web | `doodle.joeyone.cn` |
| API | `doodle-api.joeyone.cn` |
`api.doodle.joeyone.cn` 同样可以使用,名称层级不会使接口功能或 HTTPS 安全性更强。当前推荐 `doodle-api.joeyone.cn`,因为它与 Web 域名处于同一层级,也可被 `*.joeyone.cn` 覆盖(仅在已有这种证书时适用);`api.doodle.joeyone.cn` 不受该通配符覆盖,需要精确域名证书或 `*.doodle.joeyone.cn`。
用户已选择统一管理根域及一级子域名证书;2026-10-19 已通过 1Panel 签发 `joeyone.cn` + `*.joeyone.cn`,可以覆盖表中的 Web/API 域名。将来换独立品牌域名时,可以在过渡期间让新旧域名同时路由到同一 API,不立即强制重定向旧小程序的 POST/上传请求;待旧客户端退出后再安排旧域名退役。
## 证书与自动续签
用户已选择由 1Panel 统一管理 `joeyone.cn` + `*.joeyone.cn` 的泛域名证书,复用现有 ACME 与腾讯云 DNS 账户;不接入 Atlas 的 acme.sh/systemd/七牛部署任务。
2026-10-19 面板现场核验结果:
| 项目 | 结果 |
| ---------------- | ------------------------------- |
| 证书 ID | `11` |
| 主域名 | `joeyone.cn` |
| 其他域名 | `*.joeyone.cn` |
| 颁发机构 | Let's Encrypt |
| 验证方式 | DNS 账户自动验证,腾讯云DNS认证 |
| 密钥算法 | EC 256 |
| 状态 | 正常 |
| 面板显示过期时间 | `2027-01-17 16:15:52` |
| 自动续签 | 已开启,刷新后确认仍开启 |
| 备注 | joeyone.cn 泛域名共享证书 |
日志确认两个域名均验证成功、DNS-01 临时验证记录已执行清理,并于 2026-10-19 17:14:27(面板日志)返回申请成功。以上确认的是当前签发与续签开关设置,不代表未来的自动续签任务已经执行验收。
后续为 `doodle-api.joeyone.cn` 或 `doodle.joeyone.cn` 建站时,可在 HTTPS 设置中选择同一张证书。证书覆盖域名不替代 A/CNAME 解析、网站绑定和反向代理配置;实际网站证书部署完成后仍需从客户端核验。
泛域名使用 DNS 自动验证,HTTP 验证不能签发泛域名。DNS 账户权限和凭据持续有效才可自动续签,任务失败应有通知。此次未读取、导出或复制 DNS 密钥及证书私钥。
`*.joeyone.cn` 不覆盖 `api.doodle.joeyone.cn` 或 `img.atlas.joeyone.cn`。七牛和 Atlas 现有证书继续独立维护,1Panel 的续签不会自动更新七牛绑定。
参考:[1Panel 申请证书](https://docs.fit2cloud.com/1panel/user_manual/websites/certificate-create/)、[1Panel 续签证书](https://docs.fit2cloud.com/1panel/user_manual/websites/certificate-renew/)、[Let's Encrypt 验证类型](https://letsencrypt.org/docs/challenge-types/)。
## 镜像构建与交付
建议使用多阶段 Dockerfile:构建阶段安装锁定依赖、构建 contracts 和 NestJS,并生成与 Linux 运行环境匹配的 Prisma 客户端;运行阶段包含 Node.js、构建产物和运行依赖,生产启动编译后的服务。
不从 macOS 复制 `node_modules`,不把 `.env`、数据库备份、微信或七牛密钥打进镜像。数据库数据保存在独立卷中,不随应用镜像更新。数据库迁移作为独立发布步骤执行,不在每次应用重启时隐式执行。
镜像要与服务器架构匹配。服务器已确认 x86_64,因此本机构建(包括 Apple Silicon Mac)时明确选择 `linux/amd64`。版本使用发行号或 Git 提交标识,保留上一可运行版本,不只依赖 `latest`。
有两种交付方式,均可使用同一份镜像和 Compose:
### 镜像仓库
```text
本机或 CI 构建镜像 → push 私有镜像仓库 → 云服务器登录仓库 → pull 指定版本 → Compose 更新 API
```
优先核查腾讯云容器镜像服务个人版在现有账号/地域的可用性与限制,不为初期部署预先购买企业版。镜像仓库是分发镜像的存储服务,不是运行 API 的服务器;应用仍在现有 Ubuntu 主机上运行。
参考:[腾讯云个人版推送与拉取](https://cloud.tencent.com/document/product/1141/63910)。镜像地址和登录方式以账号实际控制台为准,不能把示例 namespace 当成已经创建的仓库。
### 首次离线交付
如暂不配置镜像仓库,可以本地构建后 `docker image save` 导出,使用 SSH/SCP 上传,再在云端 `docker image load` 导入,由 Compose 启动。无需将整个源码目录上传到服务器,也不要求在云端执行依赖安装与编译。
这适合首次部署或仓库网络暂不可用的情况;后续频繁发布可改为 push/pull,不改变应用内部结构。
参考:[Docker 镜像导出](https://docs.docker.com/reference/cli/docker/image/save/)、[跨平台构建](https://docs.docker.com/build/building/multi-platform/)。
## 后续配置准备顺序
1. 核查公网 IP、CPU/内存/磁盘、Docker/Compose、80/443 占用与 OpenResty 网络模式。
2. 准备 Dockerfile、`.dockerignore`、云端 Compose、运行时环境变量示例和迁移入口。
3. 准备数据库持久化、备份和恢复流程;备份副本需要保存到服务器之外。
4. 核对基础镜像及应用镜像从服务器的拉取能力,再确定仓库分发或首次离线交付。
5. 确认 API 域名并配置 DNS、1Panel 反向代理,绑定已签发的证书 ID 11,验收 HTTPS 与续签部署链路。
6. 按最新方案将本地内容与 CloudBase 最新用户业务数据整合,对账后迁入 1Panel 管理的 `doodle_prod` 并备份。
7. 完成微信服务端出口 IP 与合法域名配置,再更新小程序 production 接口地址供体验版验收。
当前已完成 1Panel 泛域名证书申请及 PostgreSQL 实例安装,尚未执行双来源数据整合与导入,也未部署 Doodle 云端应用。公网入口与云端数据库验收完成前,不将开发机的 `127.0.0.1` 地址当作可用的体验版接口。