claude-mem Docker 测试容器完全指南:构建、认证、版本锁定与运行模式解析
docker/claude-mem 是 claude-mem 仓库内置的一个最小化 Docker 测试容器(harness):它在隔离的环境里启动 Claude Code CLI 与本地构建的插件,让 AI 生成的 observations 落入一个可丢弃的 SQLite 库,结束后你可以直接把数据库拿到宿主机上检查。读完本文,你将掌握该镜像的完整构建流程、三级认证回退机制、可复现的版本锁定参数、容器三种运行模式(server / worker / shell)的切换方式,以及手动 docker run 的全部变体。
一、Docker harness 的定位与文件组成
该目录的设计目标很明确(见 README):"A minimal container for exercising claude-mem end-to-end without polluting your host"——它不是开发环境,只提供启动 claude 并捕获 observations 所需的最小运行时。目录内共 4 个文件,各司其职:
| 文件 | 职责 |
|---|---|
| Dockerfile | 镜像定义(node:20 + Bun + uv + Claude Code CLI + 本地 plugin/) |
| build.sh | 先执行 npm run build 再执行 docker build,镜像 tag 默认为 claude-mem:basic |
| entrypoint.sh | 容器内入口。若挂载了 OAuth 凭据则写入 $HOME/.claude/,然后 exec "$@" 或按模式启动服务 |
| run.sh | 宿主机侧启动器。按优先级提取凭据(Keychain → 文件 → 环境变量),挂载持久化数据目录,进入交互 shell |
build.sh 的实际逻辑(build.sh)会先切换到仓库根目录执行 npm run build,保证 plugin/ 目录是最新编译产物后再交给 docker build;run.sh 则在运行时通过 SCRIPT_DIR/../.. 推导仓库根目录,并据此设置默认数据目录 $REPO_ROOT/.docker-claude-mem-data(run.sh)。
二、快速上手:构建与运行
从仓库根目录执行:
docker/claude-mem/build.sh
docker/claude-mem/run.sh
run.sh 会把你带进容器内的 bash,其中 claude 已在 PATH 上,插件预置于 /opt/claude-mem。启动会话时使用:
claude --plugin-dir /opt/claude-mem
会话结束后,SQLite 数据库留在宿主机的 ./.docker-claude-mem-data/claude-mem.db,可用 sqlite3 直接验证 observations 是否被捕获:
sqlite3 .docker-claude-mem-data/claude-mem.db 'select count(*) from observations'
需要注意一个入口行为:从 entrypoint.sh 的源码看,CLAUDE_MEM_CONTAINER_MODE 的默认值是 server,此时容器会 exec bun /opt/claude-mem/scripts/server-service.cjs --daemon 启动 server-beta 运行时而不是进入 shell。若要获得 README 快速开始中描述的交互 shell 体验,需要把模式切到 shell(或别名 tooling),该模式在无参数时 exec bash,有参数时 exec "$@"。
三、镜像解剖:运行时、层级与缓存设计
README 说明镜像布局对标 anthropics/claude-code 的 devcontainer:FROM node:20、非 root 的 node 用户、全局安装 @anthropic-ai/claude-code;同时去掉了防火墙、zsh、fzf、delta、git-hist 等编辑向工具,因为"这个镜像是为了跑 claude-mem,而不是写代码"。
对照 Dockerfile 逐层验证:
- 基础层(L2-L17):
node:20+ apt 安装git curl ca-certificates unzip jq less procps uuid-runtime sqlite3,其中sqlite3正是快速开始里检查 DB 所依赖的客户端。 - Bun 运行时(L19-L23):通过官方
bun.sh/install脚本安装到/usr/local/bun,这是 claude-mem worker/service 脚本(如 server-service.cjs)的运行环境,PATH已前置。 - uv(L25-L29):通过版本化安装脚本装到
/usr/local/bin,为 Chroma 向量检索提供 Python 运行时。 - Claude Code CLI(L31-L38):先切到
node用户再执行npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION},npm 全局前缀指向/usr/local/share/npm-global。 - 插件层(L41-L46):以 root 身份
COPY plugin/ /opt/claude-mem/并归还属主,再以node用户执行npm install --omit=dev --legacy-peer-deps。 - 挂载点预创建(L49-L50):
/home/node/.claude、/home/node/.claude-mem、/data/claude-mem。 - 入口与模式(L52-L67):entrypoint 拷入
/usr/local/bin/claude-mem-entrypoint,并预置CLAUDE_MEM_CONTAINER_MODE=server、CLAUDE_MEM_RUNTIME=server-beta。
README 特别强调层级顺序是刻意为之:插件文件放在 npm install 层之后,这样在插件上反复迭代时不会击穿 CLI 安装层的构建缓存,显著提升开发迭代速度。
四、版本锁定:用 build-arg 换取可复现性
镜像中一切影响可复现性的组件都暴露为 --build-arg——需要复现时锁定,追求最新时省略即可:
docker build \
-f docker/claude-mem/Dockerfile \
--build-arg BUN_VERSION=1.3.12 \
--build-arg UV_VERSION=0.11.7 \
--build-arg CLAUDE_CODE_VERSION=1.2.3 \
-t claude-mem:basic .
| Arg | 默认值 | 说明 |
|---|---|---|
BUN_VERSION |
1.3.12 |
通过官方 bun.sh/install 脚本安装,tag 为 bun-v${BUN_VERSION} |
UV_VERSION |
0.11.7 |
通过带版本号的 astral.sh/uv/${UV_VERSION}/install.sh 安装 |
CLAUDE_CODE_VERSION |
latest |
npm tag 或精确版本号。建议在 CI 中锁定,本地可让其浮动 |
这三个默认值与 Dockerfile 中的 ARG BUN_VERSION=1.3.12、ARG UV_VERSION=0.11.7、ARG CLAUDE_CODE_VERSION=latest 一一对应。其中 Bun 的安装命令带 -s "bun-v${BUN_VERSION}" 参数(L21),uv 的安装 URL 直接嵌入版本号(L28),因此两个默认值天然是可复现的;而 CLAUDE_CODE_VERSION=latest 意味着每次构建的 CLI 版本可能不同,README 给出的实践建议是"CI 锁定、本地浮动"。
五、认证链:三级回退与临时凭据的安全处理
run.sh 按固定顺序选择第一个可用的认证源(run.sh):
ANTHROPIC_API_KEY环境变量——直接挂载进容器(CREDS_MOUNT_ARGS=(-e ANTHROPIC_API_KEY)),跳过 OAuth 凭据提取;- macOS Keychain——仅在
uname为Darwin时执行security find-generic-password -s 'Claude Code-credentials' -w; ~/.claude/.credentials.json——旧版磁盘形式,仍存在于一些老 CLI 安装和迁移后的机器上。
当走凭据文件路径时,安全处理链条如下:
- 凭据先写入
mktemp生成的临时文件,并chmod 600; - 以只读方式挂载到容器内
/auth/.credentials.json,同时注入-e CLAUDE_MEM_CREDENTIALS_FILE=/auth/.credentials.json; - 容器端 entrypoint.sh 在启动时检查该文件存在(缺失则报错退出),
cp到$HOME/.claude/.credentials.json并再次chmod 600; run.sh通过trap 'rm -f "$CREDS_FILE"' EXIT在返回时删除宿主机临时文件。README 特别指出docker run被刻意没有exec,目的正是让EXITtrap 有机会触发。
若三级认证源全部落空,run.sh 会以错误退出,提示先在宿主机执行 claude login 或设置 ANTHROPIC_API_KEY(run.sh)。
六、手动 docker run(不经过 run.sh)
需要完全控制挂载与环境变量时,可以绕过 run.sh 直接调用镜像。OAuth 凭据文件方式:
docker run --rm -it \
-v $(mktemp -d):/home/node/.claude-mem \
-e CLAUDE_MEM_CREDENTIALS_FILE=/auth/.credentials.json \
-v /path/to/creds.json:/auth/.credentials.json:ro \
claude-mem:basic
API key 方式:
docker run --rm -it \
-v $(mktemp -d):/home/node/.claude-mem \
-e ANTHROPIC_API_KEY \
claude-mem:basic
两个示例都把 /home/node/.claude-mem 挂到一个 mktemp -d 目录,保证数据落盘在宿主机且随时可弃;-e ANTHROPIC_API_KEY 不带值的形式表示透传宿主机已导出的同名变量。另外注意 run.sh 中有对应的 TTY 处理([[ -t 0 && -t 1 ]] 才加 -it,run.sh),手动调用时非交互场景应去掉 -it。
七、环境变量速查表
| 变量 | 作用位置 | 用途 |
|---|---|---|
TAG |
build.sh、run.sh |
覆盖镜像 tag(默认 claude-mem:basic) |
HOST_MEM_DIR |
run.sh |
覆盖宿主机持久化 .claude-mem 卷路径(默认 $REPO_ROOT/.docker-claude-mem-data) |
ANTHROPIC_API_KEY |
run.sh、entrypoint |
API key 认证,跳过 OAuth 凭据提取 |
CLAUDE_MEM_CREDENTIALS_FILE |
entrypoint | 容器内已挂载 OAuth 凭据 JSON 的路径,启动时复制到 $HOME/.claude/.credentials.json |
补充两个未在表中列出但由源码确认的容器内变量:
CLAUDE_MEM_DOCKER=1:entrypoint 强制导出(entrypoint.sh)。在服务端代码 create-server-service.ts 中,detectDockerEnvironment会把CLAUDE_MEM_DOCKER=1/true或/.dockerenv存在性都识别为 Docker 环境,其后果是环境校验拒绝local-dev认证旁路——"从源码结构看",因为容器可通过服务间网络与暴露端口被访问,回环地址假设不再成立;CLAUDE_MEM_RUNTIME:entrypoint 以server-beta为默认导出,服务端校验只接受server或旧字面量server-beta(create-server-service.ts)。
八、参数透传与清理
run.sh 后面的任何参数都会作为命令转发进容器,例如免交互直接提问:
docker/claude-mem/run.sh claude --plugin-dir /opt/claude-mem --print "what did we learn yesterday?"
用完后的清理动作:
rm -rf .docker-claude-mem-data # 抹掉持久化 DB + Chroma 存储
docker rmi claude-mem:basic # 删除镜像
九、容器运行模式与 server-beta 运行时
entrypoint.sh 通过 CLAUDE_MEM_CONTAINER_MODE 实现了三模式分发:
server(默认):exec bun /opt/claude-mem/scripts/server-service.cjs --daemon,运行 HTTP server-beta 运行时,不启动 legacy worker;worker:exec bun ... worker start,只跑 BullMQ 生成 worker(无 HTTP),并强制unset CLAUDE_MEM_GENERATION_DISABLED——因为 worker 进程本身就是生成进程;shell/tooling:落入"$@",无参数时进入bash,用于插件调试等工具类场景;- 其他值:打印
ERROR: unknown CLAUDE_MEM_CONTAINER_MODE=...并exit 1。
README 还给出了生产化拆分思路:在本服务上设置 CLAUDE_MEM_GENERATION_DISABLED=true,把生成任务拆到兄弟容器中的 claude-mem server worker start 进程里,实现 HTTP 服务与生成 worker 的水平分离。
与根目录 docker-compose.yml 的全量部署(见 docs/docker.md)相比,本 harness 是"单机验证"路线:compose 栈带 Valkey sidecar 与 api-key 认证、监听 37777 端口的 /healthz;而本目录镜像面向端到端观察捕获验证,两者共用同一套 CLAUDE_MEM_DOCKER / CLAUDE_MEM_RUNTIME 环境契约,但用途不重叠。
十、小结
docker/claude-mem 展示了测试容器设计的几个可复用要点:以 build-arg 显式暴露所有版本旋钮以换取可复现性;用"插件层后置"的层级顺序保护昂贵的 CLI 安装缓存;认证链按 Keychain → 磁盘文件 → 环境变量的确定优先级回退,并配合 chmod 600、只读挂载与 EXIT trap 形成完整的临时凭据生命周期;再以一个环境变量(CLAUDE_MEM_CONTAINER_MODE)切换 server / worker / shell 三种前台进程,让同一镜像既能做交互调试,也能拆分为服务与 worker 两个部署单元。所有脚本与镜像定义均为可读的 shell/多行 Dockerfile,适合作为自研 agent 插件的容器化测试参考。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00