feat: add compose deployment baseline
This commit is contained in:
8
Makefile
8
Makefile
@@ -1,6 +1,6 @@
|
|||||||
GO ?= go
|
GO ?= go
|
||||||
|
|
||||||
.PHONY: fmt test vet build image integration console-e2e mysql-replication mysql-compatibility sdk-check protocol-check docs-check schedule-backlog release-manifest release-local-check
|
.PHONY: fmt test vet build image integration console-e2e compose-check mysql-replication mysql-compatibility sdk-check protocol-check docs-check schedule-backlog release-manifest release-local-check
|
||||||
fmt:
|
fmt:
|
||||||
$(GO) fmt ./...
|
$(GO) fmt ./...
|
||||||
cd sdk/go && $(GO) fmt ./...
|
cd sdk/go && $(GO) fmt ./...
|
||||||
@@ -35,6 +35,12 @@ integration:
|
|||||||
console-e2e:
|
console-e2e:
|
||||||
./scripts/test-console-e2e.sh
|
./scripts/test-console-e2e.sh
|
||||||
|
|
||||||
|
compose-check:
|
||||||
|
@test -n "$${ORBIT_DB_USER:-}" || (echo 'ORBIT_DB_USER is required' >&2; exit 1)
|
||||||
|
@test -n "$${ORBIT_DB_PASSWORD:-}" || (echo 'ORBIT_DB_PASSWORD is required' >&2; exit 1)
|
||||||
|
@test -n "$${ORBIT_DB_ROOT_PASSWORD:-}" || (echo 'ORBIT_DB_ROOT_PASSWORD is required' >&2; exit 1)
|
||||||
|
@docker compose -f deploy/docker-compose.yml config >/dev/null
|
||||||
|
|
||||||
mysql-replication:
|
mysql-replication:
|
||||||
./scripts/test-mysql-replication.sh
|
./scripts/test-mysql-replication.sh
|
||||||
|
|
||||||
|
|||||||
95
deploy/docker-compose.yml
Normal file
95
deploy/docker-compose.yml
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
name: orbit
|
||||||
|
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.4
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: ${ORBIT_DB_NAME:-orbit}
|
||||||
|
MYSQL_USER: ${ORBIT_DB_USER:?ORBIT_DB_USER is required}
|
||||||
|
MYSQL_PASSWORD: ${ORBIT_DB_PASSWORD:?ORBIT_DB_PASSWORD is required}
|
||||||
|
MYSQL_ROOT_PASSWORD: ${ORBIT_DB_ROOT_PASSWORD:?ORBIT_DB_ROOT_PASSWORD is required}
|
||||||
|
volumes:
|
||||||
|
- orbit-mysql:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
- CMD-SHELL
|
||||||
|
- MYSQL_PWD="$${MYSQL_ROOT_PASSWORD}" mysqladmin ping -h 127.0.0.1 -uroot --silent
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 30
|
||||||
|
start_period: 20s
|
||||||
|
|
||||||
|
migrate:
|
||||||
|
image: ${ORBIT_IMAGE:-orbit:dev}
|
||||||
|
restart: "no"
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
entrypoint: ["/usr/local/bin/orbit-migrate"]
|
||||||
|
command: ["up"]
|
||||||
|
environment:
|
||||||
|
ORBIT_MYSQL_DSN: "root:${ORBIT_DB_ROOT_PASSWORD}@tcp(mysql:3306)/${ORBIT_DB_NAME:-orbit}?parseTime=true&multiStatements=true"
|
||||||
|
|
||||||
|
grant:
|
||||||
|
image: mysql:8.4
|
||||||
|
restart: "no"
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
entrypoint: ["/bin/sh", "-ec"]
|
||||||
|
command:
|
||||||
|
- |
|
||||||
|
case "$${ORBIT_DB_NAME}" in *[!A-Za-z0-9_]*|'') echo 'ORBIT_DB_NAME must contain only letters, numbers and underscores' >&2; exit 2;; esac
|
||||||
|
case "$${ORBIT_DB_USER}" in *[!A-Za-z0-9_]*|'') echo 'ORBIT_DB_USER must contain only letters, numbers and underscores' >&2; exit 2;; esac
|
||||||
|
MYSQL_PWD="$${MYSQL_ROOT_PASSWORD}" mysql --protocol=tcp -h mysql -uroot \
|
||||||
|
-e "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '$${ORBIT_DB_USER}'@'%'; \
|
||||||
|
GRANT SELECT, INSERT, UPDATE, DELETE ON \`$${ORBIT_DB_NAME}\`.* TO '$${ORBIT_DB_USER}'@'%'; \
|
||||||
|
FLUSH PRIVILEGES;"
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${ORBIT_DB_ROOT_PASSWORD:?ORBIT_DB_ROOT_PASSWORD is required}
|
||||||
|
ORBIT_DB_NAME: ${ORBIT_DB_NAME:-orbit}
|
||||||
|
ORBIT_DB_USER: ${ORBIT_DB_USER:?ORBIT_DB_USER is required}
|
||||||
|
|
||||||
|
verify:
|
||||||
|
image: ${ORBIT_IMAGE:-orbit:dev}
|
||||||
|
restart: "no"
|
||||||
|
depends_on:
|
||||||
|
migrate:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
grant:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
entrypoint: ["/usr/local/bin/orbit-admin"]
|
||||||
|
command: ["verify"]
|
||||||
|
environment:
|
||||||
|
ORBIT_MYSQL_DSN: "${ORBIT_DB_USER}:${ORBIT_DB_PASSWORD}@tcp(mysql:3306)/${ORBIT_DB_NAME:-orbit}?parseTime=true&multiStatements=true"
|
||||||
|
|
||||||
|
orbit:
|
||||||
|
image: ${ORBIT_IMAGE:-orbit:dev}
|
||||||
|
restart: unless-stopped
|
||||||
|
init: true
|
||||||
|
depends_on:
|
||||||
|
verify:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
environment:
|
||||||
|
ORBIT_HTTP_ADDR: 0.0.0.0:8080
|
||||||
|
ORBIT_MYSQL_DSN: "${ORBIT_DB_USER}:${ORBIT_DB_PASSWORD}@tcp(mysql:3306)/${ORBIT_DB_NAME:-orbit}?parseTime=true&multiStatements=true"
|
||||||
|
ORBIT_DB_MAX_OPEN: ${ORBIT_DB_MAX_OPEN:-20}
|
||||||
|
ORBIT_DB_MAX_IDLE: ${ORBIT_DB_MAX_IDLE:-5}
|
||||||
|
ORBIT_WORKFLOW_TICK_INTERVAL: ${ORBIT_WORKFLOW_TICK_INTERVAL:-1s}
|
||||||
|
ORBIT_SCHEDULE_TICK_INTERVAL: ${ORBIT_SCHEDULE_TICK_INTERVAL:-1s}
|
||||||
|
ORBIT_RECOVERY_TICK_INTERVAL: ${ORBIT_RECOVERY_TICK_INTERVAL:-2s}
|
||||||
|
ORBIT_RUNTIME_BATCH_LIMIT: ${ORBIT_RUNTIME_BATCH_LIMIT:-100}
|
||||||
|
ORBIT_SHUTDOWN_TIMEOUT: ${ORBIT_SHUTDOWN_TIMEOUT:-10s}
|
||||||
|
ORBIT_WORKER_CONNECTION_LIMIT: ${ORBIT_WORKER_CONNECTION_LIMIT:-128}
|
||||||
|
ORBIT_EVENT_CONNECTION_LIMIT: ${ORBIT_EVENT_CONNECTION_LIMIT:-128}
|
||||||
|
ORBIT_DISPATCH_WORKERS: ${ORBIT_DISPATCH_WORKERS:-4}
|
||||||
|
ORBIT_DISPATCH_CAPACITY: ${ORBIT_DISPATCH_CAPACITY:-128}
|
||||||
|
ORBIT_CONSOLE_QUEUE_ID: ${ORBIT_CONSOLE_QUEUE_ID:-}
|
||||||
|
ORBIT_METRICS_ADDR: ${ORBIT_METRICS_ADDR:-}
|
||||||
|
ports:
|
||||||
|
- "${ORBIT_HTTP_PORT:-8080}:8080"
|
||||||
|
stop_grace_period: 30s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
orbit-mysql:
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Orbit 持续开发与回归计划
|
# Orbit 持续开发与回归计划
|
||||||
|
|
||||||
更新:2026-09-21。此计划对应持续开发目标,由开发过程同步维护。数据库已按用户要求采用无外键设计,迁移 000008 移除历史外键,关联一致性由服务端事务保证。
|
更新:2026-09-22。此计划对应持续开发目标,由开发过程同步维护。数据库已按用户要求采用无外键设计,迁移 000008 移除历史外键,关联一致性由服务端事务保证。
|
||||||
|
|
||||||
## 1. 最终交付目标
|
## 1. 最终交付目标
|
||||||
|
|
||||||
@@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
新增 `make console-e2e` 作为首次部署闭环门禁:在一次性 MySQL 和 Docker Orbit 中从空库迁移、初始化控制台管理员,完成登录、受保护页面、WS Worker 成功执行、明确失败重试、定时任务、控制台任务读取和登出后的 401 校验,证据见[首次部署与控制台任务闭环](reports/phase-8-console-e2e.md)。该门禁证明功能链路可重复,不替代目标生产拓扑、容量和 RPO/RTO 验收。
|
新增 `make console-e2e` 作为首次部署闭环门禁:在一次性 MySQL 和 Docker Orbit 中从空库迁移、初始化控制台管理员,完成登录、受保护页面、WS Worker 成功执行、明确失败重试、定时任务、控制台任务读取和登出后的 401 校验,证据见[首次部署与控制台任务闭环](reports/phase-8-console-e2e.md)。该门禁证明功能链路可重复,不替代目标生产拓扑、容量和 RPO/RTO 验收。
|
||||||
|
|
||||||
|
新增 `deploy/docker-compose.yml` 作为单节点可部署基线:MySQL 健康检查通过后依次执行迁移和 `orbit-admin verify`,核验成功才启动 Orbit;`make compose-check` 提供不泄露密码的静态配置门禁,首次管理员初始化和域名/同源访问说明见[Compose 部署基线](22-compose-deployment.md),实际正常启动与失败阻断证据见[Compose 部署基线验证](reports/phase-9-compose-deployment.md)。该基线不替代生产数据库高可用、正式 Secret、容量、备份和 RPO/RTO 验收。
|
||||||
|
|
||||||
## 2. 持续推进方式
|
## 2. 持续推进方式
|
||||||
|
|
||||||
每个阶段按以下顺序推进:
|
每个阶段按以下顺序推进:
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ docker run --rm \
|
|||||||
registry.example/orbit:dev
|
registry.example/orbit:dev
|
||||||
```
|
```
|
||||||
|
|
||||||
`ORBIT_CONSOLE_QUEUE_ID` 是控制台的可选默认队列范围,只用于打开 `/console/` 时预填队列 ID,不是认证凭据。服务端仍要求业务请求携带有权限的 Bearer Token;多队列部署可以省略此变量,改为在浏览器选择凭据 JSON,由其中的 `queue_id` 自动填充。
|
`ORBIT_CONSOLE_QUEUE_ID` 是控制台的可选默认队列范围,只用于打开 `/console/` 时预填队列 ID,不是认证凭据。控制台登录使用数据库中的管理员账号,会话建立后服务端按账号绑定的业务凭据读取统计和任务;浏览器不需要填写 API 地址或上传凭据 JSON。多队列部署可以省略此变量,管理员在控制台内选择有权限的队列范围。首次管理员通过 `orbit-admin bootstrap` 创建,后续账号使用 `orbit-admin console-user create` 创建。
|
||||||
|
|
||||||
生产编排应先完成迁移和 `verify`,再启动新节点。服务收到 `SIGTERM` 后停止接收新连接并在有限窗口内关闭 HTTP、WebSocket 和后台循环;编排器的终止宽限期必须覆盖该窗口。启动后才能把节点加入流量池。
|
生产编排应先完成迁移和 `verify`,再启动新节点。服务收到 `SIGTERM` 后停止接收新连接并在有限窗口内关闭 HTTP、WebSocket 和后台循环;编排器的终止宽限期必须覆盖该窗口。启动后才能把节点加入流量池。
|
||||||
|
|
||||||
|
|||||||
113
docs/22-compose-deployment.md
Normal file
113
docs/22-compose-deployment.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# Orbit Compose 部署基线
|
||||||
|
|
||||||
|
本文给出单节点部署的可重复入口,适合开发、验收和小规模生产前置环境。它把 MySQL、迁移、schema 核验和 Orbit 服务串成一条有明确失败边界的启动链路;生产多节点、数据库高可用、备份恢复和容量门禁仍按[生产验收](05-production-acceptance.md)执行。
|
||||||
|
|
||||||
|
前置条件:Docker Engine、Docker Compose v2.20 或更高版本;正式环境还应具备镜像仓库、Secret 管理器和 HTTPS 反向代理。
|
||||||
|
|
||||||
|
## 1. 启动契约
|
||||||
|
|
||||||
|
`deploy/docker-compose.yml` 使用同一个 Orbit 镜像启动 Orbit 相关服务,并使用一个短生命周期的 MySQL 客户端服务收紧运行账号权限:
|
||||||
|
|
||||||
|
1. `mysql` 先通过 MySQL 8.4 健康检查。
|
||||||
|
2. `migrate` 使用迁移账号执行 `orbit-migrate up`。
|
||||||
|
3. `grant` 撤销 MySQL 初始化时给运行账号的全库权限,只保留 Orbit 运行所需的 `SELECT`、`INSERT`、`UPDATE`、`DELETE`。
|
||||||
|
4. `verify` 使用收紧后的运行账号执行 `orbit-admin verify`。
|
||||||
|
5. `orbit` 只有在迁移、权限收紧和核验都成功后才启动,运行账号不承担迁移职责。
|
||||||
|
|
||||||
|
迁移或核验失败时,Compose 的 `service_completed_successfully` 依赖会阻止 Orbit 进入流量。修复数据库或发布物后,用同一项目重新执行 `docker compose up -d`;不要通过删除迁移记录或手工改表来绕过核验。
|
||||||
|
|
||||||
|
Compose 文件要求显式提供数据库密码,仓库没有默认密码,也不读取隐式凭据。密码应来自部署平台的 Secret 注入,不应提交到 Git、镜像或日志。
|
||||||
|
|
||||||
|
## 2. 首次启动
|
||||||
|
|
||||||
|
先构建不可变镜像。正式发布时应把 `ORBIT_IMAGE` 换成带版本和摘要的镜像地址:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker build \
|
||||||
|
--build-arg VERSION=1.0.0 \
|
||||||
|
--build-arg REVISION="$(git rev-parse HEAD)" \
|
||||||
|
--build-arg BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||||
|
-t orbit:1.0.0 .
|
||||||
|
```
|
||||||
|
|
||||||
|
在当前 shell 或 Secret 管理器中注入配置。以下值仅是变量示例,不是生产密码:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export ORBIT_IMAGE=orbit:1.0.0
|
||||||
|
export ORBIT_DB_NAME=orbit
|
||||||
|
export ORBIT_DB_USER=orbit_runtime
|
||||||
|
export ORBIT_DB_PASSWORD='从秘密管理器读取'
|
||||||
|
export ORBIT_DB_ROOT_PASSWORD='从秘密管理器读取'
|
||||||
|
export ORBIT_HTTP_PORT=8080
|
||||||
|
```
|
||||||
|
|
||||||
|
`ORBIT_DB_NAME` 和 `ORBIT_DB_USER` 仅使用字母、数字和下划线;权限收紧服务会拒绝其他字符。数据库密码由 Secret 管理器注入,建议使用字母、数字和短横线组成的随机值,避免 DSN 转义差异。
|
||||||
|
|
||||||
|
首次启动先只拉起 MySQL、迁移、权限收紧和核验:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose -f deploy/docker-compose.yml up -d mysql verify
|
||||||
|
docker compose -f deploy/docker-compose.yml ps
|
||||||
|
docker compose -f deploy/docker-compose.yml logs --no-log-prefix migrate grant verify
|
||||||
|
```
|
||||||
|
|
||||||
|
`verify` 成功后,使用同一镜像和数据库连接创建初始业务资源与控制台管理员。密码通过标准输入传入,不能写在命令行参数中:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
credential_dir="$(mktemp -d)"
|
||||||
|
umask 077
|
||||||
|
printf '%s\n' "$ORBIT_CONSOLE_PASSWORD" | \
|
||||||
|
docker compose -f deploy/docker-compose.yml run --rm -T --no-deps \
|
||||||
|
--entrypoint /usr/local/bin/orbit-admin \
|
||||||
|
-e ORBIT_MYSQL_DSN="root:${ORBIT_DB_ROOT_PASSWORD}@tcp(mysql:3306)/${ORBIT_DB_NAME:-orbit}?parseTime=true&multiStatements=true" \
|
||||||
|
-v "$credential_dir:/run/orbit" migrate bootstrap \
|
||||||
|
--application platform \
|
||||||
|
--namespace default \
|
||||||
|
--environment production \
|
||||||
|
--queue default \
|
||||||
|
--worker-access \
|
||||||
|
--schedule-access \
|
||||||
|
--console-username "$ORBIT_CONSOLE_USERNAME" \
|
||||||
|
--console-display-name 'Orbit 管理员' \
|
||||||
|
--console-password-stdin \
|
||||||
|
--output /run/orbit/credentials.json
|
||||||
|
```
|
||||||
|
|
||||||
|
将 `credentials.json` 按 Secret 文件处理,仅用于保存业务接入凭据;控制台登录使用上面创建的用户名和密码。完成安全保存后再启动服务:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export ORBIT_CONSOLE_QUEUE_ID="$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1]))["queue_id"])' "$credential_dir/credentials.json")"
|
||||||
|
docker compose -f deploy/docker-compose.yml up -d orbit
|
||||||
|
curl --fail http://127.0.0.1:"${ORBIT_HTTP_PORT:-8080}"/health/ready
|
||||||
|
```
|
||||||
|
|
||||||
|
如果只需业务 SDK 接入,可以省略控制台管理员;如果要创建多个管理员,使用 `orbit-admin console-user create`,每个账号单独审计和轮换,不共享密码。
|
||||||
|
|
||||||
|
## 3. 访问和域名
|
||||||
|
|
||||||
|
Orbit Console 使用当前页面的同源地址调用服务端,浏览器不需要再填写 API URL,也不需要上传凭据 JSON 才能查看控制台。直接访问 `http://主机:端口/console/`,未登录会跳转到 `/console/login`。
|
||||||
|
|
||||||
|
接入域名时,将 HTTPS 反向代理转发到 Orbit 的 `8080` 端口,并保留 WebSocket Upgrade/Connection 头;浏览器访问的域名就是 Console 自动使用的 API 地址。`ORBIT_HTTP_PORT` 只控制主机映射端口,不是业务域名配置。TLS 证书、域名和安全头由反向代理或入口网关管理。
|
||||||
|
|
||||||
|
## 4. 日常操作与失败处理
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# 查看迁移、核验和服务状态
|
||||||
|
docker compose -f deploy/docker-compose.yml ps
|
||||||
|
|
||||||
|
# 读取结构化服务日志
|
||||||
|
docker compose -f deploy/docker-compose.yml logs --tail=200 orbit
|
||||||
|
|
||||||
|
# 发布新镜像:先完成迁移和核验,再启动新服务
|
||||||
|
docker compose -f deploy/docker-compose.yml up -d verify
|
||||||
|
docker compose -f deploy/docker-compose.yml up -d orbit
|
||||||
|
|
||||||
|
# 停止服务但保留数据库卷
|
||||||
|
docker compose -f deploy/docker-compose.yml down
|
||||||
|
```
|
||||||
|
|
||||||
|
Compose 没有为 scratch 镜像伪造容器内 HTTP healthcheck;编排器或入口网关应调用 `/health/live`、`/health/ready` 和 `/version`。`ready` 返回 `503` 时摘除节点,保留原幂等键并等待数据库恢复。只有明确的废弃环境才使用 `docker compose down -v`,生产数据卷不得随服务停止删除。
|
||||||
|
|
||||||
|
## 5. 当前边界
|
||||||
|
|
||||||
|
该文件是可重复的单节点启动基线,不代表自动数据库故障切换、跨故障域多副本、备份恢复或容量目标已经验收。生产上线还需要真实 MySQL 拓扑、滚动替换、凭据轮换、备份恢复、压测和 RPO/RTO 证据;对应门槛以[交付核对清单](release-checklist.md)为准。
|
||||||
@@ -21,8 +21,10 @@
|
|||||||
| [P7 协议兼容矩阵](reports/phase-7-compatibility.md) | 当前协议门禁、历史提交双向任务 API 演练与正式标签矩阵边界 |
|
| [P7 协议兼容矩阵](reports/phase-7-compatibility.md) | 当前协议门禁、历史提交双向任务 API 演练与正式标签矩阵边界 |
|
||||||
| [P7 Console 真实链路回归](reports/phase-7-console-e2e.md) | 真实 MySQL、Worker、流程、结果订阅与控制台读取闭环 |
|
| [P7 Console 真实链路回归](reports/phase-7-console-e2e.md) | 真实 MySQL、Worker、流程、结果订阅与控制台读取闭环 |
|
||||||
| [首次部署与控制台任务闭环](reports/phase-8-console-e2e.md) | 从空库初始化管理员、Docker 启动、控制台登录、WS Worker、重试和定时任务 |
|
| [首次部署与控制台任务闭环](reports/phase-8-console-e2e.md) | 从空库初始化管理员、Docker 启动、控制台登录、WS Worker、重试和定时任务 |
|
||||||
|
| [Compose 部署基线验证](reports/phase-9-compose-deployment.md) | MySQL、迁移、核验、Orbit 启动顺序及失败门禁 |
|
||||||
| [20 运行与发布手册](20-operations-runbook.md) | 启动、发布、滚动停止、数据库恢复、备份和事故处理 |
|
| [20 运行与发布手册](20-operations-runbook.md) | 启动、发布、滚动停止、数据库恢复、备份和事故处理 |
|
||||||
| [21 容器发布说明](21-container-deployment.md) | 最小镜像、迁移/核验/启动顺序、探针和发布边界 |
|
| [21 容器发布说明](21-container-deployment.md) | 最小镜像、迁移/核验/启动顺序、探针和发布边界 |
|
||||||
|
| [22 Compose 部署基线](22-compose-deployment.md) | MySQL、迁移、核验、Orbit 服务和首次管理员初始化的可重复启动链路 |
|
||||||
| [09 可靠结果订阅](09-result-subscription-core.md) | 提交水位、冻结结果与可靠交付 |
|
| [09 可靠结果订阅](09-result-subscription-core.md) | 提交水位、冻结结果与可靠交付 |
|
||||||
| [10 Weave决策与交付](10-workflow-engine-core.md) | 有限步骤决策和内部结果Inbox |
|
| [10 Weave决策与交付](10-workflow-engine-core.md) | 有限步骤决策和内部结果Inbox |
|
||||||
| [11 Weave实例受理](11-workflow-admission.md) | 固定版本、初始图和首批任务事务 |
|
| [11 Weave实例受理](11-workflow-admission.md) | 固定版本、初始图和首批任务事务 |
|
||||||
|
|||||||
57
docs/reports/phase-9-compose-deployment.md
Normal file
57
docs/reports/phase-9-compose-deployment.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# Compose 部署基线验证
|
||||||
|
|
||||||
|
验证日期:2026-09-22
|
||||||
|
验证范围:MySQL 健康检查、迁移、运行账号权限收紧、schema 核验、Orbit 启动、就绪探针和核验失败门禁。
|
||||||
|
验证环境:Docker Desktop、MySQL 8.4、当前 `orbit:dev` 镜像。
|
||||||
|
|
||||||
|
## 已通过
|
||||||
|
|
||||||
|
### 静态配置门禁
|
||||||
|
|
||||||
|
使用临时数据库用户名、密码和镜像标签执行:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose -f deploy/docker-compose.yml config
|
||||||
|
```
|
||||||
|
|
||||||
|
结果:Compose 配置成功展开,五个服务的依赖条件、健康检查、数据卷、端口和运行时 DSN 均可解析;密码没有写入仓库。
|
||||||
|
|
||||||
|
同时通过:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git diff --check
|
||||||
|
make docs-check
|
||||||
|
```
|
||||||
|
|
||||||
|
### 正常启动链路
|
||||||
|
|
||||||
|
在一次性 MySQL 8.4 和临时数据库卷中执行 Compose 服务链。当前开发机已有大量 Docker 自定义网络,地址池不足,因此本次测试只在临时覆盖文件中把容器放到 Docker 默认 `bridge` 网络并添加链接;生产 Compose 文件仍使用标准项目隔离网络,服务依赖语义没有改变。
|
||||||
|
|
||||||
|
验证顺序和结果:
|
||||||
|
|
||||||
|
1. `mysql` 通过 `mysqladmin ping` 健康检查。
|
||||||
|
2. `migrate` 使用 root 迁移连接完成当前迁移。
|
||||||
|
3. `grant` 撤销运行账号的额外数据库权限,仅保留运行所需的 DML 权限。
|
||||||
|
4. `verify` 使用运行账号完成 `orbit-admin verify`。
|
||||||
|
5. `orbit` 在前述一次性服务成功后启动。
|
||||||
|
6. `GET /health/ready` 返回成功。
|
||||||
|
|
||||||
|
最后输出:
|
||||||
|
|
||||||
|
```text
|
||||||
|
compose-e2e=passed readiness=ok grant=ok
|
||||||
|
```
|
||||||
|
|
||||||
|
### 失败门禁
|
||||||
|
|
||||||
|
第二次使用临时 MySQL,故意让 `verify` 使用错误的运行账号密码。迁移成功后,`verify` 以退出码 1 结束,Compose 报告:
|
||||||
|
|
||||||
|
```text
|
||||||
|
service "verify" didn't complete successfully: exit 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Orbit 没有进入运行状态,证明 schema 核验失败不会把未核验节点拉入流量。
|
||||||
|
|
||||||
|
## 尚未由本报告关闭的事项
|
||||||
|
|
||||||
|
本报告只证明单节点 Compose 的启动顺序和失败边界,不代表生产高可用。数据库自动切换、跨故障域多节点、正式 Secret 注入、反向代理 TLS、备份恢复、容量余量和 RPO/RTO 仍按[生产验收总清单](../05-production-acceptance.md)逐项留证。首次管理员和控制台任务闭环的真实证据见[phase-8 控制台闭环](phase-8-console-e2e.md)。
|
||||||
Reference in New Issue
Block a user