Open Notebook Docker Compose 多容器部署实战:从 docker-compose.yml 到 AI 供应商配置的完整指南
本文以 Open Notebook 官方安装文档 Docker Compose 安装指南 为主体,完整讲解如何通过多容器方式部署 Open Notebook:包括 docker-compose.yml 每个服务、每个环境变量的含义与底层实现印证、启动与验证流程、Ollama 本地模型扩展、常用运维命令以及常见故障排查。读完本文,你可以独立完成一次可复现、可维护的 Open Notebook 本地部署,并理解容器内 API、后台 Worker 与前端三个进程的组织方式。
部署架构概览:两个容器,四类进程
Open Notebook 的推荐部署方式是 Docker Compose 多容器方案,官方文档将其定位为“适合大多数用户”的安装路径。整个栈由两个容器组成:
- surrealdb:基于
surrealdb/surrealdb:v2镜像的 SurrealDB 数据库,使用 RocksDB 引擎持久化到./surreal_data目录,负责存储笔记本、来源、笔记、凭据等全部业务数据; - open_notebook:基于
lfnovo/open_notebook:v1-latest镜像的应用容器,对外暴露 8502(Web UI)与 5055(REST API)两个端口。
值得强调的是,open_notebook 容器并不是只跑一个进程。查看 Dockerfile 与 supervisord.conf 可以确认:镜像通过 supervisord 在容器内同时管理三个进程——
- api:
uvicorn api.main:app --host 0.0.0.0 --port 5055,即 FastAPI 后端(见 supervisord.conf); - worker:
surreal-commands-worker后台任务进程,并发数由OPEN_NOTEBOOK_WORKER_MAX_TASKS控制,默认 5(见 supervisord.conf); - frontend:Next.js 前端服务,端口 8502,且会先执行 scripts/wait-for-api.sh 等待 API 就绪后再启动(见 supervisord.conf)。
这解释了文档中“首次启动可能需要 20~30 秒”的现象:需要数据库、API、前端依次就绪。另外,两个容器之间通过 Compose 内部网络连接(如 SURREAL_URL=ws://surrealdb:8000/rpc),因此宿主机端口 8000 仅用于本地调试,数据库端口被刻意绑定到 127.0.0.1 以避免默认凭据暴露在网络中——这一点在根目录 docker-compose.yml 的注释中有明确说明。
前置条件
开始部署前需要准备:
- Docker Desktop(或任意支持
docker compose的 Docker 环境); - 约 5~10 分钟时间;
- 至少一个 AI 供应商的 API Key(新手推荐 OpenAI;也可选择 Anthropic、Google、Groq 等,或后续使用 Ollama 本地模型)。
镜像同时发布于 Docker Hub(lfnovo/open_notebook)与 GitHub Container Registry(ghcr.io/lfnovo/open-notebook)。若 Docker Hub 拉取受限,可将镜像地址替换为 GHCR 的等价标签,其余配置不变。
第一步:准备 docker-compose.yml
获取官方 docker-compose.yml 有三种方式:从仓库根目录直接复制官方文件(推荐),或在本地按下面的内容手工创建。以下即为官方完整配置(与仓库根目录 docker-compose.yml 一致):
services:
surrealdb:
image: surrealdb/surrealdb:v2
# Credentials default to root:root for a zero-config local setup. Before
# exposing this instance to a network, set SURREAL_USER / SURREAL_PASSWORD
# in a .env file (see .env.example) — they are applied here and to the
# open_notebook service below, so the two always stay in sync.
# List (exec) form so each interpolated value stays a single argument —
# a password containing spaces would otherwise be split into several.
command: ["start", "--log", "info", "--user", "${SURREAL_USER:-root}", "--pass", "${SURREAL_PASSWORD:-root}", "rocksdb:/mydata/mydatabase.db"]
user: root # Required for bind mounts on Linux
ports:
# Bound to localhost only: the open_notebook service reaches this over
# the internal compose network regardless, so the host port is purely
# for local debugging (e.g. Surrealist, `surreal sql`). Exposing this
# on 0.0.0.0 would let anyone who can reach the host connect with the
# default root:root credentials.
- "127.0.0.1:8000:8000"
volumes:
- ./surreal_data:/mydata
environment:
- SURREAL_EXPERIMENTAL_GRAPHQL=true
restart: always
pull_policy: always
open_notebook:
image: lfnovo/open_notebook:v1-latest
ports:
- "8502:8502" # Web UI
- "5055:5055" # REST API
environment:
# REQUIRED: Change this to your own secret string
# This encrypts your API keys in the database
- OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string
# Database connection. SURREAL_USER / SURREAL_PASSWORD default to root:root
# for local use; override them in a .env file before exposing the instance
# (the same values configure the surrealdb service above).
- SURREAL_URL=ws://surrealdb:8000/rpc
- SURREAL_USER=${SURREAL_USER:-root}
- SURREAL_PASSWORD=${SURREAL_PASSWORD:-root}
- SURREAL_NAMESPACE=open_notebook
- SURREAL_DATABASE=open_notebook
volumes:
- ./notebook_data:/app/data
depends_on:
- surrealdb
restart: always
pull_policy: always
关键配置逐项解读
surrealdb 服务
command采用 exec(列表)形式而非字符串拼接:每个插值变量保持为独立参数,若密码包含空格,字符串形式会被 shell 拆分成多个参数导致认证失败;user: root是 Linux bind mount 的必需项:Docker 以 root 创建宿主机挂载目录,而 SurrealDB 默认以非 root 用户运行会因权限不足报Permission denied(详见后文故障排查);rocksdb:/mydata/mydatabase.db指定 RocksDB 存储引擎与数据文件位置,配合./surreal_data:/mydata卷实现数据持久化;SURREAL_EXPERIMENTAL_GRAPHQL=true启用实验性 GraphQL 接口;${SURREAL_USER:-root}语法表示:从.env读取SURREAL_USER,未定义时回退为root。该变量同时作用于数据库服务端启动参数和应用侧连接参数,保证两边凭据始终同步;- 端口绑定
127.0.0.1:8000:8000:宿主端口仅供本地调试(如连接 Surrealist 图形客户端或surreal sqlCLI),应用容器通过 Compose 内部网络直连surrealdb:8000。
open_notebook 服务
OPEN_NOTEBOOK_ENCRYPTION_KEY是必填项:用于加密数据库中存储的 AI 供应商凭据(API Key)。官方环境参考文档(环境变量参考)强调:丢失或更换此密钥后,已存储的凭据将无法解密,因此务必妥善保存;SURREAL_URL=ws://surrealdb:8000/rpc通过 Compose 服务名surrealdb解析,无需关心宿主机端口;./notebook_data:/app/data挂载用户数据目录。结合 Dockerfile 可以看到,/app/data下还承载着 Docling、Crawl4AI 等可选重运行时的缓存(wheels、Chromium、HuggingFace 模型),首次启动启用后下载一次即可在重启与升级间复用;depends_on: surrealdb声明启动顺序依赖;- 仓库根目录的 docker-compose.yml 还保留了若干注释掉的可选环境变量,按需取消注释即可:
OPEN_NOTEBOOK_ENABLE_DOCLING=true:启用 Docling 内容处理引擎(含 OCR 与图片来源支持,依赖较大的 ML 栈);OPEN_NOTEBOOK_ENABLE_CRAWL4AI=true:容器内安装本地 Crawl4AI(自带 Chromium 浏览器);CRAWL4AI_API_URL=http://crawl4ai:11235:改用远程 Crawl4AI 服务器,跳过本地安装;OPEN_NOTEBOOK_WORKER_MAX_TASKS=1:单 GPU / 本地 LLM 场景下调低后台任务并发,避免并行请求压垮模型。这些运行时安装由 scripts/docker-entrypoint.sh 在 supervisord 启动前完成。
编辑文件
- 将
change-me-to-a-secret-string替换为你自己的随机字符串(任意字符串均可,例如my-super-secret-key-123); - (可选)若要使用非默认的
root:root数据库凭据,在docker-compose.yml同目录创建.env文件写入SURREAL_USER=...与SURREAL_PASSWORD=...,两个服务会自动读取同一份值。完整格式可参考仓库的 .env.example,其中还列出了OPENAI_API_KEY、CHUNK_SIZE、CHUNK_OVERLAP、API_URL等可选配置。
第二步:启动服务
在 docker-compose.yml 所在目录打开终端:
docker compose up -d
等待 15~20 秒(首次拉取镜像会更久),预期看到类似:
✅ surrealdb running on :8000
✅ open_notebook running on :8502 (UI) and :5055 (API)
检查状态:
docker compose ps
第三步:验证安装
API 健康检查:
curl http://localhost:5055/health
# 应返回: {"status": "healthy"}
该端点由 FastAPI 应用直接提供,源码见 api/main.py 中的 @app.get("/health") 处理器。
前端访问: 浏览器打开 http://localhost:8502,应看到 Open Notebook 界面。若前端白屏或报错,通常是前端仍在等待 API(supervisord 中的 frontend 程序会先执行等待脚本),稍候重试即可。
第四步:配置 AI 供应商
- 进入 Settings → API Keys;
- 点击 Add Credential;
- 选择供应商(如 OpenAI、Anthropic、Google);
- 填写名称并粘贴 API Key(Key 在对应供应商官网申请);
- 点击 Save;
- 点击 Test Connection,应显示连接成功;
- 点击 Discover Models → Register Models,完成模型发现与注册。
这些操作对应后端的路由实现(api/routers/credentials.py、api/routers/providers.py),凭据经 OPEN_NOTEBOOK_ENCRYPTION_KEY 加密后存入 SurrealDB。除 UI 外,也支持在 .env 中以 OPENAI_API_KEY 等环境变量方式注入,官方文档推荐 UI 配置以获得更好的安全性与灵活性(见 .env.example 注释)。
第五步:创建第一个笔记本
- 点击 New Notebook;
- 名称填写如 "My Research",描述 "Getting started";
- 点击 Create。
至此,一个完整可用的 Open Notebook 实例部署完成。
进阶配置:加入 Ollama 本地模型
若希望使用免费、私密的本地模型,官方提供了现成示例 examples/docker-compose-ollama.yml。该文件在基础栈之上增加了一个 ollama 服务:
ollama:
image: ollama/ollama:latest
ports:
- "11434:11434"
volumes:
- ollama_models:/root/.ollama
restart: always
volumes:
ollama_models:
手动添加时,把上述 ollama 服务与顶层 volumes 段并入你现有的 docker-compose.yml 即可。然后重启并拉取模型(示例文件的用法注释给出的命令是 docker exec open_notebook-ollama-1 ollama pull mistral,实际容器名以 docker ps 输出为准):
docker compose restart
docker exec <ollama容器名> ollama pull mistral
在设置界面中配置 Ollama:
- Settings → API Keys;
- Add Credential → 选择 Ollama;
- Base URL 填
http://ollama:11434(容器间以服务名互访,不要填localhost); - Save 后 Test Connection;
- Discover Models → Register Models。
环境变量参考
| 变量 | 用途 | 示例 / 默认值 |
|---|---|---|
OPEN_NOTEBOOK_ENCRYPTION_KEY |
凭据加密密钥(必填) | my-secret-key |
SURREAL_URL |
数据库连接地址 | ws://surrealdb:8000/rpc |
SURREAL_USER |
数据库用户 | 默认 root |
SURREAL_PASSWORD |
数据库密码 | 默认 root |
SURREAL_NAMESPACE |
数据库命名空间 | open_notebook |
SURREAL_DATABASE |
数据库名 | open_notebook |
API_URL |
API 对外 URL(反向代理 / 自定义域名时设置) | http://localhost:5055 |
OPEN_NOTEBOOK_EMBEDDING_BATCH_SIZE |
覆盖 embedding 批大小,CPU-only 或严格限流的本地 provider 建议调小(纯 CPU 本地环境推荐 8) |
默认 50 |
OPEN_NOTEBOOK_WORKER_MAX_TASKS |
Worker 并发任务数 | 默认 5;单 GPU / 本地 LLM 建议 1 |
补充说明(依据环境变量参考):
OPEN_NOTEBOOK_ENCRYPTION_KEY支持以_FILE后缀引用 Docker secrets;变量名大小写敏感,等号两侧不能有空格;OPEN_NOTEBOOK_WORKER_MAX_TASKS在 worker 启动时从进程环境读取,在 Docker 中放在environment:下即可生效。
常用运维操作
# 停止服务
docker compose down
# 查看日志(全部 / 指定服务,容器内服务名为 api、worker、frontend)
docker compose logs -f
docker compose logs -f <open_notebook容器名>
# 重启
docker compose restart
# 升级到最新版本
docker compose down
docker compose pull
docker compose up -d
# 删除所有数据(含命名卷)
docker compose down -v
注意两个细节:由于数据库端口只绑定到 127.0.0.1,如需在另一台机器上用 SurrealDB 客户端调试,需临时修改端口映射并配合强凭据;docker compose down -v 会同时删除 ./surreal_data、./notebook_data 等 bind mount 之外的命名卷数据,操作前请备份。
故障排查
“Cannot connect to API” 错误
- 确认 Docker 正在运行:
docker ps; - 确认服务状态:
docker compose ps; - 查看 API 日志:
docker compose logs(容器内实际日志来自 supervisord 管理的 api 进程,可用docker logs <open_notebook容器名>查看); - 首次启动服务可能需要 20~30 秒,耐心等待。
端口冲突
若提示 “Port 8502 already in use”,修改宿主端口映射:
ports:
- "8503:8502" # 改用 8503
- "5055:5055" # API 端口保持不变
然后访问 http://localhost:8503。
凭据问题
- 进入 Settings → API Keys;
- 对相应凭据点击 Test Connection;
- 失败时到供应商官网核验 Key 是否有效;
- 确认账户有可用额度;
- 必要时删除并重新创建该凭据。
数据库连接问题
查看 SurrealDB 日志定位原因:
docker compose logs surrealdb
重置数据库(会清空数据):
docker compose down -v
docker compose up -d
数据库权限被拒(Linux)
若 SurrealDB 日志中出现 Permission denied 或 Failed to create RocksDB directory:
docker compose logs surrealdb | grep -i permission
原因是 SurrealDB 以非 root 用户运行,而 Docker 创建的 bind mount 目录属主为 root。按本文“关键配置逐项解读”所述,给 surrealdb 服务加上 user: root(官方 compose 文件已内置该修复),然后 docker compose down -v && docker compose up -d 重启。
其他部署形态与后续步骤
除标准多容器方案外,examples/ 目录提供了更多带注释的变体配置:
- examples/docker-compose-ollama.yml:内置 Ollama 的本地 AI 方案(免费、隐私优先);
- examples/docker-compose-single.yml:单容器一体化部署(含容器内 SurrealDB,官方标注已弃用,将在 v2 移除);
- examples/docker-compose-dev.yml:面向贡献者与开发者的开发栈。
后续建议路径:
生产环境部署请额外阅读 安全加固 与 反向代理配置:务必将 SURREAL_USER/SURREAL_PASSWORD 改为强凭据、替换 OPEN_NOTEBOOK_ENCRYPTION_KEY、避免将 8000 端口暴露到公网,并在自定义域名下显式设置 API_URL(Dockerfile 说明该变量用于让前端连接正确的 API 地址,未设置时按请求自动推断)。
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