chore: strip monorepo; keep Docker runtime deploy for official dsh@latest

Image installs @deepseek-ai/dsh from npm on start. Fork 0.1.2-alpha.2 source
is obsolete for this deployment path.
This commit is contained in:
SKYMirror committed 2026-09-16 00:18:32 +08:00
commit 0bfe0b4a65
11 files changed
+638

No files matched your search

+285
View File
@@ -0,0 +1,285 @@
# 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 的开关:
1. 从 `docker logs` 复制带 `?token=` 的 URL,用浏览器打开**一次**
2. 服务端 `303` 下发 **30 天签名 cookie**
3. 之后同一浏览器直接访问 `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` |
## 快速开始
```bash
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` 里加:
```yaml
- 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` 会**追加**在后面,例如:
```yaml
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 直接跑
```bash
# 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`。
查看可用版本:
```bash
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` |
## 二、本地构建并运行
```bash
docker compose build
docker compose up -d
```
构建不需要 `pnpm build`、`release:pack` 或 `dist/`。
### 基础镜像拉不动时
Docker Hub 在部分网络不可达。可先把官方 node 镜像同步到自己 registry,再:
```bash
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 缓存
```bash
docker buildx du
docker buildx prune --filter until=24h
# 或
docker buildx prune --all
```
## 三、云效构建并推送
流水线「镜像构建」使用仓库根目录 `Dockerfile`,推送到 ACR。目标机:
```bash
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` 管理插件 |
插件示例:
```bash
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` 触发。
## 六、自定义配置
### 修改端口
```yaml
environment:
- DSH_FORWARD_PORT=8080 # 容器 0.0.0.0 转发口
- DSH_INTERNAL_PORT=3081 # dsh 本机端口(一般不用改)
ports:
- "8080:8080"
```
### 从其它机器访问
1. **Host/Origin 围栏**:浏览器地址为 `http://<服务器IP>:3080` 时,Host 不是 loopback,需在 compose 中追加:
```yaml
command: ["--trusted-host", "<服务器IP或域名>"]
```
2. **浏览器认证**:仍必须用日志里的 `?token=` URL 打开一次,换 30 天 cookie。
3. **传输与入口**:DSH 可执行代码。公网暴露请在前面加带认证/TLS 的反向代理,不要裸奔。
### 挂载自己的数据目录
```yaml
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 脚本(与镜像构建解耦):
```bash
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` 的行为差异。