dshbase

插件目录 / Developer / dsh-container

dsh-container

已验证 · 实测可装 NIyueeE

✓ 持续维护

查看 GitHub ↗ ← 返回插件目录

1Stars
0Forks
0未关闭 issue
Dockerfile语言
2026-08-15最近推送
跨平台平台

功能简介

DSH容器镜像:通用开发基础,自动更新

✅
我们的评价
可用 — 实测通过,早期项目

DSH容器镜像:通用开发基础,自动更新 实测能干净安装、正常启动。早期项目,但功能可用。

「已验证」表示我们的自动化 CI 在干净 profile 里实际执行了 dsh plugin add 并启动成功——仅此而已。功能描述与版本兼容性均为作者声明。这不是安全审计,也不代表对第三方代码的背书。

README

dsh Container Image

Containerized DeepSeek Harness (dsh), built on
a small debian:13-slim base with only the toolchains this project needs: Node.js LTS, pnpm, uv,
Rust/cargo, Caddy, podman, and GitHub CLI. It is ready to use out of the box with optional dsh
auto-update
baked in. The image is published to GitHub Container Registry; both the compose.yaml
and the Quadlet .container examples pull the image directly — no local build needed.

dsh itself comes from the official repository
deepseek-ai/deepseek-harness and is installed the
way the official README describes: install Node.js, then npm-install @deepseek-ai/dsh.

Features

Component Description
Base image debian:13-slim (small, overridable via the BASE_IMAGE build arg)
Built-in toolchain Node.js 22 LTS, pnpm, uv, Rust/cargo, git, build-essential, Caddy, podman, gh
Added user-level tools Rust/cargo (~/.rustup + ~/.cargo), uv (~/.local/bin), pnpm (~/.local/share/pnpm) — persisted with /home/dsh
Container dev tool podman (apt), with rootless subuid/subgid mapping configured; nested rootless operation depends on the host runtime
dsh Global npm install of @deepseek-ai/dsh, same source as the official README's npx @deepseek-ai/dsh web; pinnable via DSH_VERSION
Auto-update Off by default (DSH_AUTO_UPDATE=0); opt in with DSH_AUTO_UPDATE=1 to update dsh to the latest npm release on container start (only upgrades, never downgrades a pinned version). The image itself supports Pull=newer / AutoUpdate=registry
dsh web supervisor dsh web runs under a small supervisor (dsh-web) that restarts it automatically if it exits; run dsh-restart inside the container to restart dsh web without restarting the container
Exposure Caddy reverse proxy (0.0.0.0:3081 → dsh's 127.0.0.1:3080) rewriting Host/Origin to loopback, gzip-compressing UI assets (≈1.3 MB → ≈360 KB), with optional basic auth (DSH_PROXY_USER / DSH_PROXY_PASSWORD)
Observability OCI labels (org.opencontainers.image.*, incl. git revision), HEALTHCHECK (curl 3080 + 3081)
Runtime user uid 1000 (dsh); /home/dsh is the persisted user layer and dsh has passwordless sudo

The base image is pinned by default; the dsh top-level version and Rust toolchain can be pinned
with --build-arg. uv/pnpm are installed as user-level tools, and Caddy/podman/gh come from apt —
see build.md.

Environment variables

Variable Default Description
DSH_PROXY_USER / DSH_PROXY_PASSWORD (empty) Enable basic auth on the exposed proxy (recommended): without it, anyone who can reach port 3081 can drive the agent and read/write all settings & credentials (see security.md "Security boundary"). Set both or neither — the entrypoint refuses to start if only one is set
DSH_AUTO_UPDATE 0 Set to 1 to update dsh to the latest npm release on container start; keeps the in-image version when offline or on failure

Everything else uses built-in defaults:

  • dsh data: ~/.dsh (/home/dsh/.dsh) — upstream default, no DSH_HOME override
  • working directory: $HOME (/home/dsh); dsh creates folders under it as needed
  • Rust/cargo: ~/.rustup + ~/.cargo
  • uv: ~/.local/bin (managed Python/tool data in ~/.local/share/uv)
  • pnpm: ~/.local/share/pnpm

The whole /home/dsh directory is the persistence boundary: mount it as one volume so user-level
state survives while /usr/local and the rest of the system layer are reset on image upgrades.
User-level tools (Rust/uv/pnpm/dsh) are baked into the image and copied into a fresh named volume on
first start; system packages installed later with sudo apt live in the container/system layer and
are not part of the persistent home volume.

The exposed port is 3081: a Caddy reverse proxy inside the container listens on
0.0.0.0:3081 and forwards to dsh web on 127.0.0.1:3080, rewriting Host/Origin to loopback.
UI assets are gzip-compressed by the proxy (≈1.3 MB → ≈360 KB), which matters most for remote
access; SSE/WebSocket streams pass through unbuffered (verified against Caddy 2.6), so agent
output is not delayed by the proxy. For WAN access, terminate TLS with an external reverse proxy in
front of 3081; it must forward the WebSocket upgrade headers (proxy_set_header Upgrade $http_upgrade / proxy_set_header Connection "upgrade" with nginx) and must not buffer or time
out quiet streams — see deployment.md for a working example. dsh's /api
browser-trust fence checks HTTP headers only, so remote browsers pass every endpoint —
including settings/credentials methods that are otherwise loopback-only. The proxy is therefore
the security boundary
: anyone who can reach 3081 gets full control, so enable
DSH_PROXY_USER/DSH_PROXY_PASSWORD and keep the port firewalled. Extra dsh web arguments can
be passed through the container command, e.g. ["--port", "8080"] (changes only dsh's internal
port; the exposed port stays 3081).

Inside the container, dsh web is supervised by dsh-web: if it exits or crashes it is restarted
automatically. To restart it manually without restarting the container, run:

docker exec dsh dsh-restart

Quick start

Docker Compose (Linux)

docker compose -f examples/compose.yaml up -d
# open http://127.0.0.1:3081

Podman Quadlet (Linux, recommended)

sudo mkdir -p /etc/containers/systemd
sudo cp examples/dsh.container /etc/containers/systemd/
sudo systemctl daemon-reload
sudo systemctl enable --now dsh.service

Persistence — both examples mount one volume at /home/dsh. This is the user layer:
~/.dsh, ~/.cargo, npm/cache/config files, dsh-created working folders, and user-installed
tools survive image upgrades; the system layer (/usr/local, apt packages) comes from the new image.

Networking — dsh web listens on 127.0.0.1 (npm releases reject --host 0.0.0.0); the
entrypoint runs a Caddy reverse proxy on 0.0.0.0:3081 that rewrites Host/Origin to loopback
(→ dsh's 127.0.0.1:3080), so the examples can use plain bridge networking with port 3081
published. See security.md and the
deployment guide for details.

Documentation

Document Contents
docs/deployment.md Deployment & maintenance: prerequisites, Compose, Quadlet, auto-update, remote access, offline use, FAQ
docs/security.md Security notes: network exposure tradeoff, credentials, trusted workloads
docs/build.md Build configuration: build args, version pinning, reproducible builds
docs/releasing.md Image tags, release workflow (GitHub Releases + version alignment), image cleanup
docs/design.md Design references and related projects
docs/development.md Directory structure and local development

License

MIT

安装

🧩 让 Agent 自动装(推荐)

装一次目录插件,之后本站所有插件都能让 DeepSeek Harness 自动找、自动装:

dsh plugin add dshbase-catalog

然后对 agent 说「帮我装 dsh-container」,它会在目录里找到并自动安装。文档:dshbase-catalog · 已验证场景包。

该插件是 GitHub 源码(未发 npm)——直接从仓库装:

Web profile:

dsh plugin --profile web add github:NIyueeE/dsh-container

Headless(CLI)profile:

dsh plugin --profile headless add github:NIyueeE/dsh-container

实测报告

验证通过:从 GitHub 源码完成 L1 安装 + L2 加载 + L3 运行(dsh 0.1.0-rc.6)。

使用场景

扩展 agent 的编码能力面——给它一个新工具、工作流或集成,让它接手以前做不了的开发任务。

适合谁

想让 dsh 在真实代码库上像队友一样干活的开发者——能改、能跑、能验证,而不只是回答问题。

二次开发建议

工具/命令面就是缝:暴露更多 SDK 能力、加更聪明的上下文接线,或收紧改代码与验证之间的循环。

安全:尚未扫描——我们的每日静态扫描将很快覆盖它。

分享徽章

Developer 里更多

浏览全部 7797 个插件 →