Files
creator-hub/docs/deployment.md
T

12 KiB
Raw Blame History

CreatorHub 部署

本文档适用于当前阶段 A:在一台 Linux 主机上通过 Docker Compose 部署。控制面使用单用户 HTTP Basic Auth;当前不提供 RBAC 或多租户隔离。

部署内容

compose.yaml 会启动以下服务:

  • creator-hub:Go 1.26 控制面,同时提供 React 19/Vite 8 构建的静态页面;
  • docker-gateway:受限 Docker API 网关,是唯一挂载 /var/run/docker.sock 的服务;
  • postgresPostgreSQL 17,数据保存在 creatorhub_postgres 命名卷;
  • 浏览器容器:由网关按需创建,镜像引用由平台「镜像版本」页配置(缺失时网关自动拉取),Profile 保存在 creatorhub-profile-<别名> 命名卷。

控制面发布到宿主机所有网卡,局域网内可直接访问;浏览器容器可访问外网。 creator-hub 会等待 docker-gateway 健康检查通过后再启动。

前置条件

  • Linux 主机;
  • Docker Engine 26 或兼容版本;
  • Docker Compose v2
  • 当前用户可访问 Docker daemon
  • 可访问镜像仓库(如 git.ipao.vip),并已完成登录(如仓库要求认证);镜像也可不在宿主机预拉取,网关会在缺失时按引用自动拉取;
  • curl,用于部署后检查。

在仓库根目录执行预检:

test -S /var/run/docker.sock
docker info >/dev/null
docker compose version
: "${CONTROL_PLANE_USERNAME:?set CONTROL_PLANE_USERNAME or fill .env}"
: "${CONTROL_PLANE_PASSWORD:?set CONTROL_PLANE_PASSWORD or fill .env}"
docker compose config --quiet

首次部署

以下命令应在同一个 shell、仓库根目录执行。DOCKER_GID 必须与宿主机 Docker socket 的组一致;CREATORHUB_PORT 控制控制面的宿主机端口。

export DOCKER_GID="$(stat -c '%g' /var/run/docker.sock)"
export CREATORHUB_PORT=8080
export GATEWAY_TOKEN="$(openssl rand -hex 24)"   # 亦可在 .env 中设置
export CONTROL_PLANE_USERNAME=creatorhub
export CONTROL_PLANE_PASSWORD="$(openssl rand -hex 24)"

docker compose config --quiet
docker compose up --detach --build

控制面启动时会连接 PostgreSQL,并在事务和 advisory lock 保护下自动执行前向迁移。迁移失败时控制面会退出,由 Compose 按 restart: unless-stopped 重启;先检查日志,不要删除数据卷。

首次配置

服务起来后打开 http://127.0.0.1:${CREATORHUB_PORT}

  1. 「网关管理」页注册网关:名称如 gw-mainEndpoint http://docker-gateway:8081,令牌填 GATEWAY_TOKEN 的值(即 openssl rand -hex 24 生成的值)。
  2. 「镜像版本」页添加可用镜像,如版本 148.0.7778.215、引用 git.ipao.vip/rogee/fingerprint-chromium:148.0.7778.215(或 @sha256: 摘要引用)。
  3. 「运行环境」页创建环境:中文名 + 小写别名 + 指纹参数,容器名 creatorhub-browser-<别名>Profile 卷 creatorhub-profile-<别名>

部署验证

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 \
  --user "${CONTROL_PLANE_USERNAME}:${CONTROL_PLANE_PASSWORD}" \
  "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 = 12;' \
  | grep -qx 1

docker compose ps

健康检查应成功,浏览器列表接口应返回 JSON,迁移查询当前应输出 1,三个 Compose 服务应为运行状态。然后访问 http://127.0.0.1:8080;修改过 CREATORHUB_PORT 时使用对应端口。

排障时读取结构化服务日志:

docker compose logs --tail=200 creator-hub docker-gateway postgres

配置

Compose 部署时通常只需设置以下宿主机变量:

变量 默认值 说明
CREATORHUB_PORT 8080 控制面宿主机端口,局域网可访问
DOCKER_GID 999 Docker socket 的宿主机组 ID;必须按实际值设置
GATEWAY_TOKEN dev-creatorhub-gateway-token 网关与控制面共享的 Bearer 令牌;生产须改为随机值,并同步填入网关注册表单
CONTROL_PLANE_USERNAME 无(必填) 控制面唯一用户;不能包含冒号
CONTROL_PLANE_PASSWORD 无(必填) 控制面密码,至少 16 字节;使用随机值

服务本身支持并校验以下环境变量;compose.yaml 会在控制面凭据缺失或为空时拒绝渲染:

服务 变量 当前 Compose 值
creator-hub LISTEN_ADDR 默认 :8080
creator-hub WEB_DIR 镜像内固定为 /app/web
creator-hub DATABASE_URL postgres://creatorhub@postgres/creatorhub?sslmode=disable
creator-hub LOG_LEVEL 默认 info
creator-hub CONTROL_PLANE_USERNAME 必填;HTTP Basic Auth 用户名
creator-hub CONTROL_PLANE_PASSWORD 必填且至少 16 字节;不会写入日志或响应
docker-gateway LISTEN_ADDR 默认 :8081
docker-gateway DOCKER_SOCKET 默认值和 Compose 挂载均固定为 /var/run/docker.sock;不能只覆盖环境变量
docker-gateway BROWSER_NETWORK creatorhub_browser
docker-gateway GATEWAY_TOKEN 与平台注册值一致,长度 ≥16/v1 全部接口校验 Bearer 令牌
docker-gateway LOG_LEVEL 默认 info

不要把凭据写入仓库或 Compose 文件。

P0-lite 停机通知

当前只使用 creator-hub 的专用 Logrus JSON logger 作为通知渠道;它固定输出警告,不继承业务 LOG_LEVEL。选择它是因为 Compose 已可靠收集服务日志,不需要新增外部账号、凭据、网络重试或通知依赖。仅 policy_holdneeds_confirmation 会产生 operator attention required,字段限定为 event_typereason_code、账号/任务 ID;不会包含请求头、Secret 引用或凭据值。运维可用下列命令接入现有日志采集或人工查看:

docker compose logs creator-hub | grep 'operator attention required'

该渠道是单实例 P0-lite 能力,不保证外部送达、升级或确认回执;只有出现明确的多渠道/送达需求时才增加 webhook 或消息平台。

更新与回滚

更新前记录当前版本并备份数据库:

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

拉取已审核版本后,重新执行部署和验证:

set -Eeuo pipefail
git pull --ff-only
export DOCKER_GID="$(stat -c '%g' /var/run/docker.sock)"
export CREATORHUB_PORT=8080
docker compose config --quiet
docker compose up --detach --build

镜像版本升级在页面「运行环境 → 升级」完成:平台会停止并删除旧容器(保留 Profile 卷),用新镜像引用与原指纹参数重建后启动;失败时直接重试即可,无需回滚。

数据库迁移只支持安全前进,不提供自动破坏性回滚。需要同时恢复旧代码和更新前数据库时,修改下面两个变量后整块执行一次;不要逐行或拆块执行。预检、恢复演练、动态容器停止、停服、主库恢复、提交切换和启动都位于同一个 fail-fast subshell 中。

(
  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 = 12;' \
    | grep -qx 1
  docker compose exec -T postgres \
    dropdb --force -U creatorhub creatorhub_restore_check

  list_running_browsers() {
    docker ps --quiet \
      --filter 'name=^creatorhub-browser-' \
      --filter 'label=io.creatorhub.managed=true' \
      --filter 'label=io.creatorhub.runtime-id'
  }

  browser_ids="$(list_running_browsers)" || exit 1
  for browser_id in $browser_ids; do
    if ! docker stop "$browser_id"; then
      docker rm --force "$browser_id"
    fi
  done

  browser_ids="$(list_running_browsers)" || exit 1
  test -z "$browser_ids"
  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 = 12;' \
    | 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 卷仍会保留:

set -Eeuo pipefail

list_running_browsers() {
  docker ps --quiet \
    --filter 'name=^creatorhub-browser-' \
    --filter 'label=io.creatorhub.managed=true' \
    --filter 'label=io.creatorhub.runtime-id'
}

browser_ids="$(list_running_browsers)" || exit 1
for browser_id in $browser_ids; do
  if ! docker stop "$browser_id"; then
    docker rm --force "$browser_id"
  fi
done

browser_ids="$(list_running_browsers)" || exit 1
test -z "$browser_ids"

docker compose stop

恢复服务使用 docker compose up --detach。需要删除服务容器和网络但保留数据时使用:

docker compose down

不要执行 docker compose down --volumes:它会删除 PostgreSQL 数据卷。浏览器 Profile 卷不属于 Compose 声明卷,删除浏览器容器或执行 docker compose down 时仍会保留;可用以下命令核对:

docker volume ls --filter name=creatorhub-profile-

docker.sock 即使以只读文件方式挂载,也仍允许 Docker API 写操作,等价于宿主机 root 权限。完整安全边界、API 契约和失败语义见《浏览器容器控制面》