首页
/ Claude-Mem Docker 部署实战:server-beta 运行时、Postgres/Valkey 栈与 HTTP/Worker 分离架构

Claude-Mem Docker 部署实战:server-beta 运行时、Postgres/Valkey 栈与 HTTP/Worker 分离架构

2026-09-06 12:09:54作者:咎竹峻Karen

本文基于仓库中的 docs/docker.md 及配套 Compose 文件、Dockerfile 与入口脚本,讲解如何用 Docker 部署 Claude-Mem 的 server-beta 运行时:一条 docker compose up --build 拉起「Postgres(持久存储)+ Valkey(BullMQ 队列)+ HTTP 服务 + 生成 Worker」的完整栈,通过 /healthz 验证健康状态,并创建 API Key 打通受保护的 V1 写路由。读完本文,你将掌握该 Docker 栈的全部必填密钥、关键环境变量含义、server/worker 分离原理,以及容器内鉴权与安全约束。

一、快速启动:最小可运行流程

docs/docker.md 给出的核心操作只有四步:

docker compose up --build
curl http://127.0.0.1:37777/healthz

仓库根目录的 docker-compose.yml 定义了这套可部署栈(注释中称为 "Phase 10 — server-beta deployable runtime")。文档中列出的容器关键环境变量是:

  • CLAUDE_MEM_WORKER_HOST=0.0.0.0
  • CLAUDE_MEM_DATA_DIR=/data/claude-mem
  • CLAUDE_MEM_QUEUE_ENGINE=bullmq
  • CLAUDE_MEM_REDIS_URL=redis://valkey:6379
  • CLAUDE_MEM_AUTH_MODE=api-key

以及最后一条硬性要求:在使用受保护的 V1 写路由之前,必须先在容器内创建 API Key

需要说明一个版本差异:docs/docker.md 示例中的探测端口是 37777,而当前仓库的 docker-compose.yml 实际映射并健康检查的端口是 37877ports: "37877:37877",healthcheck 执行 curl -fsS http://127.0.0.1:37877/healthz)。因此以当前 Compose 文件为准,验证命令应为:

curl http://127.0.0.1:37877/healthz

健康检查路由本身在 ServerV1Routes.ts 中注册,无需鉴权,直接返回 { status: 'ok' }/v1/info 也会暴露服务名、版本、运行时和当前 authMode

二、栈的组成:四个服务与三个命名卷

docker-compose.yml 实际包含四个服务,比文档的「Server + Valkey sidecar」描述更完整:

服务 镜像/构建 职责
postgres postgres:17-alpine 规范存储(canonical storage),数据落在 postgres-data
valkey valkey/valkey:8-alpine BullMQ 队列后端,启用 AOF(--appendonly yes --appendfsync everysec)与 --maxmemory-policy noeviction,数据落在 valkey-data
claude-mem-server docker/claude-mem/Dockerfile 构建 HTTP 服务,CLAUDE_MEM_GENERATION_DISABLED=true,不做生成
claude-mem-worker 同一镜像 BullMQ 生成消费者,从队列消费并产出观察(observations)

几个工程细节值得注意(均来自 docker-compose.yml 头部注释与服务定义):

  • 崩溃自愈:所有长驻服务声明 restart: unless-stopped,容器因 OOM、panic 或依赖瞬时故障崩溃后会自动拉起;
  • 启动顺序:server 通过 depends_oncondition: service_healthy 等待 Postgres 与 Valkey 的健康检查通过,worker 又额外等待 server 健康(L96-L100L146-L152);
  • Redis URL 有兜底CLAUDE_MEM_REDIS_URL: ${CLAUDE_MEM_REDIS_URL:-redis://valkey:6379},未设置时默认指向栈内 valkey,可通过同名变量覆盖为外部 Redis;
  • 数据卷:server 与 worker 共享 claude-mem-data 卷,挂载到 /data/claude-mem,与 CLAUDE_MEM_DATA_DIR=/data/claude-mem 对应;
  • legacy 运行时永不启动:注释明确说明旧版 worker-service.cjs 运行时在这套栈中 NEVER spawned,server 容器跑 server-beta-service.cjs --daemon,worker 容器跑 server-beta-service.cjs worker start

三、必填密钥:缺一个就拒绝启动

Compose 文件把 Postgres 凭据定义为「无默认值的必填环境变量」,使用了 ${VAR:?message} 的 fail-fast 语法(docker-compose.yml):

POSTGRES_USER: ${POSTGRES_USER:?POSTGRES_USER is required}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
POSTGRES_DB: ${POSTGRES_DB:?POSTGRES_DB is required}

因此启动方式必须二选一:

# 方式一:.env 文件
echo 'POSTGRES_USER=mem
POSTGRES_PASSWORD=change-me
POSTGRES_DB=mem' > .env
docker compose up --build

# 方式二:内联传入
POSTGRES_USER=mem POSTGRES_PASSWORD=change-me POSTGRES_DB=mem docker compose up --build

文件头注释明确警告:此文件不得原样部署到任何公网可达环境(包括 VPN 可达的 staging),缺失任一必填密钥时栈会直接拒绝启动。此外还支持(注释掉的可选配置)通过 CREDENTIALS_FILE 把提供者/API 密钥以只读文件挂载到 /run/secrets/claude-mem-credentials,替代内联环境变量。

四、环境变量全解:server 与 worker 的差异

文档列出的 5 个变量是精简版;结合 docker-compose.yml,完整的关键变量如下:

变量 取值(server) 说明
CLAUDE_MEM_CONTAINER_MODE server / worker 容器模式选择,决定 entrypoint 分支(见下一节)
CLAUDE_MEM_DOCKER "1" 标记容器环境,启动校验会据此拒绝 local-dev 鉴权并强制完整 Postgres+Valkey 配置
CLAUDE_MEM_RUNTIME server-beta 固定运行时,由 validateServerBetaEnv() 启动时校验
CLAUDE_MEM_HOST / CLAUDE_MEM_SERVER_HOST 0.0.0.0 监听地址,容器内必须放开到 0.0.0.0 才能被端口映射访问
CLAUDE_MEM_SERVER_PORT "37877" server-beta 运行时端口,即 compose 映射与 healthcheck 使用的端口
CLAUDE_MEM_WORKER_HOST / CLAUDE_MEM_WORKER_PORT 0.0.0.0 / "37877" 注释标注为「旧库仍在读取的 legacy 变量」,与 server 端口保持对齐,保证既有 E2E 驱动与 viewer 继续工作
CLAUDE_MEM_DATA_DIR /data/claude-mem 数据目录,对应 claude-mem-data
CLAUDE_MEM_QUEUE_ENGINE bullmq 队列引擎,绑定 Valkey
CLAUDE_MEM_REDIS_URL redis://valkey:6379(可覆盖) 队列后端地址
CLAUDE_MEM_REDIS_MODE docker Redis 连接模式
CLAUDE_MEM_SERVER_DATABASE_URL postgres://user:pass@postgres:5432/db 由必填密钥拼装出的数据库连接串
CLAUDE_MEM_AUTH_MODE api-key Docker 内唯一被允许的鉴权模式,local-dev 会被启动校验拒绝
CLAUDE_MEM_CHROMA_ENABLED "false" 栈内不启用 Chroma 向量存储
CLAUDE_MEM_GENERATION_DISABLED "true"(仅 server) HTTP 服务不消费 BullMQ 任务,避免 provider 调用拖慢 HTTP 延迟;worker 端由 entrypoint 主动 unset 该变量强制启用生成

worker 服务额外注入生成所需的 provider 配置(docker-compose.yml):

CLAUDE_MEM_SERVER_PROVIDER: ${CLAUDE_MEM_SERVER_PROVIDER:-claude}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
CLAUDE_MEM_ANTHROPIC_API_KEY: ${CLAUDE_MEM_ANTHROPIC_API_KEY:-}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}

注释说明:ANTHROPIC_API_KEY(或 CLAUDE_MEM_ANTHROPIC_API_KEY)是真实生成所必需的,缺失时 worker 保持运行但不会产出任何观察。

Compose 头部还解释了两种鉴权路径的成本差异(docker-compose.yml):

  • API-KEY 模式(本栈默认):每个请求携带 server api-key create 创建的 bearer key,生成消耗配置的 provider API key,按 token 计费,高观察量下可能费用可观;
  • SUBSCRIPTION 模式:把生成 provider 指向 Claude 订阅/Pro 会话而非按量计费的 API key,以规避 token 成本;HTTP 侧的 bearer 鉴权契约不变。

五、一个镜像,三种角色:entrypoint 如何切换模式

server 和 worker 使用同一份 Dockerfile 构建的行为差异,全部由 entrypoint.sh 通过 CLAUDE_MEM_CONTAINER_MODE 分派(L37-L60):

#   CLAUDE_MEM_CONTAINER_MODE=server (默认) — HTTP server-beta,无 worker
#   CLAUDE_MEM_CONTAINER_MODE=worker        — 仅 BullMQ 生成 worker
#   CLAUDE_MEM_CONTAINER_MODE=shell         — 透传到 "$@",用于运维工具
case "$MODE" in
  server) exec bun "$SERVER_BETA_SCRIPT" --daemon ;;
  worker) unset CLAUDE_MEM_GENERATION_DISABLED
          exec bun "$SERVER_BETA_SCRIPT" worker start ;;
  shell|tooling) exec "$@" ;;
esac

其中 $SERVER_BETA_SCRIPT 指向 /opt/claude-mem/scripts/server-service.cjs(即仓库中打包后的 plugin/scripts/server-service.cjs)。worker 分支里那句 unset CLAUDE_MEM_GENERATION_DISABLED 很关键:它保证即使共享的 compose 文件给全局设置了「禁用生成」,worker 进程自身一定是生成进程。

entrypoint 还处理了凭据注入:若设置了 CLAUDE_MEM_CREDENTIALS_FILE 且文件存在,则把它复制为 $HOME/.claude/.credentials.jsonchmod 600;文件不存在时直接报错退出。随后 entrypoint 会导出 CLAUDE_MEM_DOCKER=1 与默认 CLAUDE_MEM_RUNTIME=server-beta,与 /.dockerenv 的双重检测一起确保容器内环境校验严格生效(entrypoint.sh)。

六、镜像内容:Dockerfile 里装了什么

docker/claude-mem/Dockerfile 基于 node:20,安装顺序与要点:

  1. 系统依赖:git curl ca-certificates unzip jq less procps uuid-runtime sqlite3
  2. Bun 1.3.12BUN_VERSION build-arg 可覆盖)安装到 /usr/local/bun,作为 server-beta 运行时的 JS 运行时;
  3. uv 0.11.7UV_VERSION build-arg)安装到 /usr/local/bin,为可能需要的 Python 工具链提供环境;
  4. node 用户全局安装 @anthropic-ai/claude-codeCLAUDE_CODE_VERSION build-arg,默认 latest,建议 CI 中钉死版本);
  5. COPY plugin/ /opt/claude-mem/ 后执行 npm install --omit=dev --legacy-peer-deps——分层顺序是刻意的:插件文件放在 npm install 层之后,迭代插件不会击穿 CLI 安装缓存(见 docker/claude-mem/README.md);
  6. 预建 /home/node/.claude/home/node/.claude-mem/data/claude-mem 三个挂载点,WORKDIR /home/nodeENTRYPOINT 指向 entrypoint。

七、鉴权链路:从 API Key 创建到 V1 路由保护

docs/docker.md 的最后一句要求「先创建 API Key 再用 V1 写路由」。仓库中完整的做法是(参见 docs/server.md):

claude-mem server api-key create \
  --name "ci" \
  --scope memories:read,memories:write
  • 原始 key 只显示一次,Postgres 的 api_keys.key_hash 里只存 SHA-256 哈希;
  • 吊销用 claude-mem server api-key revoke <id>;每次请求都会按哈希重新加载数据库行做校验,没有可被投毒的内存缓存;
  • 路由层的对应实现在 ServerV1Routes.ts:读路由(如 GET /v1/projects)用 requireServerAuth(..., { requiredScopes: ['memories:read'] }),写路由(如 POST /v1/projectsPOST /v1/sessions/start)要求 memories:write;而 /healthz/v1/info 在鉴权之外。项目级 key 被明确禁止创建项目(返回 403)。

安全约束上,docs/server.md 给出了 Docker 场景下最重要的一条红线:不要在容器内启用 CLAUDE_MEM_AUTH_MODE=local-dev——loopback 绕过依赖请求来自 127.0.0.1,这个边界在容器内没有意义;启动校验器对「Docker + local-dev」组合会直接以非零退出码拒绝启动。

八、横向扩展生成与 E2E 验证

生成吞吐通过扩 worker 容器数实现,这是 HTTP/生成分离架构的直接收益:

docker compose up -d --scale claude-mem-worker=N

仓库还自带一个 E2E 覆盖层 docker-compose.e2e.yml:新增一个 node:20-alpine 的一次性容器 server-e2e,等三个核心服务全部 healthy 后,以 E2E_BASE_URL=http://claude-mem-server:37877 跨 compose 网络调用 docker/e2e/server-e2e.mjs,配套的宿主机驱动脚本是 scripts/e2e-server-docker.sh

九、区分:docker/claude-mem 下的单容器调试 harness

注意不要与根目录 Compose 栈混淆:docker/claude-mem/ 下的 run.sh + entrypoint.sh 是另一套单容器端到端调试工具——run.sh 按「ANTHROPIC_API_KEY → macOS Keychain → ~/.claude/.credentials.json」的顺序提取凭据,以只读文件挂载进容器,把宿主机的 .docker-claude-mem-data 目录持久化,退出后可以用 sqlite3 .docker-claude-mem-data/claude-mem.db 'select count(*) from observations' 检查捕获到的观察。它用于不污染宿主机地跑通 claude --plugin-dir /opt/claude-mem 全流程,而不是生产部署;生产与可部署验证请以根目录 docker-compose.yml 为准。

十、小结

这套 Docker 部署方案的要点可以浓缩为五条:

  1. docker compose up --build 拉起 Postgres 17 + Valkey 8 + server-beta HTTP 服务 + BullMQ worker 四件套,curl http://127.0.0.1:37877/healthz 验证;
  2. POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB 必填、无默认值,缺失即拒绝启动;
  3. CLAUDE_MEM_AUTH_MODE 在容器内只能取 api-keylocal-dev 会被启动校验拒绝;
  4. 受保护 V1 路由使用前必须 claude-mem server api-key create,原始 key 仅显示一次,只存哈希;
  5. HTTP 服务禁用生成、worker 容器专职消费队列,用 --scale claude-mem-worker=N 横向扩展生成吞吐。
登录后查看全文
热门项目推荐
相关项目推荐