背景
当前 docker-compose.yml 对 /home/node 目录采用分散挂载策略:
~/.global → named vol openclaw-global
~/.local → named vol openclaw-python-local
~/.openclaw → bind mount ~/.openclaw-in-docker
~/.claude → bind mount ~/.claude
~/.notebooklm → bind mount ~/.notebooklm
~/.agents/skills → bind mount ~/.agents/skills (ro)
~/.cache/ms-playwright → named vol openclaw-playwright-cache
~/.go/pkg/mod → named vol openclaw-go-mod
/app/node_modules → named vol openclaw-node-modules
共 9 行挂载配置。
目标
用单个命名卷 openclaw-devkit-home:/home/node 替代上述所有分散挂载,同时通过只读 bind mount 保留从宿主机编辑配置的能力。
优势
- 数据完整性 — 镜像构建时写入的所有内容(工具链、CLI、配置)随容器重启全部保留,不从镜像层重新初始化
- entrypoint 简化 — 无需针对 bind mount / named vol / root 运行做复杂的权限修复逻辑
- Go 生态覆盖完整 —
go/pkg/mod、go/bin、go/build、~/.cache/go-build 全部保留
- 运维极简 — 一个卷的备份/清理/迁移
- 配置隔离 — 天然与宿主机隔离,不污染原生
~/.openclaw
新卷挂载方案
volumes:
openclaw-devkit-home:
name: openclaw-devkit-home
services:
openclaw-gateway:
volumes:
# ─────────────────────────────────────────────────────────────
# 1. 全量命名卷(核心)
# 替代所有分散挂载,包含:.global, .local, .opencode, .openclaw
# .claude, .notebooklm, .agents, .cache, go/, /app
# ─────────────────────────────────────────────────────────────
- openclaw-devkit-home:/home/node:rw
# ─────────────────────────────────────────────────────────────
# 2. 只读挂载:CLI 工具配置文件(容器内可读,宿主机可编辑)
# 注意:必须只读,避免宿主机编辑器锁文件或权限问题
# ─────────────────────────────────────────────────────────────
- ${HOME:-${USERPROFILE}}/.claude:/home/node/.claude:ro
- ${HOME:-${USERPROFILE}}/.openclaw-in-docker:/home/node/.openclaw:ro
- ${HOME:-${USERPROFILE}}/.notebooklm:/home/node/.notebooklm:ro
- ${HOME:-${USERPROFILE}}/.agents/skills:/home/node/.agents/skills:ro
# ─────────────────────────────────────────────────────────────
# 3. 读写挂载:初始化脚本和动态工作区
# ─────────────────────────────────────────────────────────────
- ./docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh:ro
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace:rw
只读挂载说明
| 宿主机路径 |
容器挂载点 |
模式 |
用途 |
~/.claude |
/home/node/.claude |
ro |
Claude Code 配置文件、claude.json、skills、memory |
~/.openclaw-in-docker |
/home/node/.openclaw |
ro |
OpenClaw Gateway 配置、会话状态 |
~/.notebooklm |
/home/node/.notebooklm |
ro |
NotebookLM 认证信息 |
~/.agents/skills |
/home/node/.agents/skills |
ro |
共享 Skills 目录 |
只读理由:
- 避免宿主机编辑器(如 VSCode)在打开文件时创建
.swp 交换文件,导致容器内进程权限问题
- 避免宿主机用户的 uid/gid 与容器内
node 用户 (uid 1000) 不一致,引发权限冲突
- 配置修改统一在宿主机端进行,容器内对配置的写入操作(如
openclaw config set)通过 docker exec 或 Gateway UI 完成
写入方式:
# 宿主机端直接编辑(只读挂载不会阻止宿主机写入)
vim ~/.claude/claude.json
vim ~/.openclaw-in-docker/openclaw.json
# 容器内命令修改(通过 exec 临时以 node 用户运行)
docker exec -it openclaw-gateway openclaw config set ...
docker exec -it openclaw-gateway claude config set ...
workspace 路径重叠检测
问题:如果 OPENCLAW_WORKSPACE_DIR 设置在 ~/.openclaw-in-docker 内部,bind mount 会遮蔽命名卷中同名路径,导致数据丢失或行为不可预期。
检测机制:已在 docker-entrypoint.sh 增加 _validate_workspace_path() 验证函数(entrypoint 第 0 步执行):
# 检测场景:
# 1. workspace 路径 == ~/.openclaw-in-docker → ERROR
# 2. workspace 路径是 ~/.openclaw-in-docker 的子目录 → ERROR
# 正确示例:
OPENCLAW_WORKSPACE_DIR=~/projects # 在 ~/.openclaw-in-docker 外部 ✓
OPENCLAW_WORKSPACE_DIR=~/openclaw-workspace # 在 ~/.openclaw-in-docker 外部 ✓
# 错误示例(会被检测并拒绝启动):
OPENCLAW_WORKSPACE_DIR=~/.openclaw-in-docker/workspace # ✗
OPENCLAW_WORKSPACE_DIR=~/.openclaw-in-docker # ✗
待办事项
风险
- 命名卷内数据丢失风险 → 首次切换前需备份旧卷数据
- 首次启动需初始化逻辑(已有
.openclaw-seed 模式可复用)
参考
- 当前权限修复逻辑:
docker-entrypoint.sh:56-111(重构前)
- workspace 重叠检测:
docker-entrypoint.sh 新增 _validate_workspace_path()
背景
当前
docker-compose.yml对/home/node目录采用分散挂载策略:~/.global→ named volopenclaw-global~/.local→ named volopenclaw-python-local~/.openclaw→ bind mount~/.openclaw-in-docker~/.claude→ bind mount~/.claude~/.notebooklm→ bind mount~/.notebooklm~/.agents/skills→ bind mount~/.agents/skills(ro)~/.cache/ms-playwright→ named volopenclaw-playwright-cache~/.go/pkg/mod→ named volopenclaw-go-mod/app/node_modules→ named volopenclaw-node-modules共 9 行挂载配置。
目标
用单个命名卷
openclaw-devkit-home:/home/node替代上述所有分散挂载,同时通过只读 bind mount 保留从宿主机编辑配置的能力。优势
go/pkg/mod、go/bin、go/build、~/.cache/go-build全部保留~/.openclaw新卷挂载方案
只读挂载说明
~/.claude/home/node/.claudeclaude.json、skills、memory~/.openclaw-in-docker/home/node/.openclaw~/.notebooklm/home/node/.notebooklm~/.agents/skills/home/node/.agents/skills只读理由:
.swp交换文件,导致容器内进程权限问题node用户 (uid 1000) 不一致,引发权限冲突openclaw config set)通过docker exec或 Gateway UI 完成写入方式:
workspace 路径重叠检测
问题:如果
OPENCLAW_WORKSPACE_DIR设置在~/.openclaw-in-docker内部,bind mount 会遮蔽命名卷中同名路径,导致数据丢失或行为不可预期。检测机制:已在
docker-entrypoint.sh增加_validate_workspace_path()验证函数(entrypoint 第 0 步执行):待办事项
docker-compose.yml:volumes:中的 6 个冗余命名卷(openclaw-node-modules、openclaw-go-mod、openclaw-playwright-cache、openclaw-playwright-bin、openclaw-global、openclaw-python-local)openclaw-devkit-home命名卷volumes:为新方案(命名卷 + 只读挂载 + 读写挂载)docker-entrypoint.sh权限修复逻辑:TARGET_DIRS数组遍历逻辑.openclaw-seed复制逻辑.openclaw配置持久化(只读挂载模式下宿主机编辑生效).claude会话状态持久化(只读挂载模式下宿主机编辑生效).notebooklm只读挂载正常工作make clean/make clean-volumes说明).env.example或文档说明OPENCLAW_WORKSPACE_DIR路径约束风险
.openclaw-seed模式可复用)参考
docker-entrypoint.sh:56-111(重构前)docker-entrypoint.sh新增_validate_workspace_path()