Docker 部署 Calibre-Web 遇到 “数据库路径无效” 的排查与解决

警告
本文最后更新于 2024-09-27,文中内容可能已过时。

Docker 部署 Calibre-Web 遇到 “数据库路径无效” 的排查与解决

在用 Docker 部署 Calibre-Web 时,有人会遇到这样一个错误:

text

calibre-web 数据库路径无效,请输入正确的路径

刚开始看,这似乎是 Calibre 的 metadata.db 文件损坏或者架构不兼容的问题。但经过实际排查,这种情况 更多是 Docker 挂载路径和权限配置问题,尤其是在 Calibre-Web 容器运行用户不是 root 时。

本文记录一次完整的排查过程和解决方案,供大家参考。


Calibre-Web 并不是自己存储电子书数据,而是直接读取 Calibre 主程序的书库(Library)目录。 书库目录中最重要的文件就是:

text

metadata.db

它是一个 SQLite 数据库,存储了书籍的元数据(书名、作者、标签、路径等)。 Calibre-Web 启动时,需要在配置中指定这个数据库所在的目录路径。


有读者怀疑:

“我在 x86_64 上创建的 metadata.db,放到 ARM 上会不会不能用?”

答案是:

  • metadata.db 是 SQLite 数据库,x86_64 和 ARM64 都是小端序,理论上完全兼容。

  • 如果 SQLite 版本差距太大(比如 Calibre 写入时用的是新版本特性),ARM 端 SQLite 太旧,可能会读取失败,但这种情况少见。

  • 可以用以下命令验证文件健康度:

    bash

    sqlite3 /path/to/metadata.db "PRAGMA integrity_check;"

    如果返回 ok,说明数据库结构正常。

本次案例中,integrity_check 返回正常,排除了数据库损坏和架构不兼容的可能性。


部署配置(docker-compose.yml)如下:

yaml

volumes:
  - type: bind
    source: /DATA/AppData/calibre-web/config
    target: /config
  - type: bind
    source: /DATA/Media/Books
    target: /books

容器内 /books 映射到宿主机 /DATA/Media/Books。 Calibre-Web 配置“Calibre 数据库路径”时,必须填容器内路径 /books,而不是宿主机路径 /DATA/Media/Books


bash

docker exec -it calibre-web sh
ls -l /books

结果输出:

text

d?????????   ? ?    ?        ?            ? books

这是典型的 容器内挂载目录不可访问 的表现,说明即使挂载成功,也没有读取权限。


很多 Docker 镜像(例如 linuxserver/calibre-web)不是用 root 运行的,而是用一个普通用户,比如:

  • UID:1000
  • GID:1000 或
  • UID:911
  • GID:911

如果挂载的目录在宿主机的 /root/DATA 等路径下,而该路径的权限不允许 UID 1000 访问,即使挂载成功,容器内也会看到 d?????????

重点:

如果 Docker 使用了普通用户 UID 与 GID(例如 UID:1000, GID:1000),那么它挂载的路径如果在 root 路径下,需要添加权限它才可以访问到,否则能够成功挂载也会没有权限。


确保容器运行用户可以一路访问到 metadata.db 文件。

宿主机执行:

bash

# 检查每一级目录权限
ls -ld /DATA /DATA/Media /DATA/Media/Books

# 修改权限,让其他用户也能读
chmod 755 /DATA
chmod 755 /DATA/Media
chmod 755 /DATA/Media/Books

# 确保 metadata.db 可读
chmod 644 /DATA/Media/Books/metadata.db

如果需要更精确控制权限,可以直接改属主为容器用户:

bash

chown -R 1000:1000 /DATA/Media/Books

(UID/GID 按实际容器用户修改)


  1. Calibre-Web 配置

    • “Calibre 数据库路径”填写容器内路径:

      text

      /books
  2. Docker 挂载

    • 保证宿主机 /DATA/Media/Books 目录存在且权限正确
  3. 验证 进入容器运行:

    bash

    sqlite3 /books/metadata.db "PRAGMA integrity_check;"

    如果返回 ok,且 Calibre-Web 启动后能读取书籍列表,就说明问题解决。


  • 路径问题:Calibre-Web 要填容器内路径,不是宿主机路径。

  • 权限问题:非 root 容器用户需要对挂载目录和上级目录有可执行/可读权限。

  • 架构兼容性:x86_64 和 ARM64 的 SQLite 数据库是通用的,问题多半是版本或权限,不是文件本身。

  • 经验法则

    Docker 挂载目录的所有上级目录权限必须允许容器运行用户执行(x 权限),否则即使挂载成功也会显示 d????????? 无法访问。


+————————————————————–+ | 宿主机 (Host) | | | | /DATA/Media/Books <—- 目录权限必须允许容器用户读取 | | ├── metadata.db | | ├── Book1/ | | └── Book2/ | | | | docker-compose.yml: | | volumes: | | - /DATA/Media/Books : /books | +————————————————————–+ │ │ 挂载 (bind mount) ▼ +————————————————————–+ | Docker 容器 (Container) | | | | /books <—- 容器内访问路径,Calibre-Web 填这里 | | ├── metadata.db | | ├── Book1/ | | └── Book2/ | | | | 容器运行用户 UID:GID = 1000:1000 (非 root) | | → 必须能访问 /books 及其所有上级目录 | +————————————————————–+