DeepSeek Harness 容器化安装:DSH plugin 与 dsh web 的 Docker 部署与端口绑定

安装与快速上手发布于 2026-10-17作者: DeepSeek Plugin 插件市场
DeepSeek Harnessdsh安装Dockerdsh webDSH plugin容器部署
DeepSeek Harness 在 Docker 里怎么装?三种方案任选:镜像内全局安装、npx 免安装、自建镜像;并解决 dsh web 的端口映射、数据卷持久化与容器内插件沙箱前提。

DeepSeek Harness 在容器里是能跑的,但要先想清楚三件事:用哪种安装方案、把状态挂到哪个卷、dsh web 监听哪个地址。 容器化安装本身不难——官方 CLI 包是 @deepseek-ai/dsh,可执行文件叫 dsh——难的是它默认「只服务本机」的设计前提在容器里被打破了:dsh web 默认只监听回环地址,容器内的回环在宿主侧不可达,所以很多人卡在「容器起来了、浏览器打不开」。另外 DSH 是有状态的:profile、已装 DSH plugin 清单、会话数据、凭据都在数据目录里,不挂卷就一删全没。

本文按三条主线展开:三种安装方案怎么选(镜像内全局装 / npx 免装 / 自建镜像)、dsh web 的端口与绑定三种做法、容器里跑 DSH plugin 的额外前提。命令里的子参数名请用容器内 dsh --help 与 dsh web --help 的输出核对——官方 CLI 还在快速迭代,以你装到的那一版为准。

DeepSeek Harness 容器化安装:三种方案先选一个

一句话结论:长期跑选「镜像内全局装」,临时试选「npx 免装」,团队与 CI 选「自建镜像」——三者不是替代关系,而是按「状态要不要留、插件要不要装、环境要不要复现」三问来分。

方案适合谁状态与插件主要代价
A. 镜像内全局安装长期运行、要装 DSH plugin、要连本地文件状态靠数据卷,插件可持久镜像稍大,每次升级要重建镜像或容器内升级
B. npx 免安装一次性试跑、临时验证 dsh web UI状态默认落在容器临时目录,删容器即丢每次启动可能拉取,版本随最新漂移
C. 自建镜像团队统一版本、CI 流水线、预置插件完全可控、可复现要自己维护 Dockerfile 与升级流程

选完再往下看对应小节,别把三套混着用——混用最常见的后果是「插件装在了另一个数据目录」。

方案 A:镜像内全局安装 DSH plugin(最稳)

一句话结论:在镜像里用 npm 全局装 @deepseek-ai/dsh,把数据目录与工作区各挂一个卷,dsh web 指定对外监听地址与端口——这是唯一同时满足「插件可持久、会话不丢、宿主可访问」的方案。

  1. 选基座镜像。要跑 DSH plugin 就用标准 node:20(或更高)这类带构建工具的基座;只跑 CLI 与网页端可以用 node:20-slim,但先记住:slim / alpine 装带原生模块的插件时极易失败(见第 6 节)。
  2. 全局安装本体:
bash
npm i -g @deepseek-ai/dsh
dsh --version       # 预期:打印出版本号,例如 0.2.0-rc.2
  1. 把数据目录指到挂载点上,让 profile、插件记录、会话都落在卷里:
bash
export DSH_HOME=/data/dsh     # 容器内路径,对应宿主挂载的卷
mkdir -p "$DSH_HOME"
  1. 起 dsh web 并显式指定监听地址与端口(参数名以 dsh web --help 为准):
bash
dsh web --host 0.0.0.0 --port 3080
# 预期:进程常驻并打印监听地址;容器内 curl -I http://127.0.0.1:3080 能通
  1. docker run 时做端口映射 + 双卷挂载:
bash
docker run -d --name dsh \
  -p 3080:3080 \
  -e DSH_HOME=/data/dsh \
  -v dsh-data:/data/dsh \
  -v "$PWD/workspace:/workspace" \
  dsh-local:0.2.0-rc.2
  1. 验证三件事:宿主浏览器能打开 http://宿主机IP:3080;容器内 dsh plugin 相关子命令能列出已装项;重建容器后 profile 与插件清单仍在(这一步才是「卷挂对了」的证明)。

方案 B:npx 免安装跑 dsh web(最轻)

一句话结论:npx @deepseek-ai/dsh web 不落全局安装、最省事,代价是状态默认落在临时目录、每次启动可能拉最新版——只适合试跑与临时排查。

  1. 一条命令起服务(仍需把数据目录与工作区挂出来,否则重启即丢):
bash
docker run --rm -it -p 3080:3080 \
  -e DSH_HOME=/data/dsh \
  -v dsh-data:/data/dsh \
  node:20 \
  npx -y @deepseek-ai/dsh web --host 0.0.0.0 --port 3080
  1. 把 npx 缓存也挂出来(否则每次重建都要重新下载,慢且费流量):
bash
-v dsh-npx-cache:/root/.npm
  1. 钉住版本避免漂移:把 @deepseek-ai/dsh 写成带版本号的形式(例如 @deepseek-ai/dsh@0.2.0-rc.2),否则每次启动可能拿到新版本,插件兼容性跟着变(这条与 npx 版与全局版混装的版本漂移 是同一类问题)。
  2. 知道它的边界:npx 方案下如果你在容器里装了 DSH plugin,装的位置取决于 DSH_HOME——所以第 3 步的 -e DSH_HOME 不能省,否则插件装在临时目录里,容器一停就白装。

方案 C:基于官方包自建镜像(最可控)

一句话结论:自建镜像的价值在于「版本钉死 + 常用 DSH plugin 预装 + 环境一次配好」,适合团队与 CI;代价是每次升级都要重建镜像。

dockerfile
FROM node:20
# 1) 钉住 DeepSeek Harness 本体版本
RUN npm i -g @deepseek-ai/dsh@0.2.0-rc.2
# 2) 预置数据目录(供挂卷覆盖)
ENV DSH_HOME=/data/dsh
RUN mkdir -p /data/dsh
# 3) 可选:预装团队常用插件(插件名以你实际使用的为准)
# RUN dsh plugin add <你的插件包名>@<版本>
WORKDIR /workspace
EXPOSE 3080
CMD ["dsh", "web", "--host", "0.0.0.0", "--port", "3080"]
  1. 构建与运行:docker build -t dsh-local:0.2.0-rc.2 .,然后按方案 A 的第 5 步运行。
  2. 把「预装插件」与「数据卷」分开想:镜像里预装的是基线,用户自己后装的插件记在 DSH_HOME 里(走数据卷)——升级镜像时基线更新、个人插件不受影响。
  3. CI 里复用:把镜像推到私有仓库,流水线直接拉取,避免每次装依赖(这套思路在 CI 里更新 DeepSeek Harness 里有更细的落地)。
  4. 升级姿势二选一:重建镜像(推荐,可回滚)或容器内 npm i -g @deepseek-ai/dsh@<新版本> 后提交为新镜像——后者容易积累脏层,不建议长期用。

dsh web 在容器里的绑定与端口:DeepSeek Harness 为什么必须监听 0.0.0.0

一句话结论:dsh web 默认只监听本机回环地址,而容器内的「本机」是容器自己的网络命名空间——宿主访问不到。要让宿主打开,必须同时做两件事:服务端监听全部网卡 + 运行时把端口映射出来。只做一件都不通。

三种做法,按你的暴露面需求选:

  1. 做法一:监听 0.0.0.0 + -p 端口映射(最常用)
bash
dsh web --host 0.0.0.0 --port 3080      # 容器内
docker run -p 3080:3080 ...              # 宿主侧
# 预期:宿主 curl -I http://127.0.0.1:3080 返回 HTTP 响应头
  1. 做法二:只绑回环 + 宿主侧反代(暴露面最小):容器只监听回环、不映射端口,由宿主上的反向代理通过容器网络访问。这条把「对外暴露」这件事集中到反代层,适合要加 HTTPS 与鉴权的场景(配置写法见 给 dsh web 配反向代理与 HTTPS)。
  2. 做法三:--network host(最省事、最不隔离):容器直接用宿主网络栈,dsh web 绑 0.0.0.0 即等于绑在宿主上——省掉端口映射,但失去网络隔离,只建议本机开发用。

端口起不来的两类错误要分清:提示「地址已在使用」是端口被占(同容器内换端口即可);提示「权限被拒绝」是权限或系统保留区间问题(换到 1024 以上的高位端口)。先看错误码属于哪一类,再决定换端口还是换号段,别先去查鉴权——端口冲突总览见 DeepSeek Harness 端口冲突排查。

容器里跑 DSH plugin 与沙箱的额外前提

一句话结论:容器化最容易踩的不是安装,而是「宿主能跑、容器跑不了」——原生依赖、文件所有权、沙箱差异三者占绝大多数。

  1. 原生依赖:带原生模块的 DSH plugin 在 slim / alpine 上编译失败。三条路:换标准基座、先装构建工具(apt-get install -y python3 make g++)、或换一个纯 JS 实现的替代插件。
  2. 文件所有权:容器内以 root 跑,写出来的文件宿主侧属主是 root,宿主编辑时没权限。两条路:运行时用 --user $(id -u):$(id -g) 指定宿主用户,或挂卷时接受属主差异并在宿主侧调整。
  3. 沙箱差异:容器里再叠一层沙箱会放大失败面;如果只是本机开发用,可以把工作区直接挂进来、让它在「已授权的目录」内工作,别在容器里再套一层限制。
  4. 时区与语言:日志时间错乱多半是容器缺 TZ(例如 -e TZ=Asia/Shanghai);中文显示异常多因基础镜像缺 locale,按需装 locales 即可。
  5. 插件从哪来:容器里缺哪个插件,用 DSH Plugin Hub 按分类找、看依赖说明挑「不依赖原生模块」的候选,再在容器内装——比盲搜包名省事。
已安装插件列表

DSH plugin 容器化排查注意事项

一句话结论:按「能装 → 能起 → 能连 → 能用」四步定位,别把四类问题混成一轮排查。

  1. 装不上先看基础镜像是否缺构建工具,再看包名与版本是否存在(npm view 一下)。
  2. 起不来看 dsh web 的启动输出:是监听失败(端口/权限)还是配置加载失败(profile 路径不对)。
  3. 连不上只查两件事:服务端监听地址是不是 0.0.0.0、运行时有没有 -p 映射(两者缺一不通)。
  4. 用不了(能连但功能受限)优先查数据目录权限与沙箱前提,而不是重装。
  5. 状态丢只可能是卷没挂对:确认 DSH_HOME 指向的路径就是 -v 挂进来的那个目录,重建容器后再验证一次。
  6. 修复状态如实:本文的安装方案与命令基于官方 CLI 包的一次对照(@deepseek-ai/dsh,bin dsh);子命令与参数名请以你容器内 dsh --help 的实际输出为准,容器化没有官方专文,方案取舍由本文给出、需你在自己环境验证一遍。

来源:apps/cli/README.md、npm @deepseek-ai/dsh、apps/desktop/README.zh.md。

常见问题

DeepSeek Harness 在 Docker 容器里怎么安装?官方包名和最小可行命令是什么?

DeepSeek Harness 的 CLI 包名是 @deepseek-ai/dsh,可执行文件叫 dsh;容器里最稳的做法是在镜像内全局安装(npm 全局装 @deepseek-ai/dsh),再用 dsh web 起服务。最小链路是「装 Node → 全局装 dsh → 挂数据卷 → 起 dsh web」,装完用 dsh --version 验证,具体子命令参数以容器里 dsh --help 的输出为准。

为什么 DeepSeek Harness 的 dsh web 在容器里起了,宿主机浏览器却打不开?

因为 DeepSeek Harness 的 dsh web 默认只监听本机回环地址,容器内监听的「本机」是容器自己的网络命名空间,宿主机访问不到。要在 dsh web 里把监听地址改成全部网卡(0.0.0.0),并在 docker run 时用 -p 把容器端口映射到宿主机;只改端口映射不监听对外地址,仍然打不开。

容器里跑 DSH plugin 需要挂哪些数据卷?不挂会丢什么?

至少要把 DeepSeek Harness 的数据目录(由 DSH_HOME 指向)挂成卷或绑定到宿主机目录,否则容器一删,profile 配置、已装插件清单、会话历史与凭据全部丢失。工作区目录也要单独挂(-v 你的项目:容器内路径),这样 dsh plugin 的工具才有文件可操作;模型与插件缓存可另挂一卷减少重复下载。

在 Docker 里装 DSH plugin 时原生模块编译失败,怎么绕开?

DeepSeek Harness 的部分插件依赖原生模块,精简基础镜像(如 alpine、slim)缺少编译工具链与预编译产物会失败。三条路:换用体积更大的标准镜像基座、先装构建工具(python3 / make / g++)再装插件、或改用不依赖原生模块的替代插件;在 DSH Plugin Hub 里可以按依赖说明筛掉需要编译的候选。

DeepSeek Harness 在容器里报端口不可用或权限错误,该怎么定位?

DeepSeek Harness 端口起不来分两类:端口已被占用返回的是「地址已在使用」,端口落在系统保留区间或权限不足返回的是「权限被拒绝」。容器里前者多因同容器内已有进程占用,后者多因改用非 root 用户后绑到了低位端口。定位顺序是先看错误码属于哪一类,再决定换端口还是换端口号段,别先去改鉴权。

相关术语

DSH_HOME
DSH_HOME 是 DeepSeek Harness 用来指定数据目录位置的环境变量,指向的目录里存放 profile 配置、插件安装记录、会话数据与凭据。容器里把它指向挂载卷,才能让这些状态在容器重建后保留。— https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md
dsh web
dsh web 是 DeepSeek Harness 的网页端启动入口,把会话与插件管理能力以本地网页服务的形式提供出来。它默认只监听本机地址,容器与远程访问场景需要显式指定监听地址与端口。— https://www.npmjs.com/package/@deepseek-ai/dsh
容器内插件沙箱(container plugin sandbox)
容器内插件沙箱指 DeepSeek Harness 在容器里执行工具与插件时额外的权限与文件系统约束。它与宿主侧沙箱能力不完全等价,原生依赖、用户身份与文件系统差异都会让「宿主能跑、容器跑不了」。— https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md
数据卷(volume)
数据卷是 Docker 里独立于容器生命周期的持久化存储,容器删除后仍然保留。DeepSeek Harness 容器化时至少要挂两个卷:数据目录(存 profile、插件、会话)与工作区目录(存要处理的文件)。— https://docs.docker.com/storage/volumes/

来源