修改docker部署方式

This commit is contained in:
ChuNa7a committed 2026-10-17 13:13:26 +08:00
1 parent 3e7c9420fe
commit 3c6f2c0b7b
18 files changed
+323 -95

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
# ADR-006:在 Docker 内编译部署产物
## 状态与日期
已接受,2026-10-17。
## 背景
旧部署流程要求宿主机安装 Rust、C 编译工具和 Haskell Stack,先生成 `deploy/bin/`,再复制到镜像。只有 Docker 的服务器会在调用 Cargo 时失败,也容易因宿主机与运行镜像的系统库不同而产生兼容问题。
## 决定
Rust API、ChuSQL 的 Rust 存储库、Haskell 服务端与 bootstrap 均改为 Docker 多阶段构建,使用 Debian 13 系列构建和运行镜像。Astro 保持容器内构建。运行阶段只复制必要的二进制与共享库,不包含构建工具、源码和凭据。ChuSQL 不构建 Web 管理端。
依赖仍由宿主机 Git 与 Python 初始化,保留固定版本、HTTPS 回退和服务器已有 Git 配置。Docker 构建只消费已取得的源码,不挂载 SSH 私钥,也不复制 Git 元数据、宿主机编译产物或环境密码文件。
部署准备脚本调用 Compose 构建全部镜像。管理员密码哈希在不启动依赖服务的临时 API 容器中生成。宿主机不需要执行博客或数据库二进制。
## 影响
宿主机只需 Docker Engine、Compose 插件、Python 3 和 Git。首次构建仍需要足够的内存、磁盘和网络,Rust 与 GHC 编译器来自预装工具链的容器镜像,优先通过腾讯云内网注册表拉取;Cargo 与 Haskell 包仍从各自软件包源下载。Debian 与 npm 默认使用腾讯云内网源。腾讯云未列出的 Cargo/Hackage 不伪造镜像地址,Cargo 源可配置;公开验证源单独存放,不覆盖生产秘密配置。构建缓存留在 BuildKit 内;运行容器的权限、网络和持久卷规则保持原有配置。
旧 `--build-database` 参数兼容保留;默认已构建数据库。移除依赖宿主机产物的 `--no-build`、`--chusql-source` 用法。
+1
View File
@@ -9,5 +9,6 @@
| [ADR-003](0003-author-repositories-and-manifest.md) | 作者独立仓库;文本索引方案由 ADR-004 替代 |
| [ADR-004](0004-toml-multipage-staging.md) | TOML 元信息、多页正文、系统时间与索引暂存 |
| [ADR-005](0005-astro-reading-frontend.md) | Astro 前端、同源 API 与 Docker/Caddy 编排 |
| [ADR-006](0006-container-builds.md) | Docker 内编译后端与数据库,宿主机无需编译工具链 |
旧决策保留其历史背景;当前作者隔离与文章索引规则以 ADR-003 和 ADR-004 为准。
+53 -16
View File
@@ -4,13 +4,19 @@
## 构建与启动
- 部署基于 Debian 13。
- 构建与运行镜像基于 Debian 13;宿主机只需满足 Docker 运行要求。
- `scripts/deploy.sh` 会使用同一个依赖初始化脚本,自动按[依赖源顺序](development.md)进行 HTTPS 回退,再构建外部数据库与 Docker 镜像;沿用运行者现有的 Git 配置,不在项目内覆盖服务器环境。
```sh
scripts/deploy.sh
```
## 宿主机要求
宿主机只需 Docker Engine(含 BuildKit)、Docker Compose 插件、Python 3 和 Git,以及执行 Docker 命令的权限。不需要安装 Cargo、Rust、GHC、Stack、Node.js 或 C 编译工具。
Rust API、ChuSQL 存储库和 Haskell 服务端在 Docker 多阶段构建中编译,Astro 前端也在 Docker 中构建。构建工具和源码只保留在构建阶段,运行镜像仅包含应用产物及运行依赖。首次构建会拉取预装工具链的镜像并下载软件包,需要网络、足够的内存及磁盘空间;后续构建复用 Docker 缓存。
## 服务与路由
Compose 编排 Astro 前端 `web`、Rust API `api`、文章 SSH 接收 `ssh`、ChuSQL 数据库 `db` 和 Caddy。`init` 初始化持久卷,`db-init` 用于首次数据库授权。
@@ -21,40 +27,71 @@ Caddy 将 `/api/*` 转发到 `api:3001`,其余请求转发到 `web:4321`。Nod
## 腾讯云镜像
`.env.example` 默认配置 `REGISTRY_PREFIX=mirror.ccs.tencentyun.com/library/`,为 Debian、Node 与 Caddy 使用腾讯云内网 Docker 镜像。该地址仅供腾讯云内网访问,见[腾讯云官方说明](https://cloud.tencent.com/document/practice/1207/45596)。
`.env.example` 默认配置 `REGISTRY_PREFIX=mirror.ccs.tencentyun.com/library/`,为 Rust、Debian、Node 与 Caddy 使用腾讯云内网 Docker 镜像。该地址仅供腾讯云内网访问,见[腾讯云官方说明](https://cloud.tencent.com/document/practice/1207/45596)。
在腾讯云内网部署时保留该值;其他环境将 `REGISTRY_PREFIX` 留空以使用原始镜像名,或改为可访问且受信的镜像前缀。项目不修改宿主机 Docker 配置、不关闭 TLS,也不重启 Docker 守护进程。
镜像注册表与 Debian 软件包源是不同配置。`REGISTRY_PREFIX` 控制基础镜像和 Caddy,`DEBIAN_MIRROR` 控制容器构建时的 apt 源。
镜像注册表与软件包源分别配置:
| 配置 | 默认值与用途 |
| --- | --- |
| `REGISTRY_PREFIX` | `mirror.ccs.tencentyun.com/library/`,用于 Rust、GHC/Haskell、Debian、Node 与 Caddy 镜像 |
| `DEBIAN_MIRROR` | `mirrors.tencentyun.com`,容器内 Debian 软件包源,保留 Debian 签名校验 |
| `NPM_REGISTRY` | `https://mirrors.tencentyun.com/npm/`,前端依赖源 |
| `CARGO_MIRROR_INDEX` | 默认 `sparse+https://rsproxy.cn/index/`;显式留空可使用 crates.io |
腾讯云的[公开软件源目录](https://mirrors.tencent.com/)没有列出 Cargo 与 Hackage 镜像,因此不拼接未经确认的腾讯云地址。Cargo 使用 [RsProxy](https://rsproxy.cn/) 等可配置外部源;Haskell 包沿用 Stack 默认配置。腾讯云的[软件源说明](https://cloud.tencent.com/document/product/213/8623)区分了公网和内网域名。
Rust 工具链直接来自 Rust 镜像;GHC 9.10.3 和 Stack 来自匹配 ChuSQL resolver 的 Haskell 镜像。构建时禁止 Stack 再下载 GHC,也不调用 rustup 安装或更新编译器。编译仍在 Debian 13 中进行。
### 使用外网源验证
项目提供不含密码的 `deploy/sources.public.env`,使用公开 ECR Docker Library 镜像、USTC Debian 源、官方 npm 源及 RsProxy Cargo 源。外网构建与隔离联调时运行:
```sh
python3 scripts/prepare-deploy.py --sources-env-file deploy/sources.public.env
python3 scripts/smoke.py --key-type rsa \
--sources-env-file deploy/sources.public.env
```
第二份配置只覆盖下载来源,不改写 `.env` 的域名、口令等生产设置。Docker Compose 会优先使用当前 shell 中已导出的同名环境变量;切换测试配置前须检查这些覆盖。公网源连通性不能证明腾讯云内网镜像可用,内网源仍需在腾讯云服务器验证。
## 首次部署
先按[开发与依赖](development.md)初始化子模块,再执行以下同架构构建步骤。使用 `scripts/deploy.sh` 时,也须先准备 `.env`。
在项目根目录执行。先按[开发与依赖](development.md)初始化子模块,再准备配置和构建镜像:
```sh
# ChuSQL 尚未编译时,先按其项目说明构建 Rust 存储库、server 与 bootstrap。
python3 scripts/prepare-deploy.py --build-database
cp .env.example .env
chmod 600 .env
# 从标准输入输入管理员口令,Ctrl-D 结束;不要把明文写进命令行历史。
./deploy/bin/chublog-api hash-password
# 将输出以单引号包裹写入 .env 的 ADMIN_PASSWORD_HASH;同时配置域名、镜像前缀及两份不同的随机 DB 口令。
docker compose --env-file .env -f deploy/compose.yaml up -d --build
# 编辑 .env,配置域名、镜像前缀及两份不同的随机 DB 口令。
python3 scripts/prepare-deploy.py
# 在临时容器内生成管理员密码哈希;不启动其他服务。
# 输入口令后按 Ctrl-D 结束,不要把明文写进命令行历史。
docker compose --env-file .env -f deploy/compose.yaml \
run --rm --no-deps -T api hash-password
# 将输出以单引号包裹写入 .env 的 ADMIN_PASSWORD_HASH。
docker compose --env-file .env -f deploy/compose.yaml up -d --no-build
# db 启动就绪后,创建 chublog 库和非超级用户 chublog_index;失败时检查日志后重试。
docker compose --env-file .env -f deploy/compose.yaml run --rm db-init
```
后续部署可运行 `scripts/deploy.sh`,自动初始化依赖、在 Docker 内构建并启动服务。
部署入口启动服务后,首次仍需执行上面的 `db-init` 命令;入口不会在数据库启动竞态中静默吞掉初始化错误。
## 构建选项与平台
构建时若 Debian 官方下载源较慢,可在 `.env` 配置 `DEBIAN_MIRROR=mirrors.ustc.edu.cn`,仍使用 Debian 签名校验。
需要切换默认腾讯云内网 Debian 包源时,可在 `.env` 配置 `DEBIAN_MIRROR=mirrors.ustc.edu.cn`,仍使用 Debian 签名校验。
- `prepare-deploy.py` 默认从数据库子模块读取编译产物;`--build-database` 会先构建其 Rust 存储库、Haskell server 和 bootstrap。
- 也可用 `--chusql-source /已有构建的/ChuSQL` 选择已有外部构建,没有产物会明确失败。
- 编译产物只暂存在被忽略的 `deploy/bin/`。
- 跨平台部署须先在目标 Debian/架构构建,不能复制 macOS、Windows 或其他架构二进制。
- 镜像不含编译器、源码、`.env` 或密码文件。
- `prepare-deploy.py` 调用 Compose 构建全部应用镜像,不执行宿主机编译、不生成 `deploy/bin/`。
- `--build-database` 保留为兼容参数;数据库始终在 Docker 中构建。旧的 `--no-build` 和 `--chusql-source` 不再支持。
- `--sources-env-file PATH` 可追加只含下载源配置的 Compose 环境文件;优先级高于第一份环境文件。
- `--env-file PATH` 可选择配置文件;默认读取项目 `.env`,不存在时读取 `.env.example`(仅用于构建,不用于生产启动)。
- 外部依赖仍由宿主机 `init-deps.py` 初始化,沿用现有 Git 配置;构建过程不将 SSH 私钥或 Git 凭据复制到镜像。
- GHC 工具链镜像支持 amd64、arm64;更新 ChuSQL resolver 时,须同步核对 GHC 镜像版本与 Dockerfile 中的复制路径。
- 镜像默认按 Docker 主机架构构建,不复用宿主机已有二进制;构建与运行阶段均使用 Debian 13 系列镜像。
- Cargo、Stack 软件包缓存保存在 Docker BuildKit 中。镜像前缀控制编译器镜像来源,Cargo 与 Haskell 包下载独立于镜像注册表。
- 运行镜像不含编译器、源码、`.env` 或密码文件。
## 管理员初始化
+12 -4
View File
@@ -59,12 +59,20 @@ cargo clippy --all-targets -- -D warnings
## 联调
部署镜像在 Docker 内编译,不需要宿主机 Rust 或 Haskell 工具链;运行上面的源码开发检查时仍须自行安装 Rust。准备脚本的轻量回归检查:
```sh
python3 scripts/prepare-deploy.py --build-database
python3 scripts/smoke.py
python3 scripts/smoke.py --key-type rsa
python3 scripts/test-prepare-deploy.py
```
```sh
python3 scripts/prepare-deploy.py --sources-env-file deploy/sources.public.env
python3 scripts/smoke.py --sources-env-file deploy/sources.public.env
python3 scripts/smoke.py --key-type rsa \
--sources-env-file deploy/sources.public.env
# 安装 Python Playwright 和 Chromium 后,可追加前端真实浏览器验证。
python3 scripts/smoke.py --key-type rsa --browser-test
python3 scripts/smoke.py --key-type rsa --browser-test \
--sources-env-file deploy/sources.public.env
```
- 联调使用独立随机命名的 Compose 项目、本机 18080/18443/12222 端口,测试结束清理自己创建的容器与卷。
+3 -2
View File
@@ -47,12 +47,13 @@ Markdown 禁用原始 HTML,并在渲染后清理输出。文章内链接只映
## 浏览器检查
浏览器联调需要 Python Playwright 及 Chromium:
以下检查用于开发电脑,需要 Python Playwright 及 Chromium;生产部署无需安装这些工具:
```sh
python3 -m pip install playwright
python3 -m playwright install chromium
python3 scripts/smoke.py --key-type rsa --browser-test
python3 scripts/smoke.py --key-type rsa --browser-test \
--sources-env-file deploy/sources.public.env
```
该命令使用隔离的 Docker 项目,验证真实注册登录、密码修改、公钥保存、站长授权、多页阅读及手机布局,测试后清理自己创建的容器与卷。截图默认放在 `/tmp/chublog-web-screenshots`。系统缺少浏览器库时,按 Playwright 安装说明准备运行环境。