Web management panel for Docker on DeepSeek Harness: manages Docker MCP servers (deploy/remove, official catalog search/pull, gateway start-stop-restart, custom deploy) and containers/images (list, start/stop/restart, remove, logs, inspect, interactive terminal, create, pull, build, load) across local CLI and SSH remote targets with one-click switching. Credentials are encrypted with Windows DPAPI, HTTP is loopback-only, and command parameters are whitelist-filtered. Build-free pure ESM; client is zero-dependency.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:somebdly/dsh-docker
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
DeepSeek Harness (DSH) Web plugin · Docker Management Panel (Docker MCP Gateway management + container/image management)
dsh-docker (plugin id: dsh-docker) is a sidebar Docker panel plugin for the DeepSeek Harness Web GUI. It unifies two categories of Docker operations into a single build-free web panel:
- Docker MCP management: view/deploy/remove MCP servers in profiles, search/pull from the official Docker MCP Catalog, start/stop/restart the MCP Gateway, custom deployments (remote https or local images)
- Container & image management: container list/start/stop/restart/remove/logs/inspect/interactive terminal, prune stopped containers, create containers, pull/build/load/run images, batch-select and delete images
Supports multiple management targets: switch between Local CLI and SSH remote server — all tabs (MCP / containers / images) then operate against the currently selected target.
✨ Features
Multi-target management
- Target selector at the top of the panel; switch management target with one click
- Local target: executes
docker/docker mcpcommands directly on this machine; container operations connect to the daemon via the current docker context - SSH target: executes
docker mcpCLI on the remote host over a persistent paramiko SSH connection, managing the remote Docker Engine and MCP servers
Docker MCP management (MCP tab)
- View deployed MCP servers (servers in a profile)
- Deploy / remove MCP servers (
docker mcp) - Search / pull from the official Docker MCP Catalog (300+ MCP servers)
- Start / stop / restart the MCP Gateway (persistent process that launches server containers on demand)
- Custom deployment: remote https MCP endpoint, or a local image (non-self-describing images like
mcp/sqlitemust firstdocker pullsuccessfully; the gateway loads local images with--pull never) - Profile management: create / delete profiles
Container & image management (Containers tab)
- Containers: list / start / stop / restart / remove / logs / inspect / interactive terminal (
docker exec -it, SSH targets only) / prune stopped containers - Create container:
docker runwith ports, environment variables, volumes, and command arguments; "keep running" is enabled by default (appendstail -f /dev/nullautomatically when no command is given, preventing the container from exiting right after start) - Images: pull / build (
docker build) / load (docker load) / run / delete single / batch-select and delete (check rows or select all in the table, then remove multiple images with onedocker rmi; dangling<none>images are removed by ID automatically) - Destructive operations (stop / restart / remove / prune) require a confirmation dialog
Security design
- SSH authentication supports password or private key; credentials are stored encrypted with Windows DPAPI (only the current user can decrypt; never written in plaintext)
- Panel HTTP is restricted to loopback (127.0.0.1 / ::1) only
- Command injection protection: container IDs, image names, ports, and paths are validated against whitelist regexes before being composed into commands
- Credentials never appear on the command line: the SSH connection reads them from environment variables inside a Python subprocess
Engineering highlights
- Build-free: both Host and Client halves are pure ESM JavaScript; the Client is zero-dependency pure DOM
- Config precedence: environment variables >
config.json> inline cordis config - Zero credentials in the repository: all connection info is configured locally by each user and never enters the repo
🏗️ Architecture
┌──────────────────── DSH Web GUI (browser) ────────────────────┐
│ lib/client.js (pure DOM, zero-dependency) │
│ sidebar "Docker" ⇄ MCP / containers / images tabs + target │
│ switching + interactive terminal │
└──────────────────────────┬────────────────────────────────────┘
│ same-origin HTTP (loopback-only)
┌──────────────────────────▼────────────────────────────────────┐
│ DSH Host · lib/index.js │
│ McpGatewayBoardService: multi-target dispatch + MCP/Gateway + │
│ Docker operations │
│ GET /api/dsh-docker/{state,catalog} │
│ POST /api/dsh-docker/{action,shell/*} │
│ config ~/.dsh/dsh-docker/config.json │
└──────────┬──────────────────────────────┬──────────────────────┘
│ local │ ssh (persistent paramiko)
┌──────▼──────┐ ┌──────▼──────┐
│ local docker│ │ remote Docker│ docker mcp profile/catalog/gateway
│ context │ │ Engine │ MCP servers in containers
└─────────────┘ └──────────────┘
Module responsibilities
| Module | Responsibility |
|---|---|
lib/index.js |
Host entry: config resolution, service mounting, system-prompt injection |
lib/host-service.js |
Core service: multi-target management, MCP/Gateway operations, Docker container/image operations, snapshot polling |
lib/host-routes.js |
HTTP routes (loopback-only): state / catalog / action / shell endpoints |
lib/client.js |
Frontend UI: panel, target switching, MCP/container/image tabs, interactive terminal |
lib/ssh-service.js |
SSH execution service: spawns persistent ssh-exec.py, one-JSON-per-line protocol |
lib/ssh-exec.py |
Persistent paramiko SSH process: command execution + PTY interactive terminal |
lib/local-exec.js |
Local docker execution: execFile + shell-style argument parsing (injection-safe) |
lib/local-db.js |
Reads/writes working_set in the local ~/.docker/mcp/mcp-toolkit.db (node:sqlite) |
lib/crypto-store.js |
Windows DPAPI credential encryption (ProtectedData · CurrentUser) |
scripts/wsl-docker-setup.sh |
One-shot WSL2 Ubuntu Docker Engine + docker mcp installer (with Tsinghua mirror fallback) |
📦 Installation
Method 1: dsh CLI (recommended)
# <repo-path> is the cloned/extracted plugin directory
dsh plugin --profile web add link:<repo-path>
dsh web
Method 2: Manual setup
Add to
dependenciesin~/.dsh/profiles/web/package.json:"dsh-docker": "file:<repo-path>"Append
dsh-dockerto thedsh.profile.bundlesarrayKeep this entry in
~/.dsh/profiles/web/cordis.patch.yml:- insert: - id: dsh-docker name: 'dsh-docker'Run
npm installin the profile directory and restartdsh web
After installation a Docker entry appears in the sidebar.
⚙️ Configuration
Config precedence: environment variables > ~/.dsh/dsh-docker/config.json > inline cordis config
Environment variables
| Variable | Description |
|---|---|
MCPGW_SSH_HOST |
SSH host |
MCPGW_SSH_PORT |
SSH port (default 22) |
MCPGW_SSH_USER |
SSH user |
MCPGW_SSH_PWD |
SSH password (prefer env; do not write into config.json) |
MCPGW_SSH_AUTH |
Auth method: password (default) or key |
MCPGW_SSH_KEY |
Private key path (used with auth=key) |
MCPGW_SSH_PASSPHRASE |
Private key passphrase (optional) |
Runtime config (~/.dsh/dsh-docker/config.json, in your home dir — never commit to git)
{
"pollIntervalMs": 8000,
"activeTargetId": "remote",
"targets": [
{
"id": "local",
"name": "Local Docker",
"type": "local",
"dockerPath": ""
},
{
"id": "remote",
"name": "Remote server",
"type": "ssh",
"ssh": {
"host": "203.0.113.10",
"port": 22,
"user": "root",
"auth": "password",
"password": "<DPAPI ciphertext, or leave empty to use env vars>"
}
}
]
}
Legacy single
sshconfig is automatically migrated into an SSH target in thetargetsarray.
Recommended setup
- Plugin "Connection Settings" dialog (recommended): sidebar "Docker" → settings (top-right) → fill SSH host/port/user, choose password or key auth, save. The password is stored encrypted with DPAPI and never echoed back.
- Environment variables: best for scripts/CI; nothing written to disk.
- Manual config.json: as in the example above.
🖥️ Usage
Panel layout
- Top bar: management target selector (local / SSH remote) + connection status indicator + settings button
- MCP tab: two sub-pages — deployed / catalog
- Deployed: view MCP servers in profiles; deploy/remove
- Catalog: search the official Docker MCP Catalog; one-click deploy
- Containers tab: two sub-pages — containers (ps) / images
- Containers: list, start/stop/restart, remove, logs, inspect, open terminal, prune stopped containers, create container
- Images: pull, build, load, run, delete single, batch-select and delete
Interactive container terminal (SSH targets only)
- Click "Terminal" in the container list
- An interactive
docker exec -it <container> shshell (PTY) opens inside the panel - Real-time I/O, window resize, and session close are supported
Custom MCP deployment
- Remote https endpoint: fill in the MCP server URL directly
- Local image: first
docker pull <image>locally, then fill in the image reference; the gateway loads local images with--pull never - After writing to the target profile's working_set, restart the gateway to apply (one-click restart in the panel, automatically using
--verify-signatures=falseto work around Docker Hub CDN access issues for signature verification)
🔒 Security
| Info | Stored where | Enters the repo? |
|---|---|---|
| SSH host/port/user | config.json (home dir) or env vars |
❌ |
| SSH password | DPAPI ciphertext (only current user can decrypt) | ❌ |
| Private key path/passphrase | config.json |
❌ |
| Non-sensitive config (poll interval, etc.) | config.json |
❌ |
config.jsonis excluded by both.gitignoreand.npmignore; it has never been and will never be committed- All examples in the code use generic placeholders (
203.0.113.10,root, etc.) that do not represent any real environment - Panel HTTP is loopback-only; destructive operations require confirmation; command injection is blocked by whitelist validation
See SECURITY.md.
🗂️ Project structure
dsh-docker/
├── lib/
│ ├── index.js # Host entry (config resolution, service mounting)
│ ├── host-service.js # Core service (multi-target, MCP, Gateway, Docker ops)
│ ├── host-routes.js # HTTP routes (loopback-only)
│ ├── client.js # Frontend UI (pure DOM, build-free)
│ ├── ssh-service.js # SSH execution service (spawns python)
│ ├── ssh-exec.py # Persistent paramiko SSH process (commands + PTY)
│ ├── local-exec.js # Local docker execution
│ ├── local-db.js # Local sqlite working_set operations
│ └── crypto-store.js # DPAPI credential encryption
├── scripts/
│ └── wsl-docker-setup.sh # WSL2 Docker one-shot installer
├── cordis.patch.yml # Plugin registration patch
├── package.json
├── README.md # 中文文档
└── README.en.md # This document (English)
🛠️ Development
- Build-free: edit
lib/*.jsdirectly; restartdsh webafter Host-side changes, hard-refresh the browser (Ctrl+F5) after Client-side changes - Host syntax check:
node --check lib/*.js - Remote prerequisites:
- Docker Engine +
docker-mcpCLI plugin (~/.docker/cli-plugins/docker-mcp) export DOCKER_MCP_IN_CONTAINER=1(when Docker Desktop is unavailable)docker mcp feature enable profilesdocker mcp catalog pull mcp/docker-mcp-catalog- Python 3 +
paramikoon the local machine (forssh-exec.py)
- Docker Engine +
📄 License
Links
More in this category
zhu1090093659/dsh-web-ui#packages/dsh-ssh★ 7488
SSH ops panel for DSH: web terminal, SFTP transfer with progress, local port forwarding, and one-command cluster execution across hosts; agents share the same host config.
zhu1090093659/dsh-web#packages/dsh-remote-web-ui★ 7488
Remote control of a dsh web workspace from phone or PC: QR-code pairing through a token-gated channel, SSE real-time sync, and separate mobile and full desktop GUI modes.
ZSeven-W/dsh-ios★ 288
A live iOS Simulator or USB-connected iPhone inside the conversation: 22 agent tools for booting, building, driving the UI by accessibility identity or OCR text, list-row actions and SwiftUI preview hot reload, plus a streaming sidebar panel you can tap and drag on.
saya-ch/dsh-mobile★ 260
Access DeepSeek Harness from the Android app or a mobile browser with secure LAN and remote connections, persistent device pairing, and a customizable mobile interface.
liguobao/deepseek-harness-remote★ 183
Multi-device remote access for DeepSeek Harness: continue an active session from your phone, tablet, browser, or another computer over an end-to-end encrypted channel (Noise IK + adaptive relay/WebRTC transport), with device authorization, ApiProxy-only remote capabilities, and read-only file preview via dsh-file-viewer — no shell, remote desktop, or write access.
wenbin-wb/dsh-bridge★ 158
Remote and mobile access for DeepSeek Harness: provides LAN QR code connection, Cloudflare/custom tunnels, WeChat, QQ, Feishu, Telegram bot integration, and security authentication.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.