fix(deployment): harden backend core recovery
This commit is contained in:
+1
-1
@@ -44,7 +44,7 @@ services:
|
||||
context: .
|
||||
dockerfile: src/components/backend-core/Dockerfile
|
||||
container_name: unidesk-backend-core
|
||||
restart: unless-stopped
|
||||
restart: always
|
||||
depends_on:
|
||||
- database
|
||||
ports:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
## Services
|
||||
|
||||
- `database` 使用 `postgres:16-alpine`,数据保存到 named volume `unidesk_pgdata_10gb`,当前容量预算为 15 GB,初始化 SQL 位于 `src/components/database/init/`。
|
||||
- `backend-core` 是无状态核心服务,提供 Docker 内网 REST API、provider ingress WebSocket、任务调度入口和数据库访问层。源码拆分为 15 个职责单一的模块(`index.ts` 只做路由和启动),模块结构见 `docs/reference/repo-tree.md`。
|
||||
- `backend-core` 是无状态核心服务,提供 Docker 内网 REST API、provider ingress WebSocket、任务调度入口和数据库访问层,Compose restart policy 必须为 `always`,确保进程崩溃或 Docker daemon 重启后自动恢复。源码拆分为 15 个职责单一的模块(`index.ts` 只做路由和启动),模块结构见 `docs/reference/repo-tree.md`。
|
||||
- `frontend` 是唯一公开 Web 控制台,提供登录、从 TSX 转译出的 React 应用资产和到 backend-core 的同源代理。
|
||||
- `provider-gateway` 是当前主 server 的本机计算节点代理,通过 WebSocket 主动连到 provider ingress,挂载 `/var/run/docker.sock` 作为自动任务执行主路径,使用 `pid: "host"` 读取节点级进程资源,并周期性上报系统资源指标、进程占用与 Docker daemon 状态;计算节点 provider-gateway 还必须把 egress proxy 仅发布到宿主 loopback `127.0.0.1:18789` 供本节点执行环境出网,维护用 Host SSH / WSL SSH 私钥目录只读挂载到 `/run/host-ssh`,不得作为自动任务调度主路径。
|
||||
- `todo-note` 是主 server 承载的 Todo Note 纯后端用户服务,容器名 `todo-note-backend`,只在 Compose 内网暴露 `4211/tcp`,使用主 PostgreSQL 存储迁移后的 Todo Note 数据。
|
||||
@@ -25,7 +25,7 @@ Docker Compose 对最终用户只公开 frontend host port 和 provider ingress
|
||||
|
||||
CLI 会优先使用 `docker compose` v2 plugin;当 v2 plugin 不存在时才回退到 `docker-compose` v1。主 server 可以通过安装系统包形式的 Compose v2 plugin 完成无中断升级,因为该动作只增加 Docker CLI plugin,不要求重启 Docker daemon,也不要求重建或停止已有容器。若 Compose v2 build 提示 buildx plugin 不存在,应同样以系统包安装 buildx CLI plugin,而不是重启 Docker 或重建业务容器。
|
||||
|
||||
Compose v2 安装后仍然必须遵守 UniDesk 的服务控制入口:全栈生命周期用 `server start` / `server stop`,单服务重建用 `server rebuild <service>`。不要因为 v2 可用就直接在生产栈上手工执行未纳入 CLI 的 `up --build`、`down -v` 或跨项目清理命令;所有会影响容器的动作都应保持 job 可观测、Compose project 固定、database named volume 保留。
|
||||
Compose v2 安装后仍然必须遵守 UniDesk 的服务控制入口:全栈生命周期用 `server start` / `server stop`,单服务重建用 `server rebuild <service>`。不要因为 v2 可用就直接在生产栈上手工执行未纳入 CLI 的 `up --build`、`down -v` 或跨项目清理命令;所有会影响容器的动作都应保持 job 可观测、Compose project 固定、database named volume 保留。主 server Compose 命令必须从 `providerGateway.upgrade.hostProjectRoot` 指定的 canonical UniDesk 根目录运行,临时 worktree、Code Queue 导出目录或实验分支不得复用生产 `-p unidesk` 和固定 `container_name` 去替换生产容器。
|
||||
|
||||
版本化用户服务部署优先使用 `bun scripts/cli.ts deploy apply`。`deploy.json` 只声明服务 `id`、`repo` 和 `commitId`;目标节点、Dockerfile、Compose、Kubernetes manifest、健康检查和代理路径继续来自 `config.json` 与现有 manifest。主 server 直管微服务和内部 sidecar,例如 `code-queue-mgr`,也必须支持这一路径:`deploy apply --service code-queue-mgr` 从 `deploy.json` 指定 commit 导出源码、构建镜像、替换固定 Compose service 并验证运行中镜像/健康信息的 commit。部署必须遵循 target-side build:服务部署到哪台 target,就在哪台 target 从 remote commit 导出源码、一次性代理构建镜像并部署;不得把中心构建镜像作为默认分发路径,也不得用 `docker commit` 或脏 worktree 作为部署输入。完整规则见 `docs/reference/deploy.md`。
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ export function isRebuildableService(value: string | undefined): value is Rebuil
|
||||
}
|
||||
|
||||
export function resolveComposeCommand(config: UniDeskConfig, envFile: string): string[] {
|
||||
assertCanonicalServerRoot(config);
|
||||
const composeFile = rootPath(config.docker.composeFile);
|
||||
if (commandOk(["docker", "compose", "version"], repoRoot)) {
|
||||
return ["docker", "compose", "--env-file", envFile, "-f", composeFile, "-p", config.docker.projectName];
|
||||
@@ -52,7 +53,21 @@ function envValue(value: string): string {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
|
||||
function assertCanonicalServerRoot(config: UniDeskConfig): void {
|
||||
const canonicalRoot = resolve(config.providerGateway.upgrade.hostProjectRoot);
|
||||
const currentRoot = resolve(repoRoot);
|
||||
if (currentRoot !== canonicalRoot) {
|
||||
throw new Error([
|
||||
"Main-server Docker Compose commands must run from the canonical UniDesk root.",
|
||||
`canonicalRoot=${canonicalRoot}`,
|
||||
`currentRoot=${currentRoot}`,
|
||||
`Run from the canonical root: cd ${canonicalRoot} && bun scripts/cli.ts server <start|status|logs|rebuild|stop>`,
|
||||
].join(" "));
|
||||
}
|
||||
}
|
||||
|
||||
export function writeComposeEnv(config: UniDeskConfig, freshLogPrefix: boolean): ComposeRuntimeEnv {
|
||||
assertCanonicalServerRoot(config);
|
||||
const stateDir = rootPath(config.paths.stateDir);
|
||||
mkdirSync(stateDir, { recursive: true });
|
||||
const envFile = join(stateDir, "docker-compose.env");
|
||||
|
||||
Reference in New Issue
Block a user