Bundle
dsh-docker
Docker MCP Gateway 管理面板:经 SSH 在远端服务器执行 docker mcp 命令,管理 Docker MCP(列出/部署/移除 profile 中的 MCP、搜索/拉取 Docker MCP Catalog)。免构建(纯 ESM:Host 端 Node 原生 import + spawn python paramiko,Client 端零依赖纯 DOM)。
- Source
- somebdly
- License
- Apache-2.0
- Updated
- Updated yesterday
Readme
# dsh-docker
> DeepSeek Harness (DSH) Web 插件 · Docker 管理面板(Docker MCP Gateway 管理 + 容器/镜像管理)
`dsh-docker`(插件 id:`dsh-docker`)是 DeepSeek Harness Web GUI 的侧边栏「Docker」面板插件。它把 Docker 生态的两大类操作统一放进一个免构建的 Web 面板:
- **Docker MCP 管理**:查看/部署/移除 profile 中的 MCP server、搜索/拉取官方 Docker MCP Catalog、启停/重启 MCP Gateway、自定义部署(远端 https 或本地镜像)
- **容器与镜像管理**:容器列表/启停/重启/删除/日志/详情/交互式终端、清理停止容器、新建容器、拉取/构建/导入/运行镜像、**批量勾选删除镜像**
支持**多管理目标**:可在「本机 CLI」与「SSH 远端服务器」之间切换,切换后所有 tab(MCP / 容器 / 镜像)都针对当前目标。
---
## ✨ 功能特性
### 多目标管理
- 面板顶部目标选择器,一键切换管理目标
- **本机目标(local)**:在本机直接执行 `docker` / `docker mcp` 命令,容器操作经当前 docker context 连接 daemon
- **SSH 目标(remote)**:经 paramiko 常驻 SSH 连接在远端执行 `docker mcp` CLI,管理远端的 Docker Engine 与 MCP
### Docker MCP 管理(MCP tab)
- 查看已部署的 MCP(profile 中的 servers)
- 部署 / 移除 MCP server(`docker mcp`)
- 搜索 / 拉取官方 **Docker MCP Catalog**(仓库 300+ 个 MCP)
- 启停 / 重启 **MCP Gateway**(常驻进程,按需拉起 server 容器)
- **自定义部署**:远端 https MCP 地址,或本地镜像地址(非自描述镜像如 `mcp/sqlite` 需先本地 `docker pull` 成功,gateway 以 `--pull never` 加载本地镜像)
- profile 管理:新建 / 删除 profile
### 容器与镜像管理(容器 tab)
- 容器:列表 / 启动 / 停止 / 重启 / 删除 / 日志 / 详情 / 交互式终端(`docker exec -it`,SSH 目标支持)/ 清理停止容器
- 新建容器:`docker run`,支持端口、环境变量、卷、命令参数;默认开启「保持运行」(未填命令时自动追加 `tail -f /dev/null` 保活,防止容器启动后退出)
- 镜像:拉取 / 构建(`docker build`)/ 导入(`docker load`)/ 运行 / 单个删除 / **批量勾选删除**(表格行勾选或全选,一键 `docker rmi` 多个镜像;悬空 `<none>` 镜像自动按 ID 删除)
- 高危操作(停止 / 重启 / 删除 / 清理)带二次确认
### 安全设计
- SSH 认证支持**密码或密钥**二选一,凭据以 **Windows DPAPI** 加密存储在本机(仅当前用户可解密,不明文落盘)
- 面板 HTTP 仅允许 **loopback**(127.0.0.1 / ::1)访问
- 命令注入防护:容器 ID、镜像名、端口、路径等经白名单正则校验后才拼进命令
- 凭据不落命令行:SSH 连接经 Python 子进程从环境变量读取凭据
### 工程特性
- **免构建(build-free)**:Host 端与 Client 端均为纯 ESM JavaScript,Client 端零依赖纯 DOM
- 配置优先级:环境变量 > `config.json` > cordis 行内 config
- 代码仓库零凭据:所有连接信息由用户在本机配置,不进入代码仓库
---
## 🏗️ 架构
```
┌──────────────────── DSH Web GUI(浏览器) ────────────────────┐
│ lib/client.js(纯 DOM,零依赖) │
│ 侧边栏「Docker」⇄ MCP / 容器 / 镜像 tab + 目标切换 + 终端 │
└──────────────────────────┬────────────────────────────────────┘
│ 同源 HTTP(loopback-only)
┌──────────────────────────▼────────────────────────────────────┐
│ DSH Host · lib/index.js │
│ McpGatewayBoardService:多目标分发 + MCP/Gateway + Docker 操作 │
│ GET /api/dsh-docker/{state,catalog} │
│ POST /api/dsh-docker/{action,shell/*} │
│ 配置 ~/.dsh/dsh-docker/config.json │
└──────────┬──────────────────────────────┬──────────────────────┘
│ local │ ssh(paramiko 常驻连接)
┌──────▼──────┐ ┌──────▼──────┐
│ 本机 docker │ │ 远端 Docker │ docker mcp profile/catalog/gateway
│ context │ │ Engine │ MCP servers in containers
└─────────────┘ └─────────────┘
```
### 模块职责
| 模块 | 职责 |
|---|---|
| `lib/index.js` | Host 入口:配置解析、服务挂载、系统提示注入 |
| `lib/host-service.js` | 核心服务:多目标管理、MCP/Gateway 操作、Docker 容器/镜像操作、快照轮询 |
| `lib/host-routes.js` | HTTP 路由(loopback-only):state / catalog / action / shell 系列端点 |
| `lib/client.js` | 前端 UI:面板、目标切换、MCP/容器/镜像 tab、交互终端 |
| `lib/ssh-service.js` | SSH 执行服务:spawn 常驻 `ssh-exec.py`,一行一 JSON 协议 |
| `lib/ssh-exec.py` | paramiko 常驻 SSH 进程:命令执行 + PTY 交互终端 |
| `lib/local-exec.js` | 本机 docker 执行:`execFile` + shell 风格命令解析(防注入) |
| `lib/local-db.js` | 本机 `~/.docker/mcp/mcp-toolkit.db` 的 working_set 读写(node:sqlite) |
| `lib/crypto-store.js` | Windows DPAPI 凭据加密存储(ProtectedData·CurrentUser) |
| `scripts/wsl-docker-setup.sh` | WSL2 Ubuntu 一键安装 Docker Engine + docker mcp(含清华镜像 fallback) |
---
## 📦 安装
### 方式一:dsh CLI(推荐)
```bash
# <repo-path> 为克隆/解压后的插件目录
dsh plugin --profile web add link:<repo-path>
dsh web
```
### 方式二:手工配置
1. 在 `~/.dsh/profiles/web/package.json` 的 `dependencies` 增加:
```json
"dsh-docker": "file:<repo-path>"
```
2. 在 `dsh.profile.bundles` 数组追加 `dsh-docker`
3. 在 `~/.dsh/profiles/web/cordis.patch.yml` 保留:
```yaml
- insert:
- id: dsh-docker
name: 'dsh-docker'
```
4. 在 profile 目录执行 `npm install`,重启 `dsh web`
安装后侧边栏出现「Docker」入口,点击打开管理面板。
---
## ⚙️ 配置
配置来源优先级:**环境变量 > `~/.dsh/dsh-docker/config.json` > cordis 行内 config**
### 环境变量
| 环境变量 | 说明 |
|---|---|
| `MCPGW_SSH_HOST` | SSH 主机 |
| `MCPGW_SSH_PORT` | SSH 端口(默认 22) |
| `MCPGW_SSH_USER` | SSH 用户 |
| `MCPGW_SSH_PWD` | SSH 密码(建议用 env,不写进 config.json) |
| `MCPGW_SSH_AUTH` | 认证方式:`password`(默认)或 `key` |
| `MCPGW_SSH_KEY` | 私钥路径(auth=key 时使用) |
| `MCPGW_SSH_PASSPHRASE` | 私钥口令(可选) |
### 运行时配置(`~/.dsh/dsh-docker/config.json`,位于用户主目录、勿提交 git)
```json
{
"pollIntervalMs": 8000,
"activeTargetId": "remote",
"targets": [
{
"id": "local",
"name": "本机 Docker",
"type": "local",
"dockerPath": ""
},
{
"id": "remote",
"name": "远端服务器",
"type": "ssh",
"ssh": {
"host": "203.0.113.10",
"port": 22,
"user": "root",
"auth": "password",
"password": "<DPAPI 密文,或留空用环境变量>"
}
}
]
}
```
> 旧版单 `ssh` 配置会自动迁移为 `targets` 数组中的 SSH 目标。
### 推荐配置方式
1. **插件「连接设置」弹窗**(推荐):侧边栏「Docker」→ 右上「设置」→ 填写 SSH host / port / user,选择认证方式(密码或密钥),保存。密码经 DPAPI 加密落盘,界面不回显。
2. **环境变量**:适合脚本/CI,不落盘。
3. **手工写 config.json**:如上示例。
---
## 🖥️ 使用
### 面板布局
- **顶部**:管理目标选择器(本机 / SSH 远端)+ 连接状态指示 + 设置按钮
- **MCP tab**:已部署(deployed)/ 仓库(catalog)两个子页
- 已部署:查看 profile 中的 MCP servers,部署/移除
- 仓库:搜索官方 Docker MCP Catalog,一键部署
- **容器 tab**:容器(ps)/ 镜像(images)两个子页
- 容器:列表、启停/重启/删除、日志、详情、进入终端、清理停止容器、新建容器
- 镜像:拉取、构建、导入、运行、单个删除、批量勾选删除
### 交互式容器终端(仅 SSH 目标)
1. 在容器列表点击「终端」
2. 面板内打开 `docker exec -it <container> sh` 交互式 shell(PTY)
3. 支持实时输入输出、窗口尺寸调整、关闭会话
### 自定义部署 MCP
- **远端 https 地址**:直接填 MCP server URL
- **本地镜像**:先在本机 `docker pull <image>` 成功,再填镜像地址;gateway 以 `--pull never` 加载本地镜像
- 写入目标 profile 的 working_set 后需**重启 gateway 生效**(面板一键重启,自动带 `--verify-signatures=false` 解决镜像签名校验访问 Docker Hub CDN 被墙的问题)
---
## 🔒 安全
| 信息 | 存放位置 | 是否进入仓库 |
|---|---|---|
| SSH 主机/端口/用户名 | `config.json`(用户主目录)或环境变量 | ❌ |
| SSH 密码 | DPAPI 密文(仅当前用户可解密) | ❌ |
| 私钥路径/口令 | `config.json` | ❌ |
| 轮询间隔等非敏感配置 | `config.json` | ❌ |
- `config.json` 已被 `.gitignore` 与 `.npmignore` 双重排除,从未也不会进入版本库
- 代码中的示例均为通用占位(`203.0.113.10`、`root` 等),不代表任何真实环境
- 面板 HTTP 仅 loopback;高危操作二次确认;命令注入白名单校验
详见 [SECURITY.md](SECURITY.md)。
---
## 🗂️ 项目结构
```
dsh-docker/
├── lib/
│ ├── index.js # Host 入口(配置解析、服务挂载)
│ ├── host-service.js # 核心服务(多目标、MCP、Gateway、Docker 操作)
│ ├── host-routes.js # HTTP 路由(loopback-only)
│ ├── client.js # 前端 UI(纯 DOM、免构建)
│ ├── ssh-service.js # SSH 执行服务(spawn python)
│ ├── ssh-exec.py # paramiko 常驻 SSH 进程(命令 + PTY)
│ ├── local-exec.js # 本机 docker 执行
│ ├── local-db.js # 本机 sqlite working_set 操作
│ └── crypto-store.js # DPAPI 凭据加密
├── scripts/
│ └── wsl-docker-setup.sh # WSL2 Docker 一键安装脚本
├── cordis.patch.yml # 插件注册 patch
├── package.json
├── README.md # 本文档(中文)
└── README.en.md # English documentation
```
---
## 🛠️ 开发
- **免构建**:直接改 `lib/*.js`,Host 侧改完重启 `dsh web`,Client 侧改完浏览器刷新(Ctrl+F5)
- Host 代码检查:`node --check lib/*.js`
- 远端前置条件:
- Docker Engine + `docker-mcp` CLI 插件(`~/.docker/cli-plugins/docker-mcp`)
- `export DOCKER_MCP_IN_CONTAINER=1`(无 Docker Desktop 时)
- `docker mcp feature enable profiles`
- `docker mcp catalog pull mcp/docker-mcp-catalog`
- 本机 Python 3 + `paramiko`(供 `ssh-exec.py`)
---
## 📄 License
[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
Install
dsh plugin --profile web add github:somebdly/dsh-docker
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-docker from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.