Repository navigation
feat: 设计并实现 Docker Compose 应用管理 #2
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
目标
在 devbox 中交付可用于单机开发环境的 Docker Compose 应用管理,与 Kubernetes runtime 并列,并统一复用应用商店、应用列表和管理抽屉。当前范围是:单机、文件原生、持久异步任务驱动、安全受控的 Compose Stack 管理器、原生 1Panel 开源应用商店兼容,以及系统 Compose project 自动发现与安全接管。
Compose 应用管理(已完成)
-
apps.Controller统一领域 seam,Compose/Kubernetes adapter 隐藏在模块内部。 - Application/Task/Revision 稳定模型;旧读路径/action 兼容;phase、service replica/health 由后端聚合。
- Compose CLI v2 写、Docker Engine API 读;SQLite 保存 Application/Revision/Task/Idempotency/Audit;Compose、env、sidecar 与 revision 文件原生落盘。
- deploy/start/stop/restart/redeploy/remove/purge/definition restore 全部异步返回 Task。
- per-app 串行、跨 app 有限并发、显式幂等、乐观并发、崩溃恢复和 last observed 校验。
- 默认卸载保留数据;purge 只删除 managed 数据;external/bind/socket 永不自动删除。
- 粘贴/上传、预检、结构化参数、Compose 编辑、版本历史、definition restore,以及概览/服务/日志/Compose/环境变量/存储/版本/操作记录 8 个详情 Tab。
- edge-apiserver storeapps 与通用
devbox/v1HTTP/Git catalog 进入同一可信安装链路。
原生 1Panel 应用商店(已完成)
直接读取 1Panel 官方仓库格式(根 data.yaml、apps/<key>/data.yml、版本 data.yml/formFields、docker-compose.yml),不要求上游转换为 devbox 私有 catalog。
- UI 可添加、测试、保存、启停、刷新、删除 1Panel Git 来源;自动探测或显式选择
1panel。 - 动态来源持久化到现有
apps.db,与只读 YAML 来源合并;token 只写不回显;来源变更与审计同事务。 - 原生解析应用、版本、参数和 Compose,安装时可信重取并走
Controller.Apply、Task、revision 与风险策略。 - 处理来源隔离 ID、
1panel-network、container_name、不执行脚本、password 默认值、可变镜像、残留插值、sparse clone、last-good cache 和来源 generation。 - 动态 URL 仅允许解析到公网地址的 HTTPS,拒绝 userinfo/query/fragment、私网/loopback/link-local/metadata。
系统 Compose project 自动发现与安全接管(已完成)
- 按标准 Compose labels 扫描所有仍有容器记录(包含 stopped)的 project;与受管应用去重后统一展示。
- 外部 project 使用稳定 ID,展示 project name、services、phase/health、端口和来源路径诊断;明确标记“已发现 · 只读”。
- 未接管项目只读,禁止 start/stop/restart/redeploy/remove/edit 等写操作,避免误操作系统现有服务。
- 列表扫描不读取 labels 指向的宿主文件;只有登录用户显式点击“接管并编辑”后才读取并复制定义。
- Linux 接管使用
openat2原子打开,拒绝 symlink/path traversal/magic-link/跨文件系统/非普通文件/超限或读取中变化;FIFO 不会阻塞请求。 - Compose CLI 前阻断 include/build/env_file/extends/configs/secrets 等额外宿主读取;临时副本 0700/0600、空 env、固定子进程环境。
- 接管后保留原 Compose project name 原地管理,元数据持久化并可重启恢复;named volume 数据不变。
- 接管前执行 compose config 与现有风险预检;blocked 不可覆盖,confirmation 需显式确认并审计。
- 接管成功后进入现有 Compose 编辑、revision、Task、日志、生命周期和卸载数据边界;源目录不被 devbox 修改。
- 完全 down 且容器记录已删除的外部 project 无法从 Docker daemon 自动发现,UI/文档明确说明;可继续通过粘贴/上传导入。
安全边界
- blocked 永不可 override:privileged、docker.sock、host network/PID/UTS/userns、cap_add ALL、系统关键 bind 等。
- Secret 只进入权限受限的
.env/临时期望文件,HTTP、revision、Task、audit、CLI error、日志全链路脱敏。 - 动态 Git 来源通过 Git CLI 获取,URL 校验到 clone 之间仍存在无法 pin DNS 的 rebinding 时间窗;该残余风险已写入研究文档。
- 自动发现依赖仍保留的容器 metadata;完全
compose down后不做文件系统全盘搜索。
验证
-
git diff --check -
make test(Go race;pkg/apps71.6%) -
go vet ./... - 目标前端 ESLint 0 error;helper tests 7/7;Vite build
-
make build-all,嵌入 UI 与 Linux amd64 二进制同步 - integration build tag 编译
- 真实 Docker 发现→接管→编辑/重部署→进程重启恢复,保留原 project name 与 named volume marker;完全 down 后不再发现(48.89s)
- 1Panel 官方源真实集成测试(目标机直连官方仓库)
明确边界
- CasaOS:官方 v2 协议已做一手评估,但构建产物、路径模型与参数模型不同,本 PR 不放入半成品 adapter。
- fnOS / Unraid:本轮不在范围,不作未经核验的开闭源断言。
- 多主机、数据备份/恢复、GitOps 自动 reconcile、K8s↔Compose 自动转换:不属于当前单机里程碑。
实现与验证见 PR #3。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
wuxs commentedon Jul 21, 2026
本 PR 进展:阶段 0-3 MVP(端到端跑通,含真实 Docker 验证)
分支
issue-2-compose-apps(从最新origin/main的 worktree),阶段 0-3 已完成并端到端验证。按任务要求仅本地 commit,未 push、未开 PR。已实现
Application/Task/Revision模型,Controller是唯一对外 seam,runtimeAdapter(compose/kubernetes)为内部 seam;旧 K8sManager迁成kubernetesRuntimeadapter(deploymentToAppInfo→deploymentToApplication,phase 由后端聚合);HTTP JSON 向前兼容旧useApps/useAppDetail读路径,前端零改。net/http,支持 unix socket 与tcp:///DOCKER_HOST,刻意不引入 docker SDK),按com.docker.compose.project=devbox-*只发现受管 project;Docker 不可用时 capability 清晰且不影响 K8s。modernc.org/sqlite,纯 Go 无 cgo)存元数据/任务/revision/幂等/审计;持久 Task worker:per-app 串行、幂等(同 key 同请求→同 task;同 key 异请求→409)、崩溃恢复;start/stop/restart/redeploy/remove,默认保留数据,purge 显式,external volume 永不删。compose config预检;风险策略 blocked/confirmation/warning(阻断privileged/docker.sock 挂载/根目录 bind/hostnetwork/pid:host;latest/main强警告,本地创建不静默接受);revision 历史 + 乐观并发(expectedRevision不匹配→409);app ID 防路径穿越、Compose 参数防 shell 注入、secret 仅写.env(0600) 不回传/不入 revision/审计/任务摘要。202+Task;新增 validate/capability/tasks/actions/compose/revisions/restore/operations。ComposeManager页(runtime 筛选 / 生命周期 / 新建预检 / 任务反馈),不重写 Desktop/AppMgmtDrawer。真实验证(不掺水)
make test(-race)全绿:领域 / 风险策略 / SQLite 持久化 / worker(per-app 串行 + 崩溃恢复 + secret 脱敏)/ HTTP 路由与状态码(202/409/422/404 映射)。integration,默认不跑):用缓存的alpine:3在真实 daemon 上跑通 apply→observe(running,2 services)→stop→start→remove→logs。关键决策
docker composeCLI(exec.CommandContext参数数组、无 shell、固定 project namedevbox-<app-id>);读走 Engine API。DOCKER_HOST=tcp://...:2376,实测为 plain HTTP),故 Engine 客户端同时支持 unix/tcp;生产 socket 同样适用。剩余(未做,明确边界)
Controller.Apply;商店包渲染 Compose 留后续。待 review 关注点
/actions。sqliteRepo单连接写(per-app 串行 + 有限并发读足够),WAL + busy_timeout。下一步:review 通过后 push + 开 PR(本会话按要求仅本地 commit
6cbc787)。wuxs commentedon Jul 22, 2026
阶段4 补齐:Compose 商店统一(本地 commit,未 push)
此前阶段4 被错误 defer,现补齐。两个本地 commit(
issue-2-compose-apps):09e62a4(实现) +c082998(独立安全审计驱动修复,No BLOCKER)。现状
前端原请求
/store/apps、/store/version、/store/install、/store/deployments,后端只实现/store/apps。现补齐,复用既有 edge-apiserverstoreapps协议,不新建本地 catalog、不改 edge-apiserver 仓库。catalog 包格式(向后兼容,不改 edge-apiserver)
edge-apiserver 真实
ApplicationVersionSpec当前只有workloadConfig/helmConfig/modelConfig/values/valuesSchema/configTemplates,无 compose 字段。devbox 客户端 DTO 向后兼容读取spec.composeTemplate(首选)/spec.compose(别名);该字段一旦 edge-apiserver 提供,Compose 安装即自动生效。当前真实 catalog 所有包均为 Kubernetes 包(provisioner=workload/helm/model),按 CEO 裁决第2条标 Kubernetes、不可本机 Compose 安装,未做 K8s→Compose 自动翻译。已实现
GET /store/version?appId=&v=:返回valuesSchema/defaultValues/runtime/installable;compose 模板永不回传(后端持有)。POST /store/install:后端从可信 catalog 重取版本 → 校验 values(对照 schema:required/type/select,拒绝未知 key)→ 安全渲染 →Controller.Apply→202+Task。不接受前端 compose 原文冒充 catalog。text/templatemissingkey=error+ 不注册任何 FuncMap(无任意函数/shell/file);secret/password 只进.env(0600),不进 compose 正文/revision/task/audit/HTTP;模板输出 ≤1MiB,catalog 响应 ≤4MiB,URL 转义,错误体裁剪脱敏。expectedRevision,版本切换产生新 revision;Idempotency-Key 默认按app+version+params+secrets指纹(避免 secret 轮换静默失效)。taskId经useTask轮询;无 catalog 显示清晰空态,不用 mock;/store/deployments已由 taskId 轮询替代。边界(如实)
apiserver_url、不应随意连远程集群;故未做线上端到端。完整管道由 httptest fake catalog + stub controller 覆盖(store/render/handler 测试全绿)。Controller.Apply内docker compose configstrict 预检);Docker 不可用时返回 capability 错误,前端显示 failed。/store/version为准(若 label 标 compose 但版本无模板,install 会 422 兜底,仅一次性 UX 不一致)。验证
go test ./...全绿、go vet干净;前端vite build通过;eslint 较改动前 baseline 不恶化(AppStore.jsx 既有 dead-import debt 为 main 既有,非本次引入)。embed 副本pkg/console/dist已make ui同步。feat(apps): unify Compose app store against edge-apiserver (phase 4, #2)
wuxs commentedon Jul 22, 2026
阶段 4 状态更新:Compose 商店提交
09e62a4与审查修复c082998已推送到 PR #3,PR head 与测试环境部署版本均为c082998。make test(race)通过,pkg/apps覆盖率 62.6%。make build-all通过,前端嵌入资源与 Linux amd64 二进制已同步。192.168.1.2:/opt/devbox/devbox并重启;服务 active、health 200、Compose runtime enabled、远端 SHA256 与本地一致。现等待 PR review,不会自动合并。
feat(apps): third-party docker compose catalog and mgmt detail (#2)
feat(apps): complete Compose catalog and management UI (#2)
fix(apps): close final Compose security and task review findings (#2)
fix(apps): complete Issue 2 lifecycle audit gaps (#2)
wuxs commentedon Jul 22, 2026
完成性审计与最终部署已完成,PR #3 head 为
046601b。本轮补齐了 CatalogID/StoreID 持久化、崩溃恢复事实源、同 app 提交串行、默认卸载数据安全、卸载后重装、definition restore 参数语义、本机 Docker socket 边界、结构化向导、真实 Task phase、service replica 聚合、预检 network/secret/端口/路径摘要等缺口。最终make test(race,pkg/apps 73.6%)、vet、前端 test/lint/build、build-all 全部通过;192.168.1.2 上两条真实 Docker E2E 与最终部署验证通过。PR 保持 open,等待人工 review,不会自动 merge。feat(apps): support native 1Panel catalogs (#2)
feat(apps): discover and take over Compose projects (#2)