首页
/ Open Notebook Docker Compose 多容器部署实战:从 docker-compose.yml 到 AI 供应商配置的完整指南

Open Notebook Docker Compose 多容器部署实战:从 docker-compose.yml 到 AI 供应商配置的完整指南

2026-09-05 15:05:38作者:董斯意

本文以 Open Notebook 官方安装文档 Docker Compose 安装指南 为主体,完整讲解如何通过多容器方式部署 Open Notebook:包括 docker-compose.yml 每个服务、每个环境变量的含义与底层实现印证、启动与验证流程、Ollama 本地模型扩展、常用运维命令以及常见故障排查。读完本文,你可以独立完成一次可复现、可维护的 Open Notebook 本地部署,并理解容器内 API、后台 Worker 与前端三个进程的组织方式。

部署架构概览:两个容器,四类进程

Open Notebook 的推荐部署方式是 Docker Compose 多容器方案,官方文档将其定位为“适合大多数用户”的安装路径。整个栈由两个容器组成:

  1. surrealdb:基于 surrealdb/surrealdb:v2 镜像的 SurrealDB 数据库,使用 RocksDB 引擎持久化到 ./surreal_data 目录,负责存储笔记本、来源、笔记、凭据等全部业务数据;
  2. open_notebook:基于 lfnovo/open_notebook:v1-latest 镜像的应用容器,对外暴露 8502(Web UI)与 5055(REST API)两个端口。

值得强调的是,open_notebook 容器并不是只跑一个进程。查看 Dockerfilesupervisord.conf 可以确认:镜像通过 supervisord 在容器内同时管理三个进程——

  • apiuvicorn api.main:app --host 0.0.0.0 --port 5055,即 FastAPI 后端(见 supervisord.conf);
  • workersurreal-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 sql CLI),应用容器通过 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_KEYCHUNK_SIZECHUNK_OVERLAPAPI_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 供应商

  1. 进入 Settings → API Keys
  2. 点击 Add Credential
  3. 选择供应商(如 OpenAI、Anthropic、Google);
  4. 填写名称并粘贴 API Key(Key 在对应供应商官网申请);
  5. 点击 Save
  6. 点击 Test Connection,应显示连接成功;
  7. 点击 Discover Models → Register Models,完成模型发现与注册。

这些操作对应后端的路由实现(api/routers/credentials.pyapi/routers/providers.py),凭据经 OPEN_NOTEBOOK_ENCRYPTION_KEY 加密后存入 SurrealDB。除 UI 外,也支持在 .env 中以 OPENAI_API_KEY 等环境变量方式注入,官方文档推荐 UI 配置以获得更好的安全性与灵活性(见 .env.example 注释)。

第五步:创建第一个笔记本

  1. 点击 New Notebook
  2. 名称填写如 "My Research",描述 "Getting started";
  3. 点击 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:

  1. Settings → API Keys
  2. Add Credential → 选择 Ollama
  3. Base URL 填 http://ollama:11434(容器间以服务名互访,不要localhost);
  4. SaveTest Connection
  5. 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_TASKSworker 启动时从进程环境读取,在 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” 错误

  1. 确认 Docker 正在运行:docker ps
  2. 确认服务状态:docker compose ps
  3. 查看 API 日志:docker compose logs(容器内实际日志来自 supervisord 管理的 api 进程,可用 docker logs <open_notebook容器名> 查看);
  4. 首次启动服务可能需要 20~30 秒,耐心等待。

端口冲突

若提示 “Port 8502 already in use”,修改宿主端口映射:

ports:
  - "8503:8502"  # 改用 8503
  - "5055:5055"  # API 端口保持不变

然后访问 http://localhost:8503

凭据问题

  1. 进入 Settings → API Keys
  2. 对相应凭据点击 Test Connection
  3. 失败时到供应商官网核验 Key 是否有效;
  4. 确认账户有可用额度;
  5. 必要时删除并重新创建该凭据。

数据库连接问题

查看 SurrealDB 日志定位原因:

docker compose logs surrealdb

重置数据库(会清空数据):

docker compose down -v
docker compose up -d

数据库权限被拒(Linux)

若 SurrealDB 日志中出现 Permission deniedFailed 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/ 目录提供了更多带注释的变体配置:

后续建议路径:

  1. 添加内容:Sources、笔记本、文档;
  2. 配置模型偏好:Settings → Models;
  3. 探索功能:Chat、搜索、Transformations;
  4. 深入文档用户指南配置参考

生产环境部署请额外阅读 安全加固反向代理配置:务必将 SURREAL_USER/SURREAL_PASSWORD 改为强凭据、替换 OPEN_NOTEBOOK_ENCRYPTION_KEY、避免将 8000 端口暴露到公网,并在自定义域名下显式设置 API_URLDockerfile 说明该变量用于让前端连接正确的 API 地址,未设置时按请求自动推断)。

登录后查看全文
热门项目推荐
相关项目推荐