封面图:https://www.pixiv.net/artworks/149570298
前言:
这次用的是群晖 NAS,因为需要挂载空间的机器系统是 Debian 所以使用了NFS服务。并且由于使用了 1panel 和 1panel 提供的 Dsh 应用包,所以Dsh的工作区对应的目录应该是/opt/1panel/apps/deepseek-harness/deepseek-harness/data/,我们需要把这个目录迁移到一会挂载的 NAS分区上。当主机重启后需要自动挂载NAS分区,当分区挂载成功后再启动 Dsh容器,防止报错。
第一步:群晖上准备好 NFS
群晖上打开NFS服务并创建一个目录供Dsh使用。

在控制面板-共享文件夹中选择新增一个文件夹或编辑已有的文件夹权限,幻梦这边选择了已有的这个文件夹。

由于幻梦的群晖只能在局域网内连接,所以就不用担心公网攻击的问题,这边的ip就填192.168.0.0/24;Squash这边就选择无映射(如果有公网访问的需求,这边建议设置映射,但是映射可能会造成容器无法正确获取权限导致失败,最安全的做法是新建一个 Dsh专用共享文件夹然后再进行设置)。
接下来记住这个装载路径,我们后面是要把这个路径或者路径里给Dsh用的的子文件夹挂载到容器所在的设备上。
第二步:在 Debian 上挂载 NFS
先安装 NFS 客户端:
sudo apt install nfs-common创建挂载目录:
sudo mkdir -p /mnt/nas/NasOther先手动测试:
sudo mount -t nfs4 192.168.0.13:/volume3/NasOther/DSH /mnt/nas/NasOther确认:
findmnt /mnt/nas/NasOther正常的话可以看到:
192.168.0.13:/volume3/NasOther/DSH如果这里没有问题,就可以把下面的内容写入到 /etc/fstab。
192.168.0.13:/volume3/NasOther/DSH /mnt/nas/NasOther nfs4 _netdev,nofail,x-systemd.automount,noatime 0 0然后:
sudo systemctl daemon-reload这里建议保留 nofail 和 x-systemd.automount。NAS 没开的时候,让 Debian 自己正常起来,不要因为远程存储暂时不可用把整台机器拖住。
第三步:把整个 data 目录迁移到 NAS
这里直接迁移完整的 data 目录
先创建 NAS 上的目标目录:
sudo mkdir -p /mnt/nas/NasOther/deepseek-harness-data然后把原来的整个 data 目录复制过去:
sudo rsync -aHAX --info=progress2 \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data/ \ /mnt/nas/NasOther/deepseek-harness-data/这里一定要注意结尾的 /。
源目录是:
/opt/1panel/apps/deepseek-harness/deepseek-harness/data/目标目录是:
/mnt/nas/NasOther/deepseek-harness-data/这样 dsh、workspace、caddy 以及 home 都会一次性搬过去
复制完成后检查:
sudo du -sh /mnt/nas/NasOther/deepseek-harness-datasudo du -sh /mnt/nas/NasOther/deepseek-harness-data/dsh/homesudo du -sh /mnt/nas/NasOther/deepseek-harness-data/workspace确认数据规模和原来的 data 基本一致。
第四步:把原来的 data 路径接回去
数据复制完成后,先把原来的目录改名留作备份:
sudo mv \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data.local.bak然后重新创建原路径:
sudo mkdir -p \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data建立 bind mount:
sudo mount --bind \ /mnt/nas/NasOther/deepseek-harness-data \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data检查:
findmnt -T /opt/1panel/apps/deepseek-harness/deepseek-harness/data以及:
df -h /opt/1panel/apps/deepseek-harness/deepseek-harness/data正常情况下这里应该已经指向 NAS。这一步之后,Dsh 原本的路径没有任何变化:
/opt/1panel/apps/deepseek-harness/deepseek-harness/data/只是这个目录的实际内容已经来自 NAS
第五步:让 Dsh 开机时等 NAS
这里不要把 data 的 bind mount 再写进 /etc/fstab。
这次让 fstab 只负责 NFS,Dsh 自己负责确认 NAS 并建立 data 的 bind mount。
创建启动脚本:
sudo nano /usr/local/sbin/start-dsh.sh填入:
#!/bin/bashset -euo pipefail
NAS_MOUNT="/mnt/nas/NasOther"NFS_SOURCE="192.168.0.13:/volume3/NasOther/DSH"
DATA_SOURCE="$NAS_MOUNT/deepseek-harness-data"DATA="/opt/1panel/apps/deepseek-harness/deepseek-harness/data"CONTAINER="Dsh"
NFS_UNIT="mnt-nas-NasOther.mount"
echo "[DSH] Waiting for NAS NFS..."
while true; do if findmnt -rn -T "$NAS_MOUNT" -o SOURCE,FSTYPE \ | grep -Eq "^${NFS_SOURCE} nfs4$"; then echo "[DSH] NAS NFS is ready." break fi
echo "[DSH] NAS not ready, retrying in 5s..."
systemctl reset-failed "$NFS_UNIT" 2>/dev/null || true systemctl start --no-block "$NFS_UNIT" 2>/dev/null || true
sleep 5done
if [[ ! -d "$DATA_SOURCE" ]]; then echo "[DSH] ERROR: NAS data directory does not exist:" echo "$DATA_SOURCE" exit 1fi
DATA_FSTYPE="$(findmnt -rn -T "$DATA" -o FSTYPE 2>/dev/null || true)"DATA_SOURCE_MOUNT="$(findmnt -rn -T "$DATA" -o SOURCE 2>/dev/null || true)"
if [[ "$DATA_FSTYPE" == "nfs4" ]] && \ [[ "$DATA_SOURCE_MOUNT" == "$NFS_SOURCE"/* ]]; then
echo "[DSH] Data is already mounted from NAS:" echo "[DSH] $DATA_SOURCE_MOUNT"
else mkdir -p "$DATA"
echo "[DSH] Creating data bind mount..."
if ! mountpoint -q "$DATA"; then mount --bind "$DATA_SOURCE" "$DATA" fi
DATA_FSTYPE="$(findmnt -rn -T "$DATA" -o FSTYPE 2>/dev/null || true)" DATA_SOURCE_MOUNT="$(findmnt -rn -T "$DATA" -o SOURCE 2>/dev/null || true)"
if [[ "$DATA_FSTYPE" != "nfs4" ]] || \ [[ "$DATA_SOURCE_MOUNT" != "$NFS_SOURCE" && \ "$DATA_SOURCE_MOUNT" != "$NFS_SOURCE"/* ]]; then echo "[DSH] ERROR: data is not mounted from expected NAS." echo "[DSH] FSTYPE=$DATA_FSTYPE" echo "[DSH] SOURCE=$DATA_SOURCE_MOUNT" exit 1 fifi
echo "[DSH] Data mount verified."echo "[DSH] Starting container: $CONTAINER"
docker start "$CONTAINER"
echo "[DSH] Container started successfully."保存后:
sudo chmod 755 /usr/local/sbin/start-dsh.shsudo bash -n /usr/local/sbin/start-dsh.sh没有输出就说明脚本语法没问题。
第六步:创建 systemd 服务
创建:
sudo nano /etc/systemd/system/dsh.service内容:
[Unit]Description=DeepSeek Harness Dsh with NAS storageAfter=network-online.target docker.serviceWants=network-online.targetRequires=docker.service
[Service]Type=oneshotExecStart=/bin/bash /usr/local/sbin/start-dsh.shRemainAfterExit=yesTimeoutStartSec=infinity
[Install]WantedBy=multi-user.target然后:
sudo systemctl daemon-reloadsudo systemctl enable dsh.service启动测试:
sudo systemctl reset-failed dsh.servicesudo systemctl start dsh.service查看:
systemctl status dsh.service --no-pager这里如果看到:
Active: active (exited)不用紧张。
因为这是 Type=oneshot 服务,脚本执行完成以后保持 active,真正的 Dsh 容器是另外一个进程。
检查容器:
docker inspect -f 'Dsh: {{.State.Status}}' Dsh应该是:
Dsh: running再确认数据目录:
findmnt -T /opt/1panel/apps/deepseek-harness/deepseek-harness/data这里应该能看到 NAS 对应的 NFS 文件系统。
第七步:重启进行测试
迁移到这里其实还不算结束,直接重启:
sudo reboot回来以后不要手动运行脚本,直接检查:
findmnt /mnt/nas/NasOtherfindmnt -T /opt/1panel/apps/deepseek-harness/deepseek-harness/datasystemctl status dsh.service --no-pagerdocker inspect -f 'Dsh: {{.State.Status}}' Dsh正常情况下,NFS正常工作,data目录指向 NAS,dsh.server为active (exited),Dsh容器成功运行
如果 NAS 启动得比较慢也没关系。start-dsh.sh 会一直等待真正的 NFS 挂载出现,NAS 没准备好时不会启动 Dsh容器。
第八步:确认运行稳定后清理旧文件
确认 NAS、data 和 Dsh 都正常以后,再处理之前留下的本地备份/opt/1panel/apps/deepseek-harness/deepseek-harness/data.local.bak
先看一下大小:
sudo du -sh \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data.local.bak确认没有问题后删除:
sudo rm -rf \ /opt/1panel/apps/deepseek-harness/deepseek-harness/data.local.bak删掉它以后,原来的本地 data 就算正式退休了。
