Sign inSign up

runzhliu/deepseek-harness

By runzhliu

•Updated 5 days ago

Community Docker, Compose, and Helm runtime for DeepSeek Harness on amd64 and arm64.

Image
0

10K+

runzhliu/deepseek-harness repository overview

⁠DeepSeek Harness Docker

English⁠ | 简体中文

Upstream DSH Container Release Docker Image GHCR 腾讯云 SkillHub Node.js License

这是一个可直接构建的 DeepSeek Harness 社区容器方案,默认运行官方 @deepseek-ai/dsh 的 Web UI。它不构建或修改 DeepSeek Harness 源码,只把官方 npm 发行物装入一个精简、非 root 的 Node.js 24 运行时。

当前基线:@deepseek-ai/[email protected]。DeepSeek Harness 仍处于预发布阶段;升级前应重新完成本文的构建和 Smoke Test。

0.1.7-rc.2 直接对应官方 dsh-v0.1.7-rc.2⁠ Release 与 npm Registry 的 @deepseek-ai/[email protected]⁠,并非本项目自定义版本。本项目封装 npm 成品而不从源码构建,因此以可安装的官方发行物为基线,并故意不发布漂移的 Docker latest 标签。

上游已发布可安装的显式 npm 版本;Registry 镜像与 dist-tag 的更新可能短暂滞后,本项目始终固定完整版本,避免 dist-tag 漂移。0.1.7-rc.2 新增可持久化的定时任务、Web/桌面快捷键管理和对话中热启用工具,并修复长对话持续无法发送消息、过长工具输出损坏后续对话,以及异常退出后插件安装和设置保存持续失败等问题。

升级提醒: 0.1.7-alpha.1 起 Session 日志为 V4。若从更早版本升级,必须先备份 dsh-home;依赖旧日志结构的工具需要适配 V4,降级前也应恢复升级前的卷备份,而不是让旧版直接读取已迁移数据。

兼容性提醒: 自定义 spill-policy 配置必须把 maxInlineBytes 改为按估算 Token 计数的 maxInlineTokens。内置 E2B 执行后端已移除,PTC 与 Workflow 服务已重命名;若从 0.1.7-alpha.1 以前升级,还需处理 Messages-only adapter、Profile-owned 设置、Bundle Agent Preset 和 Remote readBytes 迁移。详见官方 Release⁠。

RC2 行为调整: Web 默认关闭定时任务与时间上下文,需要时在插件管理中手动启用;Inspector 不再内置,必须作为独立插件安装。API Key 任务与账号任务也使用各自独立的模型入口。

上游版本跟踪:每日运行的 Upstream DSH version watch⁠ 会同时检查 GitHub Release 与 npm。若新版 Release 已发布但 npm 制品尚不可用,工作流会创建或刷新等待 Issue 并保留当前可安装基线;同版本 npm 包可安装后,Issue 会自动切换为升级提醒,固定版本追平后再自动关闭。

📖 延伸阅读:DeepSeek Harness GitHub 仓库深度解析⁠ · Docker、Compose 与 Helm 部署实战⁠

🤖 **Agent Skill:**根目录的 SKILL.md⁠ 已作为 deepseek-harness-docker⁠ 发布到腾讯云 SkillHub,可供支持 Agent Skills 的客户端安装和使用。它指导 Agent 按本项目的安全边界完成 Docker Compose/Helm 部署、验证、升级与排障;这是部署辅助 Skill,不是 DSH 运行时插件。

DeepSeek Harness Web UI running from this image

⁠项目状态

能力状态验证结果
Dockerfile可用linux/arm64、linux/amd64 构建与原生 PTY 实际启动均已验证
Docker Compose可用Web token/cookie 认证、healthy、回环端口、重启持久化已验证
Rootless Podman可用keep-id 用户映射、bind mount 写入、命名卷持久化与回环端口已纳入 CI
Helm可用单副本 StatefulSet、PVC、Headless Service、NetworkPolicy;helm lint --strict 通过
Web UI本机默认;可选受保护 LAN默认仅回环访问;LAN overlay 提供 HTTPS、Basic Auth、DSH token/cookie 与同源 noVNC
Headless可用运行时注入 provider Secret;需在目标环境验证实际模型调用和沙箱
Chromium默认 + 可选隐私变体Debian Chromium 默认镜像;独立 ungoogled-chromium 双架构镜像会验证无 GCM :5228 活动

Docker Hub 展示页由 GitHub README 自动生成;完整的架构分析请阅读 GitHub 仓库 README⁠。

⁠快速开始

在本目录执行:

docker compose pull
DSH_WORKSPACE=/absolute/path/to/your/project docker compose up -d --no-build
docker compose ps
docker compose logs --no-color deepseek-harness | grep 'dsh web:'

打开日志中 dsh web: 后面带 ?token=... 的完整 http://127.0.0.1:3080⁠ 地址。Harness 会把当前进程的启动 token 换成签名 Cookie,再跳转到干净的根路径;直接打开不带 token 的根地址会返回 401。进入后在设置页配置模型和凭据。侧边栏的“浏览器桌面”按钮会在 Harness WebUI 内直接打开可交互的容器 Chromium;配置和浏览器 Profile 写入命名卷 dsh-home,重建容器后仍会保留。

未设置 DSH_WORKSPACE 时,Compose 使用独立的 dsh-workspace 命名卷,避免 Agent 意外修改本仓库。只有准备好明确的项目目录后,才通过 DSH_WORKSPACE=/absolute/path/to/project 改用 bind mount。

默认镜像修订版为 Docker Hub 上的 runzhliu/deepseek-harness:0.1.7-rc.2-r1⁠,同一份多架构制品也会发布到 GitHub Container Registry:ghcr.io/runzhliu/deepseek-harness:0.1.7-rc.2-r1⁠。r1 将同版本官方 Playwright MCP Browser Use attach 到可视 Chromium,并继续使用带版本的 noVNC 静态资源路径,避免升级后浏览器缓存混用不兼容的 ES Module。Compose 同时保留 build 配置,方便审查并从本目录复现镜像;如需本地构建,执行 docker compose build --pull 后再启动。

⁠Rootless Podman

见 完整文档⁠。

⁠可选的 HTTPS 局域网访问

不要直接发布 3080/6080。可选 compose.lan.yaml⁠ 在指定 LAN IP 提供 Caddy HTTPS + Basic Auth,保留 DSH token/cookie 与 Host/Origin 校验,并同源代理 noVNC。

先创建私有配置并生成密码哈希:

cp .env.lan.example .env.lan
docker run --rm -it caddy:2.11.4-alpine caddy hash-password

编辑 .env.lan:填写确切 LAN IP(禁止 0.0.0.0)、客户端可解析的内网域名或 IP、单引号包裹的 bcrypt 哈希及可选工作区,然后启动:

make lan-up
make lan-logs

Caddy 默认使用内部 CA。将根证书安装到受信任客户端的系统信任库:

docker compose --env-file .env.lan -f compose.yaml -f compose.lan.yaml \
  cp lan-gateway:/data/caddy/pki/authorities/local/root.crt ./dsh-lan-root.crt

从 dsh web: 日志 URL 取 ?token=...,首次用 https://DSH_LAN_HOST:8443/?token=... 打开。完成两层认证后即可使用干净地址。make lan-down 保留数据卷。8443 兼容 rootless 运行时。

该模式不是多租户:登录者共享会话、凭据及 Agent 权限;不互信用户须拆分实例和卷。用防火墙限制来源,禁止转发公网。make lan-smoke 可验证边界。

⁠浏览器桌面、官方 Browser Use 与人工接管

镜像把官方 Playwright MCP Browser Use attach 到同一个持久化 Chromium;插件负责 noVNC 可视桌面与人工接管,详见 完整浏览器说明⁠。

⁠可选的 ungoogled-chromium 镜像

默认镜像继续使用 Debian Chromium,以保留 Debian 安全更新与发行版供应链。对浏览器空闲后台连接有严格要求时,可显式选择独立的 runzhliu/deepseek-harness:0.1.7-rc.2-r1-ungoogled.1⁠ 变体:

export DSH_IMAGE_VERSION=0.1.7-rc.2-r1-ungoogled.1
docker compose pull
DSH_WORKSPACE=/absolute/path/to/your/project docker compose up -d --no-build

该镜像固定 [email protected],分别校验 amd64 与 arm64 下载包的 SHA256。Smoke Test 会启动完整 Harness/noVNC 桌面、验证官方 Browser Use attach 配置并调用 browser_open,随后断言不存在 GCM 5228 连接与 google_apis/gcm 日志。它还自动使用 /home/node/.dsh/chrome-profile-ungoogled,不会与默认 Debian Chromium 的 Profile 混用。GHCR 使用相同标签;Helm 可显式设置 --set image.tag=0.1.7-rc.2-r1-ungoogled.1。

这个变体采用 ungoogled-chromium-portablelinux⁠ 的社区 portable 构建,并非 Debian 官方软件包。上游二进制索引⁠明确提示贡献者二进制不一定可复现、真实性无法完全保证;同时 Google Safe Browsing、同步、推送、Widevine 和扩展商店集成可能缺失或需要手动配置。因此它不会替换默认镜像,也不会发布为 latest。本地复现与验证:

make ungoogled-build
make ungoogled-smoke
⁠独立安装浏览器插件

插件已经按 DSH bundle 规范拆到 plugins/dsh-browser-desktop⁠,可独立打包:

npm pack ./plugins/dsh-browser-desktop --pack-destination /tmp
dsh plugin --profile web add /tmp/runzhliu-dsh-browser-desktop-0.1.3.tgz

0.1.3 插件保留 0.1.2 对 DSH client module system 的兼容,并明确定位为 Browser Use 的可视化与人工接管层;旧 DSH 0.1.0/0.1.1 RC 应继续使用插件 0.1.1。发布到 npm 后可直接执行 dsh plugin --profile web add @runzhliu/dsh-browser-desktop。该 npm 包只负责 Harness Host/WebUI 集成,不会自行安装 Chromium、Xvfb、noVNC 或官方 Browser Use provider;本仓库 Docker 镜像是完整的参考运行时。官方 DSH 通过 npm/GitHub 和 dsh-plugin GitHub topic 发现社区插件。

⁠可选的社区插件市场

默认镜像、默认 Compose 和 Helm Chart 不包含也不加载插件市场,它们只跟随官方 @deepseek-ai/dsh 发行物。需要图形化浏览和安装社区插件时,可以显式选择独立的 dshmarket⁠ 变体:

docker compose -f compose.yaml -f compose.market.yaml pull
DSH_WORKSPACE=/absolute/path/to/your/project \
  docker compose -f compose.yaml -f compose.market.yaml up -d --no-build

该变体使用明确区分的 runzhliu/deepseek-harness:0.1.7-rc.2-r1-market.1 标签,固定 [email protected],不会替换默认 DSH 标签或 latest。它属于社区可选集成,不是 DeepSeek 官方组件,也不代表本项目对市场条目的审核或背书。

市场自身在构建期固定并打入可选镜像;通过市场安装的插件和 pnpm store 会写入持久化的 dsh-home 卷。安装过程需要容器能够访问 npm/GitHub,第三方包的构建脚本仍应在审查后单独授权。市场内的一键重启已禁用,变更需要通过 docker compose restart 或 Kubernetes rollout 进入新进程。

本地验证可选变体:

make market-build
make market-smoke

Helm 仍默认官方 DSH 镜像;只有明确设置 --set image.tag=0.1.7-rc.2-r1-market.1 时才使用市场变体。

如果复用的 dsh-home 曾被另一个 pnpm 主版本处理,安装时可能看到 ERR_PNPM_UNEXPECTED_STORE。先停止 DSH,再显式执行一次迁移:

docker compose -f compose.yaml -f compose.market.yaml stop deepseek-harness
docker compose -f compose.yaml -f compose.market.yaml run --rm --no-deps \
  --entrypoint dsh-market-repair-store deepseek-harness
docker compose -f compose.yaml -f compose.market.yaml up -d --no-build

迁移只按现有 package.json 重新链接依赖,固定使用 /home/node/.dsh/pnpm-store,并传入 --ignore-scripts。旧的 node_modules 会保留在 /home/node/.dsh/backups/pnpm-store-*,确认插件正常后再自行清理。

可选镜像启动时还会检查已有的 profiles/web/cordis.patch.yml:如果它是普通文件但因旧 UID 不可写,入口脚本会用内容完全相同、归当前运行用户所有的副本替换它,从而恢复插件开关;不会递归修改整个卷,符号链接或非普通文件只会给出警告。

本公开分支不打包任何公司内部模型、凭据、Skill 或个人工作区挂载。模型在 Harness 设置页配置;额外凭据和私有扩展应放在运行时 Secret、被忽略的 .env 或本机 compose.local.yaml 中。

查看日志和停止服务:

docker compose logs -f deepseek-harness
docker compose down

docker compose down 不删除命名卷。只有明确执行 docker compose down --volumes 才会删除持久化的配置、凭据、会话,以及默认 dsh-workspace 卷中的全部工作区数据;使用该参数前必须先备份需要保留的内容。

⁠直接使用 Docker

构建镜像:

docker build -t runzhliu/deepseek-harness:0.1.7-rc.2-r1 .

启动 Web UI:

docker volume create dsh-home
docker run --rm \
  --name deepseek-harness \
  --publish 127.0.0.1:3080:3080 \
  --publish 127.0.0.1:6080:6080 \
  --shm-size 1g \
  --mount type=volume,src=dsh-home,dst=/home/node/.dsh \
  --mount type=bind,src="$PWD",dst=/workspace \
  runzhliu/deepseek-harness:0.1.7-rc.2-r1

启动命令会直接打印带 token 的访问地址,请打开该完整地址。不要把端口参数改成 -p 3080:3080,也不要把它部署到公开 Ingress;Web 没有 TLS,6080 上的 noVNC 也没有认证。

⁠Headless 模式

镜像的入口等价于执行 dsh,因此可以用运行参数覆盖默认 Web 命令:

docker run --rm \
  --env DEEPSEEK_API_KEY \
  --mount type=volume,src=dsh-home,dst=/home/node/.dsh \
  --mount type=bind,src="$PWD",dst=/workspace \
  runzhliu/deepseek-harness:0.1.7-rc.2-r1 \
  --profile headless "summarize this repository"

API Key 只应在运行时通过环境变量、Secret 或 Web 设置传入,不能写进 Dockerfile、镜像层或构建参数。

⁠Kubernetes / Helm

charts/deepseek-harness 使用单副本 StatefulSet。/home/node/.dsh 由 PVC 持久化,工作区可以使用独立的现有 PVC;Chart 不创建 Ingress 或 LoadBalancer,并默认创建拒绝 Pod 入站流量的 NetworkPolicy。

默认使用已发布的 Docker Hub 镜像,直接安装 Chart:

helm upgrade --install deepseek-harness charts/deepseek-harness \
  --namespace deepseek-harness \
  --create-namespace \
  --set image.repository=runzhliu/deepseek-harness \
  --set image.tag=0.1.7-rc.2-r1

本机开发集群也可以直接拉取默认的 runzhliu/deepseek-harness,或先用 kind load docker-image / minikube image load 导入同名本地镜像。

通过 API Server 安全转发到本机浏览器:

kubectl -n deepseek-harness rollout status statefulset/deepseek-harness
kubectl -n deepseek-harness port-forward service/deepseek-harness 3080:3080 6080:6080

另开终端执行 kubectl -n deepseek-harness logs statefulset/deepseek-harness | grep 'dsh web:',然后打开日志中带 token 的完整 http://127.0.0.1:3080⁠ 地址;内嵌桌面通过同一条命令转发到 http://127.0.0.1:6080⁠。不要把无 TLS 的 Web surface 或无认证的 noVNC 改成 NodePort、LoadBalancer 或直接接入 Ingress。

如需通过 Secret 注入 provider 环境变量:

kubectl -n deepseek-harness create secret generic dsh-provider-credentials \
  --from-literal=DEEPSEEK_API_KEY='replace-me'

helm upgrade deepseek-harness charts/deepseek-harness \
  --namespace deepseek-harness \
  --reuse-values \
  --set credentials.existingSecret=dsh-provider-credentials

如需持久化工作区,先创建 PVC,再设置 workspace.existingClaim。未设置时 /workspace 是临时 emptyDir。卸载 Chart 后,StatefulSet 创建的 dsh-home PVC 默认保留;确认不再需要配置、凭据和会话后再手动删除。

helm uninstall deepseek-harness --namespace deepseek-harness
kubectl -n deepseek-harness get pvc

⁠升级版本

构建参数控制安装的 DSH 版本:

docker build \
  --build-arg DSH_VERSION=0.1.7-rc.2 \
  --build-arg IMAGE_VERSION=0.1.7-rc.2-r1 \
  -t runzhliu/deepseek-harness:0.1.7-rc.2-r1 .

Compose 分别使用上游版本和不可变镜像修订版:

DSH_VERSION=0.1.7-rc.2 DSH_IMAGE_VERSION=0.1.7-rc.2-r1 docker compose build --pull

维护者可用 make push 构建并推送同一个不可变修订标签下的 linux/amd64 与 linux/arm64 manifest。目标标签已经存在时命令会拒绝覆盖,也不会创建 latest 标签。

可选市场变体使用独立的 make market-push,只发布带 -market.1 后缀的双架构标签,不改变默认镜像。

Mirror Docker Hub images to GHCR⁠ 工作流使用现有 Docker Hub manifest 创建 GHCR 碳拷贝,不重新构建镜像。发布以 image-v 开头的 GitHub Release 时会同步基础标签;维护者也可手动指定版本,并选择同时同步 -market.1 变体。同步后会比较源和目标的全部平台 manifest digest,且不会创建 latest。

不要默认安装 latest。RC 版本正在快速变化,固定版本才能让问题可复现。

⁠安全边界

  • 容器默认以镜像内的 node 用户(UID/GID 1000)运行;如果宿主工作区拒绝该 UID 写入,需要调整目录权限或构建适配本机 UID 的派生镜像。
  • Web 目录选择器中的“主目录”是 /workspace,不是保存内部配置的 /home/node;通过 Compose 或 Kubernetes 挂载的工作区必须可由 UID 1000 写入。
  • DSH 服务丢弃全部 Linux capabilities;LAN gateway 因官方 Caddy 二进制的 file capability 仅保留 NET_BIND_SERVICE。两者均启用 no-new-privileges、只读根文件系统和独立 /tmp tmpfs。
  • 只挂载需要 Agent 操作的工作区。不要挂载宿主根目录、~/.ssh、云凭据目录或 Docker socket。
  • Docker 隔离不是多租户安全沙箱。不要把这个实例交给不受信任用户,也不要把未审查的插件装进持久化配置卷。
  • LAN overlay 只为可信内网增加传输加密和外层认证,不提供用户级授权或会话隔离;始终绑定确切 LAN IP、限制防火墙来源,并为不互信用户部署独立实例。
  • DeepSeek Harness 自己的 Linux 沙箱能力受宿主内核和容器运行时影响;镜像不会通过 --privileged 或额外 capabilities 绕过失败。应保留其默认权限模式,并验证真实工具调用。

⁠Smoke Test

每次升级至少完成以下检查:

docker run --rm --entrypoint dsh runzhliu/deepseek-harness:0.1.7-rc.2-r1 --version

docker run --rm --entrypoint dsh runzhliu/deepseek-harness:0.1.7-rc.2-r1 \
  web --patch /opt/deepseek-harness/web.cordis.patch.yml --dump-config

docker compose up -d
test "$(curl --silent --output /dev/null --write-out '%{http_code}' http://127.0.0.1:3080/)" = 401
make smoke
make lan-smoke
docker compose ps
docker compose logs --no-color deepseek-harness

通过标准包括:CLI 版本等于构建版本;dump 后的 webserver.config.host 为 0.0.0.0;未认证首页返回 401,启动 token 能换取 Cookie 并加载首页;容器进入 healthy;日志没有配置或插件加载错误;容器不会尝试调用宿主默认浏览器。真正发布镜像前还要分别在 linux/amd64 和 linux/arm64 上构建并实际 spawn PTY,因为终端与沙箱相关依赖包含原生模块。仓库提供 make verify、make build 和 make smoke 作为默认入口;可选市场另用 make market-build 和 make market-smoke,并额外验证默认镜像中不存在市场包。

⁠常见问题

如果 Web 新建文件夹时报 EROFS: read-only file system, mkdir '/home/node/...',说明容器仍在运行早期镜像或旧容器。当前镜像把目录选择器的主目录设为 /workspace。重新构建并强制重建容器:

docker compose build
docker compose up -d --force-recreate
docker compose exec deepseek-harness node -e "console.log(require('node:os').homedir())"

最后一条命令应输出 /workspace。如果错误变成 /workspace 下的 EACCES,则是宿主 bind mount 与容器 UID 1000 的权限不匹配;修正工作区所有权/权限,或构建使用匹配 UID 的派生镜像,不要改成 root 运行。

⁠文件

完整目录结构见 GitHub README⁠。

本目录是社区实现,不代表 DeepSeek 官方发布的容器镜像。

Tag summary

Content type

Image

Digest

sha256:ed1260bb7…

Size

1005.6 MB

Last updated

5 days ago

docker pull runzhliu/deepseek-harness:0.1.7-rc.2-r1-ungoogled.1