HH-772: add executable deployment guide (#11)

This commit is contained in:
2026-08-28 13:00:40 +08:00
parent 829521f5bc
commit fa36eeb09b
2 changed files with 242 additions and 1 deletions
+6 -1
View File
@@ -13,7 +13,7 @@ services:
security_opt: [no-new-privileges:true]
depends_on:
docker-gateway:
condition: service_started
condition: service_healthy
postgres:
condition: service_healthy
networks: [control]
@@ -51,6 +51,11 @@ services:
- /var/run/docker.sock:/var/run/docker.sock:ro
group_add:
- "${DOCKER_GID:-999}"
healthcheck:
test: [CMD, wget, -q, -O, /dev/null, http://127.0.0.1:8081/healthz]
interval: 2s
timeout: 2s
retries: 15
read_only: true
tmpfs:
- /tmp:size=16m,noexec,nosuid,nodev
+236
View File
@@ -0,0 +1,236 @@
# CreatorHub 部署
本文档适用于当前阶段 A:在一台可信 Linux 主机上通过 Docker Compose 部署,且仅允许本机单用户访问。当前控制面没有认证或 CSRF 防护,PostgreSQL 使用仅限内部网络的 `trust` 认证;不要将服务反向代理到公网或共享网络。
## 部署内容
`compose.yaml` 会启动以下服务:
- `creator-hub`:Go 1.26 控制面,同时提供 React 19/Vite 8 构建的静态页面;
- `docker-gateway`:受限 Docker API 网关,是唯一挂载 `/var/run/docker.sock` 的服务;
- `postgres`PostgreSQL 17,数据保存在 `creatorhub_postgres` 命名卷;
- 浏览器容器:由网关按需创建,使用固定摘要的指纹浏览器镜像,Profile 保存在 `creatorhub-profile-<运行时名称>` 命名卷。
控制面只发布到 `127.0.0.1`。Compose 的 `creatorhub_control` 网络和网关创建的 `creatorhub_browser` 网络均为内部网络;阶段 A 的浏览器容器默认不能访问外网,也不能互相通信。
`creator-hub` 会等待 `docker-gateway` 健康检查通过后再启动。
## 前置条件
- Linux 主机;
- Docker Engine 26 或兼容版本;
- Docker Compose v2
- 当前用户可访问 Docker daemon
- 可访问 `git.ipao.vip`,并已完成私有镜像仓库登录(如仓库要求认证);
- `curl`,用于部署后检查。
在仓库根目录执行预检:
```bash
test -S /var/run/docker.sock
docker info >/dev/null
docker compose version
docker compose config --quiet
```
## 首次部署
以下命令应在同一个 shell、仓库根目录执行。`DOCKER_GID` 必须与宿主机 Docker socket 的组一致;`CREATORHUB_PORT` 仅控制本机监听端口。
```bash
export DOCKER_GID="$(stat -c '%g' /var/run/docker.sock)"
export CREATORHUB_PORT=8080
docker pull git.ipao.vip/rogee/fingerprint-chromium@sha256:b9f23b8e3ac640174db0dfa49e9095fe7eb06f5db55a4e7550d979b35ff3a1b7
docker compose config --quiet
docker compose up --detach --build
```
控制面启动时会连接 PostgreSQL,并在事务和 advisory lock 保护下自动执行前向迁移。迁移失败时控制面会退出,由 Compose 按 `restart: unless-stopped` 重启;先检查日志,不要删除数据卷。
## 部署验证
```bash
curl --fail --silent --show-error \
--retry 30 --retry-delay 2 --retry-connrefused \
--output /dev/null "http://127.0.0.1:${CREATORHUB_PORT}/healthz"
curl --fail --silent --show-error \
--retry 30 --retry-delay 2 --retry-connrefused \
"http://127.0.0.1:${CREATORHUB_PORT}/api/browsers" >/dev/null
docker compose exec -T postgres \
psql -U creatorhub -d creatorhub -tAc \
'SELECT 1 FROM schema_migration WHERE version = 1;' \
| grep -qx 1
docker compose ps
```
健康检查应成功,浏览器列表接口应返回 JSON,迁移查询当前应输出 `1`,三个 Compose 服务应为运行状态。然后访问 <http://127.0.0.1:8080>;修改过 `CREATORHUB_PORT` 时使用对应端口。
排障时读取结构化服务日志:
```bash
docker compose logs --tail=200 creator-hub docker-gateway postgres
```
## 配置
Compose 部署时通常只需设置以下宿主机变量:
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `CREATORHUB_PORT` | `8080` | 映射到 `127.0.0.1` 的控制面端口 |
| `DOCKER_GID` | `999` | Docker socket 的宿主机组 ID;必须按实际值设置 |
服务本身支持并校验以下环境变量;`compose.yaml` 已提供当前部署所需的值:
| 服务 | 变量 | 当前 Compose 值 |
| --- | --- | --- |
| `creator-hub` | `LISTEN_ADDR` | 默认 `:8080` |
| `creator-hub` | `DOCKER_GATEWAY_URL` | `http://docker-gateway:8081` |
| `creator-hub` | `WEB_DIR` | 镜像内固定为 `/app/web` |
| `creator-hub` | `DATABASE_URL` | `postgres://creatorhub@postgres/creatorhub?sslmode=disable` |
| `creator-hub` | `LOG_LEVEL` | 默认 `info` |
| `docker-gateway` | `LISTEN_ADDR` | 默认 `:8081` |
| `docker-gateway` | `DOCKER_SOCKET` | 默认值和 Compose 挂载均固定为 `/var/run/docker.sock`;不能只覆盖环境变量 |
| `docker-gateway` | `BROWSER_NETWORK` | `creatorhub_browser` |
| `docker-gateway` | `LOG_LEVEL` | 默认 `info` |
不要把凭据写入仓库或 Compose 文件。共享或生产部署必须先补充认证、CSRF 防护和独立 Docker daemon/VM(或 Docker authorization plugin),并将 PostgreSQL 改为强认证。
## 更新与回滚
更新前记录当前版本并备份数据库:
```bash
set -Eeuo pipefail
git rev-parse HEAD
umask 077
export BACKUP_FILE="$(pwd)/creatorhub-$(date +%Y%m%d-%H%M%S).dump"
docker compose exec -T postgres \
pg_dump -U creatorhub -d creatorhub --format=custom \
> "$BACKUP_FILE"
test -s "$BACKUP_FILE"
docker compose exec -T postgres pg_restore --list \
< "$BACKUP_FILE" >/dev/null
```
拉取已审核版本后,重新执行部署和验证:
```bash
set -Eeuo pipefail
git pull --ff-only
export DOCKER_GID="$(stat -c '%g' /var/run/docker.sock)"
export CREATORHUB_PORT=8080
docker pull git.ipao.vip/rogee/fingerprint-chromium@sha256:b9f23b8e3ac640174db0dfa49e9095fe7eb06f5db55a4e7550d979b35ff3a1b7
docker compose config --quiet
docker compose up --detach --build
```
数据库迁移只支持安全前进,不提供自动破坏性回滚。需要同时恢复旧代码和更新前数据库时,修改下面两个变量后**整块执行一次**;不要逐行或拆块执行。预检、恢复演练、动态容器回收、停服、主库恢复、提交切换和启动都位于同一个 fail-fast subshell 中。
```bash
(
set -Eeuo pipefail
BACKUP_FILE=/absolute/path/to/creatorhub-YYYYmmdd-HHMMSS.dump
RESTORE_REV=PREVIOUS_REVIEWED_COMMIT_SHA
: "${BACKUP_FILE:?set BACKUP_FILE to the absolute archive path}"
: "${RESTORE_REV:?set RESTORE_REV to the previous reviewed commit SHA}"
test -r "$BACKUP_FILE"
test -s "$BACKUP_FILE"
git cat-file -e "${RESTORE_REV}^{commit}"
docker compose exec -T postgres pg_restore --list \
< "$BACKUP_FILE" >/dev/null
docker compose exec -T postgres \
dropdb --if-exists --force -U creatorhub creatorhub_restore_check
docker compose exec -T postgres \
createdb -U creatorhub creatorhub_restore_check
docker compose exec -T postgres \
pg_restore -U creatorhub -d creatorhub_restore_check \
--exit-on-error --no-owner --no-privileges \
< "$BACKUP_FILE"
docker compose exec -T postgres \
psql -U creatorhub -d creatorhub_restore_check -v ON_ERROR_STOP=1 -tAc \
'SELECT 1 FROM schema_migration WHERE version = 1;' \
| grep -qx 1
docker compose exec -T postgres \
dropdb --force -U creatorhub creatorhub_restore_check
docker ps --all --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id' \
| xargs --no-run-if-empty docker rm --force
docker compose stop creator-hub docker-gateway
umask 077
PRE_ROLLBACK_BACKUP="$(pwd)/creatorhub-pre-rollback-$(date +%Y%m%d-%H%M%S).dump"
docker compose exec -T postgres \
pg_dump -U creatorhub -d creatorhub --format=custom \
> "$PRE_ROLLBACK_BACKUP"
test -s "$PRE_ROLLBACK_BACKUP"
docker compose exec -T postgres pg_restore --list \
< "$PRE_ROLLBACK_BACKUP" >/dev/null
test -r "$BACKUP_FILE"
test -s "$BACKUP_FILE"
git cat-file -e "${RESTORE_REV}^{commit}"
docker compose exec -T postgres pg_restore --list \
< "$BACKUP_FILE" >/dev/null
docker compose exec -T postgres \
dropdb --if-exists --force -U creatorhub creatorhub
docker compose exec -T postgres createdb -U creatorhub creatorhub
docker compose exec -T postgres \
pg_restore -U creatorhub -d creatorhub \
--exit-on-error --no-owner --no-privileges \
< "$BACKUP_FILE"
docker compose exec -T postgres \
psql -U creatorhub -d creatorhub -v ON_ERROR_STOP=1 -tAc \
'SELECT 1 FROM schema_migration WHERE version = 1;' \
| grep -qx 1
git switch --detach "$RESTORE_REV"
if ! docker compose up --detach --build; then
docker compose stop creator-hub docker-gateway || true
exit 1
fi
)
```
任何命令失败时 subshell 立即退出;若失败发生在主库 `dropdb` 之后,应用保持停止。`docker compose up` 自身失败时也会显式停回应用服务。成功后重新执行“部署验证”。不要直接删除数据卷或手工改写迁移记录。
## 停止与数据保留
`docker compose stop/down` 不管理网关动态创建的浏览器容器;直接执行会留下运行中的浏览器和活动会话。先严格按固定容器名前缀及两个管理标签筛选并回收,命令不带 `--volumes`,因此 Profile 卷仍会保留:
```bash
docker ps --all --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id' \
| xargs --no-run-if-empty docker rm --force
test -z "$(docker ps --all --quiet \
--filter 'name=^creatorhub-browser-' \
--filter 'label=io.creatorhub.managed=true' \
--filter 'label=io.creatorhub.runtime-id')"
docker compose stop
```
恢复服务使用 `docker compose up --detach`。需要删除服务容器和网络但保留数据时使用:
```bash
docker compose down
```
不要执行 `docker compose down --volumes`:它会删除 PostgreSQL 数据卷。浏览器 Profile 卷不属于 Compose 声明卷,删除浏览器容器或执行 `docker compose down` 时仍会保留;可用以下命令核对:
```bash
docker volume ls --filter name=creatorhub-profile-
```
`docker.sock` 即使以只读文件方式挂载,也仍允许 Docker API 写操作,等价于宿主机 root 权限。完整安全边界、API 契约和失败语义见[《浏览器容器控制面》](architecture/container-control.md)。