Image installs @deepseek-ai/dsh from npm on start. Fork 0.1.2-alpha.2 source is obsolete for this deployment path.
12 KiB
DeepSeek Harness (DSH) Docker 部署指南
概述
本仓库是 DeepSeek Harness 源码 + Docker 构建配置。镜像只内置工具链,不把 dsh 钉死在构建层:容器每次启动由 docker/entrypoint.sh 从 npm 安装官方 @deepseek-ai/dsh@latest(可用环境变量覆盖),安装失败则非零退出,不回退到旧版本。因此启动时必须能访问 npm registry。
端口拓扑(当前实现)
官方 dsh web 只监听 127.0.0.1,并明确拒绝 --host 0.0.0.0(安全原因:Web 面可远程执行代码)。Docker 的 -p 打不到容器内 loopback,故 entrypoint 额外起一层 L4 转发:
宿主机 :3080 → 容器 0.0.0.0:3080 → 127.0.0.1:3081 (dsh web --no-open --port 3081)
┌──────────┐ http://localhost:3080/?token=… ┌─────────────────────────────┐
│ 浏览器 │ ────────────────────────────────▶ │ 0.0.0.0:3080 (转发) │
└──────────┘ │ ↓ │
│ 127.0.0.1:3081 (dsh web) │
└──────────────┬──────────────┘
┌──────────────────────────────┼──────────────┐
│ dsh-data 卷 │ ./workspace │
│ /home/dsh/.dsh │ /workspace │
│ (会话/设置/插件/配置) │ (工作目录) │
└──────────────────────────────┴──────────────┘
浏览器认证(官方包行为)
官方 @latest 强制浏览器认证,没有免 token 的开关:
- 从
docker logs复制带?token=的 URL,用浏览器打开一次 - 服务端
303下发 30 天签名 cookie - 之后同一浏览器直接访问
http://<host>:3080/即可
说明:历史 fork 镜像里的 DSH_TRUST_ALL=1、DSH_TRUSTED_HOSTS 环境变量、默认绑定 0.0.0.0 均不在官方 npm 包中。官方侧 Host/Origin 围栏可用 --trusted-host(compose command 传入)扩展非 loopback 权威;cookie 认证仍必须完成。
镜像信息
当前 Dockerfile 为「运行时拉取」模型:构建产出工具链底座(约 747MB,linux/arm64 本地实测),dsh 版本由每次容器启动时的 @deepseek-ai/dsh@latest 决定,不体现在镜像 tag 里。
| 项目 | 值 |
|---|---|
| 基础镜像 | registry.cn-hangzhou.aliyuncs.com/skymirror/node:24.19.0-bookworm-slim(ARG BASE_IMAGE 可覆盖;内容同 docker.io/library/node:24.19.0-bookworm-slim) |
| dsh 安装 | 启动时 npm install -g @deepseek-ai/dsh@latest(默认 registry.npmjs.org) |
| 宿主机端口 | 3080(compose 3080:3080) |
| 容器内 dsh 端口 | 3081(仅 127.0.0.1) |
| ENTRYPOINT | /usr/local/bin/dsh-entrypoint |
历史镜像存档(已过时,勿按其行为部署)
以下 digest 对应旧 fork 构建时安装镜像(0.1.2-alpha.2-skymirror.1,dist/ pack + file: 闭包、DSH_TRUST_ALL、默认 0.0.0.0)。当前 Dockerfile 已取代该模型,哈希仅备查:
| 项目 | 值 |
|---|---|
| manifest list | sha256:4c8636d1f20804a39757829de5adb27dccf6435b99610e2a70e74fe8cc95b5bd |
| 更早 monorepo 编译镜像 | sha256:8a5d6406abd56f5cc3f175aa6b751e226bc91430dfb896add1fcf9a3f970f39e |
快速开始
git clone <仓库地址>
cd DSH
docker compose build
docker compose up -d
docker logs -f dsh
# 等待出现类似:
# dsh-entry: installed 0.1.5-rc.1
# dsh-entry: forwarding 0.0.0.0:3080 -> 127.0.0.1:3081
# dsh web: http://127.0.0.1:3081/?token=<一次性令牌>
# 把日志 URL 中的 127.0.0.1:3081 换成 127.0.0.1:3080(或服务器 IP:3080)后打开
首次使用时在 Web UI 中配置模型 API Key(DeepSeek 或任意 OpenAI 兼容端点)。
国内网络建议在 compose 的 environment 里加:
- DSH_NPM_REGISTRY=https://registry.npmmirror.com
启动环境变量与参数
环境变量(docker/entrypoint.sh)
| 变量 | 默认 | 说明 |
|---|---|---|
DSH_PACKAGE |
@deepseek-ai/dsh |
要安装的包名 |
DSH_DIST_TAG |
latest |
npm dist-tag 或精确版本(如 0.1.5-rc.1) |
DSH_NPM_REGISTRY |
https://registry.npmjs.org |
拉包 registry;国内可设 https://registry.npmmirror.com |
DSH_NPM_CACHE |
$DSH_HOME/npm-cache |
npm cache(dsh-data 卷内,重启可命中) |
DSH_INTERNAL_PORT |
3081 |
dsh 监听端口(仅 127.0.0.1) |
DSH_FORWARD_PORT |
3080 |
entrypoint 在 0.0.0.0 上的转发端口(Docker -p 应映射此端口) |
传给 dsh web 的参数
entrypoint 固定附加 --no-open --port ${DSH_INTERNAL_PORT}。compose 的 command 会追加在后面,例如:
command: ["--trusted-host", "203.0.113.10"]
| 参数 | 作用 |
|---|---|
--trusted-host <authority> |
向 Host/Origin 围栏追加非 loopback 权威(可重复);不替代 cookie 认证 |
--port / --host |
不要通过 command 覆盖:端口由 DSH_INTERNAL_PORT 管理;--host 0.0.0.0 会被官方拒绝 |
前置条件
- Docker Engine 20.10+(BuildKit)
- Docker Compose v2
- 启动时能访问 npm registry(官方 npmjs 或 npmmirror)
一、不用 Docker 直接跑
# Node.js ^22.19 || >=24
npx --yes @deepseek-ai/dsh@latest web
# 或
npm install -g @deepseek-ai/dsh@latest
dsh web --no-open --port 3080
本机默认只监听 127.0.0.1,浏览器打开日志里的 ?token= URL。管理插件需要 corepack enable pnpm。
查看可用版本:
npm view @deepseek-ai/dsh dist-tags
npm 路径 vs Docker
npx @latest |
Docker(本仓库) | |
|---|---|---|
| 启动耗时 | 首次拉包约 15s–数分钟(视网络/cache) | 镜像已有工具链;每次启动装 dsh(有 cache 更快) |
| 构建 | 无 | 只装 apt/工具链,不编译 monorepo |
| 工具链 | 仅本机 Node | Python / gcc·g++ / pnpm / Rust 按需 |
| 升级 | 每次 npx@latest |
每次容器启动装 @latest(失败退出) |
| 数据 | $DSH_HOME(默认 ~/.dsh) |
dsh-data → /home/dsh/.dsh |
| 远程端口 | 只听 loopback | entrypoint 3080 → dsh 3081 |
二、本地构建并运行
docker compose build
docker compose up -d
构建不需要 pnpm build、release:pack 或 dist/。
基础镜像拉不动时
Docker Hub 在部分网络不可达。可先把官方 node 镜像同步到自己 registry,再:
docker buildx build \
--build-arg BASE_IMAGE=registry.cn-hangzhou.aliyuncs.com/skymirror/node:24.19.0-bookworm-slim \
--platform linux/arm64 \
-t dsh:local-arm64 --load .
清理 buildx 缓存
docker buildx du
docker buildx prune --filter until=24h
# 或
docker buildx prune --all
三、云效构建并推送
流水线「镜像构建」使用仓库根目录 Dockerfile,推送到 ACR。目标机:
docker pull registry.cn-hangzhou.aliyuncs.com/skymirror/dsh:latest
docker run -d --name dsh \
-p 3080:3080 \
-v dsh-data:/home/dsh/.dsh \
-v /path/to/workspace:/workspace \
-e DSH_NPM_REGISTRY=https://registry.npmmirror.com \
registry.cn-hangzhou.aliyuncs.com/skymirror/dsh:latest
注意:推上去的是工具链底座;运行时仍会拉 npm 上的 dsh。请保证部署机可访问所配置的 registry。
四、目录 / 端口映射
| 项目 | 说明 |
|---|---|
宿主机 3080 → 容器 3080 |
entrypoint 的 0.0.0.0 转发口 |
容器内 dsh 3081 |
仅 127.0.0.1,不要单独 -p 映射 |
dsh-data → /home/dsh/.dsh |
会话、settings、storages、profiles(插件)、npm-cache |
./workspace → /workspace |
agent 工作目录;目录选择器默认起点(HOME) |
$DSH_HOME/profiles/<name> |
插件与 profile,卷内持久化 |
dsh 命令 |
启动时 npm install -g 装入 PATH,供 docker exec 管理插件 |
插件示例:
docker exec -it dsh dsh plugin --profile web add <package>
# 改完插件需重启容器
docker restart dsh
五、镜像内置语言环境
| 语言/工具 | 版本 | 说明 |
|---|---|---|
| Node.js | 24.19.0 | 基础镜像 |
| npm | 11.17.0 | 全局升级 |
| pnpm | 11.7.0 | corepack;dsh plugin add 使用 |
| Python | 3.11 | apt,含 pip/venv/Python.h |
| Rust | stable 按需 | 首次调用 cargo/rustc/rustup 时装进 dsh-data 卷 |
| gcc / g++ / make | bookworm | 原生模块编译 |
| git / curl | apt |
不内置 JDK、Go(体积取舍)。需要时进容器自行安装。
构建默认走国内源:npm
npmmirror、Debian 清华、rustup USTC、pip 清华。云效等可出网环境可用--build-arg NPM_REGISTRY=...等覆盖。
Rust 按需安装
/usr/local/bin/ensure-rust 包装器在首次调用时把 toolchain 装进 $RUSTUP_HOME / $CARGO_HOME(均在 dsh-data 卷)。可提前 docker exec dsh cargo --version 触发。
六、自定义配置
修改端口
environment:
- DSH_FORWARD_PORT=8080 # 容器 0.0.0.0 转发口
- DSH_INTERNAL_PORT=3081 # dsh 本机端口(一般不用改)
ports:
- "8080:8080"
从其它机器访问
-
Host/Origin 围栏:浏览器地址为
http://<服务器IP>:3080时,Host 不是 loopback,需在 compose 中追加:command: ["--trusted-host", "<服务器IP或域名>"] -
浏览器认证:仍必须用日志里的
?token=URL 打开一次,换 30 天 cookie。 -
传输与入口:DSH 可执行代码。公网暴露请在前面加带认证/TLS 的反向代理,不要裸奔。
挂载自己的数据目录
volumes:
- /data/dsh:/home/dsh/.dsh
- /data/work:/workspace
七、常见问题
| 现象 | 处理 |
|---|---|
| 启动很慢或退出 | 看 docker logs:多半是装 @latest 网络失败;设 DSH_NPM_REGISTRY=https://registry.npmmirror.com |
authentication required; reopen the URL printed by dsh web |
正常:用带 ?token= 的 URL 打开一次;官方包不能免 token |
GET / 401 |
同上 |
/api 403 |
Host 不在围栏内:给 dsh web 加 --trusted-host <你的Host> |
| 宿主机 3080 连不上 / connection reset | 确认映射的是转发口 3080:3080,且 logs 有 forwarding 0.0.0.0:3080 -> 127.0.0.1:3081 |
--host 0.0.0.0 is intentionally not supported |
官方限制;不要传 --host 0.0.0.0,依赖 entrypoint 转发 |
| 端口被占用 | 改 compose 的 ports 与 DSH_FORWARD_PORT |
Cannot find module .../dsh/lib/bin.js |
自定义了 entrypoint:/command: 绕过安装入口;去掉覆盖后重建 |
| 插件重启后消失 | 插件应装在 $DSH_HOME/profiles(卷内);确认未挂错卷 |
设置了 DSH_TRUST_ALL=1 仍要 token |
预期行为:官方包无此变量;历史 fork 镜像才有 |
附录:fork 私有 npm 发布(可选,当前 Docker 不用)
当前 Docker 路径只消费官方 npm @latest。若仍需维护 skymirror fork 并发到私有 registry,可继续用仓库内 release 脚本(与镜像构建解耦):
pnpm run release:dsh <version>
pnpm run build:official
pnpm run release:pack --family dsh --out dist/npm
# … vendor / landlock / verify / publish,见 scripts/release/
fork 的 DSH_TRUST_ALL、DSH_TRUSTED_HOSTS 环境变量、默认 0.0.0.0 绑定等部署补丁只存在于 fork 编译产物中;要在容器里用它们,需把 DSH_PACKAGE / DSH_DIST_TAG / DSH_NPM_REGISTRY 指到私有 registry 的 fork 包,并自行承担与官方 @latest 的行为差异。