中文EN

dsh-compose-panel

dev已测通过npmMIT

在右侧栏列出各 DSH 工作区中的 Docker Compose 项目,按项目目录分组,显示容器状态,支持项目级与服务级 up/stop/restart 以及单服务日志流。

下载量 / Downloads
948
依赖体积 / node_modules
1.3 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-compose-panel

沙箱测试结果

阶段结果
1 安装✓
2 列装✓
3 挂载✓
4 启动—

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

dsh-compose-panel

[English](README.md) | 中文

![DSH](https://github.com/deepseek-ai/deepseek-harness)

![CI](https://github.com/yizhixiaokong/dsh-compose-panel/actions/workflows/ci.yml)

![license: MIT](LICENSE)

![dsh-plugin](https://github.com/topics/dsh-plugin)

一个 DeepSeek Harness 插件:把 Docker

Compose 项目放进原生右侧栏——每个项目目录一组、每个容器实时状态、悬停即可

启停或重启、每个服务一个流式日志标签页。

它针对的正是单文件容器面板会做错的那种工作区布局:一个仓库里的多个子目录各自

拥有自己的 compose.yaml。

工作区 ~/work/shop
├── compose.yaml            → 分组 “shop”           2/2 运行中
├── services/api/compose.yaml  → 分组 “services/api” 1/3 运行中
└── tools/mail/compose.yaml    → 分组 “tools/mail”  未启动

截图

右侧栏里的面板:每个项目目录一个可折叠分组,容器状态汇总在标题右侧。

鼠标停在某行时,状态单元格会被该行适用的操作替代——分组标题上是项目级操作,容器行上是单服务操作。

点击容器行即为该服务打开流式日志标签页。

功能

  • 每个项目目录一组。 项目以目录为键,绝不用 compose 项目名,因此 -p、

COMPOSE_PROJECT_NAME 和 .env 都无法把两套不同的栈合并成一行。

  • 三种发现来源。 运行中与已停止的容器、Docker 已知但当前没有容器的项目、

以及从未启动过的 compose 文件——三者都会出现,所以一个没动过的

compose.yaml 也会显示为“未启动”的项目,而不是消失。

  • 限定在工作区内。 只列出 DSH 工作区内的项目;目录归属按最长匹配确定,工作区

之外的容器会被统计出来而不是被悄悄丢弃。

  • 可折叠分组、状态右对齐、行高固定(指针划过时页面不会跳动)。
  • 悬停操作。 鼠标停在某行时,状态单元格会换成该行适用的操作:项目级的

up -d / restart / stop,或单个服务的同样三项。任何命令都不会在未点击时执行。

  • 实时日志流。 点击服务行即为该服务打开日志标签页;点击项目标题则为整个项目

打开。每个目标保留自己的标签页。

  • 静默刷新。 空闲时每 45 秒、仍有服务在启动时每 8 秒重新读取一次,且不会丢失

滚动位置、已展开的分组或当前选择。

  • 与产品一致的样式:只用 Harness 自己的主题变量,因此自动跟随浅色/深色模式与强调色,

不需要额外设置页。

环境要求

要求 · 说明

DSH >= 0.1.5-rc.1 · 实测于 0.1.5-rc.1、0.1.5-rc.2、0.1.7-rc.2。0.1.7 系列需要本插件 0.1.2 及以上,见 [DSH 版本](#dsh-版本)。

带 web profile 的 DSH · 插件注册一个右侧栏标签类型和一条 HTTP 路由,二者都由 webServer 提供。

宿主进程 的 PATH 中有 Docker CLI · docker ps、docker compose ls 以子进程方式执行;需要 compose v2 插件(docker compose,不是 docker-compose)。

POSIX 系统 · 路径按 POSIX 处理;Windows 未经验证。

至少一个 DSH 工作区 · 只列出已注册工作区之内的目录。

DSH 版本

DSH · 插件版本 · 说明

0.1.7-rc.2 · 0.1.2 及以上 · 0.1.1 什么都不注册——「容器」标签直接不出现。

0.1.7-rc.1 · 0.1.2 及以上 · 同一个竞态;0.1.2 已对照该版本的发布包核实,未端到端实测。

0.1.5-rc.1 / 0.1.5-rc.2 · 0.1.1 与 0.1.2 均可 · 两者都可用。0.1.2 没有引入新 API——只加了一个 guide 字段和依赖声明——其激活门已在这条线钉定的 cordis 版本上实测通过。

为什么 0.1.1 在 0.1.7 上坏了。 客户端半边只会在自己 inject 列表中的服务全部就绪后

才被 apply。sidebarRightTabs 注册表由右栏自己的 apply 提供,而那个 apply 的依赖比本插

件多——0.1.5-rc.2 是 4 个、0.1.7-rc.1 是 6 个、0.1.7-rc.2 是 7 个——所以它落在本插件之后。

0.1.1 只声明了 slots,在注册表尚未存在时就 apply,取不到便直接退出。0.1.2 把

sidebarRightTabs 声明为硬依赖,等它就绪。

关于 0.1.7-rc.1: 已核对两个 0.1.7 候选版的发布包——该版本的右栏同样提供

sidebarRightTabs,且两者钉定同一 cordis(~4.0.4),激活门正是由它实现。因此 0.1.2 在

rc.1 上应当可用,但未在该版本端到端实测。

安装

直接从 GitHub 安装——不必克隆(想固定版本就钉一个 tag):

dsh plugin --profile web add "github:yizhixiaokong/dsh-compose-panel"
# 钉版本:dsh plugin --profile web add "github:yizhixiaokong/dsh-compose-panel#v0.1.3"

从克隆安装(需要改代码时):

git clone https://github.com/yizhixiaokong/dsh-compose-panel.git
cd dsh-compose-panel
dsh plugin --profile web add "$PWD"

从 npm 安装:

dsh plugin --profile web add dsh-compose-panel

三种方式结果一致,也都不需要手工登记:dsh plugin 先跑 pnpm,再读取每个已安装依赖的

package.json——声明了 dsh.bundle 的包,其名字会被追加进

dsh.profile.bundles,由它挂载旁边的 [cordis.patch.yml](cordis.patch.yml)。

(没有该声明的依赖只会作为普通库安装并给出警告。)同样没有构建步骤——客户端部分是随

lib/ 一起发布的手写产物。

随后重启 Harness 以加载客户端产物:

dsh web

卸载:

dsh plugin --profile web remove dsh-compose-panel
客户端部分在宿主启动时完成基线化。在运行中的实例里修改 lib/client.js
不会生效,直到 dsh web 重启——刷新浏览器不够。

更新

插件市场里的「更新」按钮执行的就是下面第一条,命令行等价形式:

# 从 npm 安装的
dsh plugin --profile web add dsh-compose-panel@latest

# 从 GitHub 安装的——钉住想要的 tag;去掉 #tag 则取默认分支最新
dsh plugin --profile web add "github:yizhixiaokong/dsh-compose-panel#v0.1.3"

# 从 checkout 安装的(link:)——checkout 就是安装源
git -C <本仓库路径> pull

更新后要重启 dsh web:客户端半边在宿主启动时基线化,重启前新代码不生效。

使用

1. 打开右侧栏,在引导页选择 🐳 容器 胶囊。

2. 每个工作区是一个区块,每个项目目录是一个可折叠分组,标题为目录路径,右侧是

容器状态的汇总。

3. 悬停在项目标题上可对整个项目操作;悬停在容器行上只对该服务操作。指针在行上时,

操作按钮会替代状态单元格,结果通过一条短横幅提示。

4. 点击容器行(不是按钮)为该服务打开日志标签页;点击分组标题打开整个项目的日志。

日志标签页有自己的控件:回放行数(tail)、重新打开流、时间戳开关、自动换行,以及

(整项目标签页的)服务名列。

项目如何被发现

一次 list 调用执行三条命令并按目录合并结果:

来源 · 命令 · 贡献

容器 · docker ps -a --format '{{json .}}' · 所有容器,按 com.docker.compose.project.working_dir 标签分组。

已知项目 · docker compose ls --all --format json · 已存在但当前没有容器的项目(其 ConfigFiles 为绝对路径)。

未动过的文件 · 每个工作区一次有界的 find · 从未启动过的 compose 文件:深度 4,并剪掉 node_modules、.git、vendor、dist、build、target、.venv、venv、__pycache__、.next、.cache、.tox。

项目目录就是连接键。扫描识别的 compose 文件名包括 compose.yml、

compose.yaml、docker-compose.yml、docker-compose.yaml,以及

compose.<name>.yml / docker-compose.<name>.yml 变体。

HTTP 接口

宿主部分注册一条前缀路由 /compose/api。所有响应使用同一信封:

成功为 {"ok":true,"value":…},失败为

{"ok":false,"error":{"code","message"}}。

任何命令执行之前,请求先经过围栏校验。两个 POST 方法要求 Host 为 loopback

地址(localhost、127.0.0.1、::1、*.localhost,可带端口)或位于 web

runtime 的信任列表中;被浏览器标记为 Sec-Fetch-Site: cross-site 的请求会被拒绝;

如果带 Origin,其 host 必须等于 Host。日志流使用读侧变体:socket 对端必须是

loopback(或 Host 受信任)、不得携带转发头(forwarded、x-forwarded-for、

x-real-ip),且允许缺少 Origin——浏览器在同源 EventSource 上不会发送它。

POST /compose/api/list

// 请求——root 可选,不传即列出所有工作区
{ "root": "/home/me/work/shop" }
// 响应 value
{
  "workspaces": [{ "path": "/home/me/work/shop", "title": "shop" }],
  "groups": [{
    "root": "/home/me/work/shop",
    "title": "shop",
    

…(truncated)

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:3,最后更新 2026-09-28

链接

GitHub · Homepage · npm

同类插件