← 返回列表
未验证
DeepSeek HarnessDSH的 Docker 沙箱,DSH 是一个编码
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/18 · 已提供中文文档
在隔离的 Docker 沙箱中运行 DeepSeek Harness,支持外部项目插件以及基于 Git 的主机/代理变更传输。
综合分
30.6
GitHub 分
30.6
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add omni-/containerize-dsh该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/20(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
DSH 沙箱
一个用于
DeepSeek Harness(DSH)的 Docker 沙箱,DSH 是一个编码
代理。DSH 在容器内获得广泛的权限,而宿主机检出目录、
其 .git、宿主机凭据存储以及 Docker socket 都与该代理隔离。
该代理可以读取显式提供给 DSH 的凭据,以及包含在
传输的 Git 历史中的机密。
工作通过使用 Git bundle 的隔离检出目录进行流转。外部插件可以添加
项目工具链和 MCP 配置,并且需要显式选择。宿主机需要
Python 3.10+、Git,以及带 Compose v2 的 Docker;在 Windows 上 Docker Desktop 必须使用 Linux
容器。不需要任何 Python 依赖。
Dockerfile 通用 DSH、Node、Git 和辅助镜像
compose.yaml 隔离、localhost Web 和持久化卷
dsh.py 宿主机启动器和传输命令
scripts/start-dsh.sh 认证、运行时钩子和 Web 启动
scripts/git_transfer.py 临时索引快照和 Git bundle
scripts/workspace.py 容器侧检出操作
examples/hello/ 无害的可选示例插件
docs/plugins.md 插件契约
tests/ Git 和 Docker 集成测试
启动
从此目录运行(或使用 dsh.py 的绝对路径):
python dsh.py build
python dsh.py init --repo /path/to/host-repository
python dsh.py up
python dsh.py url
打开 url 打印出的 localhost 登录 URL(其中包含 DSH 的浏览器令牌)。
请将该 URL 视为凭据。通过 DSH 的 UI 输入提供商凭据,或在启动进程中设置
DEEPSEEK_API_KEY。或者在命令前传入
--key-file /outside/public-repo/deepseek-key。该文件仅包含
API 密钥,并以只读方式挂载;它必须可被 UID 10001 读取。
在 DSH 中输入的凭据会持久保存在其私有 home 卷中。启动 UI 不需要密钥。
与模型提供商的认证与 Web 访问是分开的:
DSH 的浏览器令牌和 localhost 发布保护 Web 访问;不要将此
端口公开转发。核心显式信任已发布的 localhost 授权。
在每次调用时显式选择一个插件:
python dsh.py --name sample --plugin examples/hello build
python dsh.py --name sample --plugin examples/hello init --repo /path/to/repository
python dsh.py --name sample --plugin examples/hello up
python dsh.py --name sample --plugin examples/hello validate
绝对外部插件路径的工作方式完全相同,包括带
空格的路径。为每个项目/插件选择一个不同的 --name;它用于命名持久化的
home 和工作区卷。不要针对同一组卷运行两个沙箱。
--port 更改 localhost 端口。全局选项位于命令之前。
up 创建/重新创建容器而不构建;镜像更改后请运行 build。
已保存的用户配置文件
对于经常使用的插件,请在你的用户配置目录中创建 containerize-dsh/profiles.json。如有需要,创建其父目录:
- Windows:%APPDATA%\containerize-dsh\profiles.json(通常位于 AppData\Roaming 下)。
- macOS:~/Library/Application Support/containerize-dsh/profiles.json。
- Linux:$XDG_CONFIG_HOME/containerize-dsh/profiles.json,如果未设置,则为
~/.config/containerize-dsh/profiles.json。相对 XDG 路径会被忽略。
该文件是一个以配置文件名称为键的 JSON 对象。例如,将路径替换为你自己的绝对路径(Windows 路径可以使用正斜杠):
{
"my-project": {
"plugin": "/private/my-project/.dsh-plugin",
"repo": "/private/my-project",
"name": "my-project-sandbox",
"port": 11127,
"key_file": "/private-secrets/deepseek-key"
}
}
所有五个字段都是可选的。key_file 是一个路径,绝不是 API 密钥;省略它以使用现有的环境/UI 身份验证。不接受其他字段。保存的路径必须是绝对路径或以 ~ 开头;它们不依赖于当前目录。请将此注册表保存在这个公共仓库之外,并排除在 Git 之外。
python dsh.py --profile my-project up
python dsh.py --profile my-project init
python dsh.py --profile my-project --name another-sandbox --port 11128 up
python dsh.py --profile my-project status --repo /another/host-checkout
与显式选项一样,在首次 up 之前运行 build 和 init;init 要求工作区为空。保存的 repo 为 init、refresh、import 和 status 提供默认值;它绝不会挂载宿主机检出。显式 CLI 参数会覆盖保存的值,包括等于原始默认值的值。不使用 --profile 时,不会读取注册表,现有命令照常工作。没有默认配置文件或当前目录插件发现:每次调用时都要显式选择 --profile 或 --plugin。选择配置文件会像传递 --plugin 一样信任其插件;现有的插件、密钥文件和 Compose 隔离检查仍然适用。未知配置文件或无效的所选条目会在 Docker 运行之前失败。编辑 JSON 文件以添加、重命名或删除配置文件;启动器绝不会写入凭据或配置文件。
在单独的检出中工作
宿主机和 /workspace 是独立的 Git 仓库。编码代理编辑一个隔离的检出;宿主机检出不会挂载到容器中。传输使用 Git 捆绑包来携带 Git 对象和选定的引用,绝不使用宿主机 .git、远程、钩子、凭据助手、SSH 密钥、GitHub 凭据或 Docker 套接字。
在执行任何工作区命令(包括 status)之前停止沙箱,除非使用 export --force。停止可防止代理与检出或快照发生竞争。不要启动并发的维护命令,也不要在一个命令运行时从另一个终端启动服务。
python dsh.py stop
使用选定的已提交修订版本:
python dsh.py refresh --repo /path/to/host-repository --revision main
或者捕获当前已跟踪的工作树内容,而不更改真实索引:
python dsh.py refresh --repo /path/to/host-repository --snapshot
选择同时纳入新的、未被忽略的文件:
python dsh.py refresh --repo /path/to/host-repository --snapshot --include-untracked
python dsh.py status --repo /path/to/host-repository
python dsh.py up
init 要求卷为空。refresh 会拒绝脏的、未跟踪的以及被忽略的
工作区文件;它绝不会重置或清理它们。在切换到新的 dsh/work- 分支之前,
它会在 dsh/archive- 下保留旧的已提交 HEAD。
提交/导出工作成果,并手动归档/移除可丢弃的构建产物,或者
使用新的沙箱名称以保持整个旧工作区不变。
快照使用从 HEAD 初始化的临时索引和一个合成的子提交。
它们捕获工作树内容,而不是暂存/未暂存的划分。默认情况下,它们
只包含 HEAD 中已跟踪的路径;新暂存的文件还需要
--include-untracked。被忽略的文件会被排除,除非它们已被跟踪。
在快照期间不要编辑宿主:这不是原子文件系统快照。
在选择纳入之前,请审查将要传输的文件,包括已跟踪的机密信息。
临时引用随后会被删除;合成对象会保留到 Git GC 为止。
将工作成果带回以供审查
sh
python dsh.py stop
python dsh.py export --bundle /private/transfers/work.bundle
如果代理尚未提交其编辑:
python dsh.py export --snapshot --include-untracked --bundle /private/transfers/dirty-work.bundle
或者在不停止正在运行的沙箱的情况下导出:
python dsh.py export --force --snapshot --include-untracked --bundle /private/transfers/live-work.bundle
python dsh.py import --repo /path/to/host-repository --bundle /private/transfers/work.bundle --branch dsh/review-feature
export --force 仅绕过正在运行的沙箱检查;它不会停止或重启
沙箱,也不会覆盖现有 bundle。并发编辑可能使实时
快照不一致,或导致导出失败。
导入会创建一个新的本地审查分支,并打印源宿主提交和 DSH
基线。在获取之前,它要求记录的宿主提交已存在于
目标仓库中;不相关的仓库会被拒绝。宿主自传输以来可能已经
前进,并且不需要检出该提交。
它绝不会检出、合并、推送或覆盖现有分支。它适用于
脏的宿主和链接的 Git 工作树。使用 git diff dsh/review-feature
和 git log ..dsh/review-feature 进行审查;显式地拣选所需的提交。
如果基线是快照,它已经包含宿主的未提交编辑:在选择仅代理的工作成果时,
排除该基线提交。导出快照不会清理或
提交实时工作区。现有导出文件绝不会被覆盖。
status 打印原始宿主提交、传输的基线、当前代理 HEAD、
base 与 HEAD 提交计数(先是仅 base,然后是仅 agent),以及脏文件。使用 --repo
时,它还会显示当前主机 HEAD、其是否发生变化,以及主机脏文件,因此即使仓库具有
不同的路径或分支,你也能看到分歧。
Bundle 包含选定的提交历史,包括历史文件内容;请将其保密。它们不包含被忽略的
产物、LFS 对象载荷或子模块仓库。快照模式拒绝子模块;修订模式仅携带 gitlink。
请通过你的私有插件单独提供这些依赖项。浅克隆仓库可能产生依赖前置条件的 bundle,
从而导致验证失败;请使用完整的源克隆。一次只传输一个仓库。
日常工作流程
任务启动器会在唯一任务 ID 下记录每个沙箱及其传输。从你想要处理的仓库中,使用
已安装的命令:
powershell
dsh-task start --task fix-parser --open
Optional saved settings: --profile my-project
Optional: --repo --target --revision
Dirty baseline instead: --snapshot [--include-untracked]
Another simultaneous task: --port 11128
Rebuild core/plugin images explicitly: --rebuild
在没有 --profile 的情况下,启动器使用当前仓库(或 --repo)、无插件、端口
11111,以及来自环境的 DEEPSEEK_API_KEY。你也可以在 DSH 浏览器 UI 中输入
凭据。除非你明确选择一个配置,否则它不会加载已保存的配置设置。如果没有已安装的
命令,请调用
python /path/to/containerize-dsh/dsh_task.py start --task fix-parser --open。
配置的沙箱名称会被替换为新的任务命名空间。
任务配置必须使用任务自有的 home/workspace 卷,而不是外部/共享卷覆盖。现有镜像
会被复用;在更改镜像输入后请重新构建。
启动器会打印唯一的任务 ID 和浏览器 URL。它从不挂载主机检出。在该浏览器中与
DeepSeek 协作,然后导出任务以供主机侧审查。
任务清单和不可变审查 bundle 位于用户配置注册表旁边的 tasks// 下,
在源仓库之外。记录包括仓库身份、预期目标、实际源 HEAD、确切传输的 base、
解析后的设置、Docker 身份、审查引用/报告以及集成结果。
将此状态视为私有。python dsh_task.py show 无需对话历史即可解析它。
被中断/失败的操作会保留其记录和资源。
若要仅导出 bundle 而不创建审查,请使用:
powershell
dsh-task export --force --snapshot --include-untracked --bundle work.bundle
dsh-task import --bundle work.bundle
当恰好有一个活动任务属于当前 Git 仓库(包括其链接的工作树)时,可以省略任务
ID。--force 会保持沙箱运行;并发编辑可能会产生不一致的快照。没有
--snapshot,仅导出已提交的工作。现有 bundle 文件绝不会被
覆盖。省略 --bundle 将保留正常的审查导出工作流。
dsh-task import 默认使用当前目录;使用 --repo 指定另一个
仓库。它会创建一个新的本地分支并打印其名称,无需审查、
切换分支或合并。可选地使用
--branch dsh/review-feature 选择其名称。导入不需要任务 ID 或 Docker。
使用以下主机命令来导出、记录你的审查、准备集成,并在验证后
清理:
text
python dsh_task.py export [--include-untracked]
python dsh_task.py reviewed --revision --report
python dsh_task.py prepare
python dsh_task.py finalize --checks
python dsh_task.py cleanup [--require-integrated]
python dsh_task.py resume
python dsh_task.py url
导出会暂停 DeepSeek 并使其保持停止状态。新文件需要显式包含。
每次导出都会创建一个新的可恢复审查 ref。审查会将 agent 修订版本
与记录的已传输基线进行比较,分离出已有的脏基线更改。
集成仅在一个单独的工作树中应用该增量。基线依赖
或冲突会阻止准备;脏/已移动的目标会阻止最终化。
准备好的分支保持可用,集成不会被报告为完成。
报告记录人工/主机代理验证,而非自动的质量保证。
清理是显式的,并会拒绝已更改或未保留的工作、被忽略的文件以及
未完成的请求集成。它会移除确切的任务容器/工作区
卷以及干净的已记录集成工作树,保留 home/session 历史、
恢复 bundle/ref/报告、镜像、缓存、插件和网络。仅审查
绝不会修复代码、更改目标或删除任务。不要通过较低级别的 Docker 或启动器命令
并发操作同一任务。进程终止后遗留的
lock 只有在确认没有任务操作仍在进行后才能移除。
对于真正一次性的会话,请改为显式丢弃其容器工作:
text
dsh-task discard
Without the installed wrapper: python dsh_task.py discard
这会永久移除任务容器和工作区,包括未提交、
未跟踪和被忽略的文件,无需导出、审查或集成。
该命令在更改资源前会要求 [y/n] 确认。只有 y
(不区分大小写)才会继续;空输入、任何其他回答或中断的输入都会取消。
所有权检查仍然适用。DSH home/session 历史、任务记录、现有
导出、主机工作树和共享资源会保留。重复 discard 是安全的。
可选附加功能:Codex 任务助手
捆绑的 dsh-work Codex 技能 是一个可选附加功能,
用于从主机侧审查、集成和清理已完成的 DSH 任务。
不需要 Codex。该技能使用上文描述的相同任务清单和 Git 传输命令;你也可以直接使用 CLI 和手动工作流。
要安装或更新它,请从此仓库运行:
sh
python scripts/install_workflow.py
这会将仓库的规范技能源复制到你的用户级 Codex 技能目录($CODEX_HOME/skills,或 ~/.codex/skills),并安装 dsh-task 命令包装器。在 Windows 上,安装程序会将包装器添加到你的用户 PATH;之后请重新打开终端。在 Linux/macOS 上,确保 ~/.local/bin 在 PATH 中。重启 Codex 以发现该技能。请保留此检出目录和 Python 解释器,或在移动它们后重新运行安装程序。在仓库中进行技能编辑,并重新运行安装程序以刷新受管理的副本,包括删除过时的文件。
在宿主 Codex 中,显式调用它:
text
$dsh-work review
$dsh-work integrate and clean up
隔离与生命周期
核心以 UID/GID 10001 运行,具有只读根文件系统、所有能力被丢弃、no-new-privileges、可写临时文件系统,以及在 /home/agent 和 /workspace 处的持久命名卷。互联网访问保持启用,以供 DSH 和软件包下载使用。DSH 的完全访问权限模式在此边界内运行。代理可以读取自己的提供方密钥和挂载的插件运行时文件。
shell、logs、validate、stop、restart 和 down 是宿主辅助命令。down 会移除容器/网络,但保留卷。dsh.py 没有删除卷或重置工作区的命令。如果你需要保留 DSH 会话/设置,请单独备份 home;Git 捆绑包仅涵盖仓库内容。
启动器不会将插件安装到此仓库中,也不会扫描项目代码。它生成的 Compose 文件和传输使用操作系统临时目录。核心 Docker 构建使用允许列表 .dockerignore。私有插件和机密文件必须保留在此仓库之外;被忽略的 .local/ 只是防止意外,并非受支持的插件位置。没有任何 dsh.py 命令会暂存、在宿主分支上提交或发布任何内容。
通用运行时使用 Ubuntu 24.04,并从官方 Node 镜像复制 Node 24。这保留了原始运行时的 glibc 兼容性,而不包含项目 SDK 或图形库;这些属于外部插件。DSH 固定为提取设置中的 0.1.5-rc.1。Ubuntu 和 Node 标签、apt 软件包以及 npm 传递依赖在构建之间仍可能变化;这不是完全可复现的依赖锁定。安装明确允许原生运行时依赖的 npm 安装脚本。升级时请审查上游变更。
测试
sh
python -m unittest discover -s tests -v
python tests/docker_smoke.py
python tests/task_docker_smoke.py
第二条命令构建本地镜像,并使用端口 11112、示例插件的外部副本、临时合成仓库和全新的唯一命名卷。
它随后会移除自己的容器和卷。它不使用真实的 API
密钥,也不发起模型请求。参见插件契约。
第三条命令需要缓存的核心镜像,启动一个没有
提供商密钥的合成任务,演练任务生命周期,并且只移除其一次性测试夹具
资源。它不构建镜像,也不进行模型调用。
运行 python tests/task_docker_smoke.py --discard 来演练一次性会话
丢弃,包括脏文件/被忽略的文件以及对 DSH 主目录历史的保留。扫码进群