← 返回归档

NAS Calibre-Web 升级攻坚全记录(2026-09-20~21)

2026-09-21 4 分钟阅读 更新于 2026-10-03
数码折腾
NAS Calibre-Web 升级攻坚全记录(2026-09-20~21)
目录

时间:2026-09-20 20:00 → 2026-09-21 00:30 主机:REDACTED_HOSTNAME(QNAP TS-451D · QTS 5.2.10 · Docker 27.1.2-qnap8) 起因:Farmer 提问「web-calibre 容器新版本为什么不用?升级后服务起不来,也导致本地 Calibre 客户端不能升 9.x」


一、结论先行

问题结论
新版本为什么不能用Calibre 9 删除了 books.isbn/lccn/flags,而 Calibre-Web ≤0.6.25 在 ORM 里硬编码映射了这些列 → 页面 500
是"服务起不来"吗不是。容器正常启动,是页面报错
修好了吗✅ 已升到 0.6.27-ls402,实测全绿
阻塞 Calibre 桌面 9.x 吗✅ 已解锁,实测 Calibre 9.15 转换格式成功
自定义列要处理吗❌ 不用(是 composite,在 Calibre-Web 忽略名单里)

二、技术根因(源码级)

Calibre 9 做了什么

kovidgoyal/calibre → src/calibre/db/schema_upgrades.py → upgrade_version_26:

for x in {'flags', 'isbn', 'lccn'} & columns:
    statements.append(f'ALTER TABLE books DROP COLUMN {x};')

同时新建 books_pages_link、重建 meta 视图、PRAGMA application_id = 0x63616c69、user_version 26 → 27。

关键特性:Calibre 打开书库时在 BEGIN EXCLUSIVE TRANSACTION 里原地升级,不可逆。

Calibre-Web 为什么会崩

  • ≤0.6.25:cps/db.py 的 Books 模型有 isbn = Column(...) / flags = Column(...) → SQLAlchemy 生成 SELECT ... books.isbn ... → no such column: books.isbn → HTTP 500
  • 0.6.26 起:commit 7f7fc884c2(2026-01-31)把这两列注释掉 → 不再查询 → 修复
  • ⚠️ Calibre-Web 从不读 PRAGMA user_version(源码 5 处文件零命中)→ 无版本判断,只在查询时炸

为什么极难自查

错误只写进 /config/calibre-web.log(应用日志),不进 docker logs(容器 stdout)。 所以看容器日志只会看到"一切正常启动",真正原因藏在 config 目录的日志文件里。


三、自定义列排查(虚惊一场)

custom_columns 表(1 行)
  label     = formats
  name      = 格式
  datatype  = composite        ← 关键
  display   = {"composite_template": "{:'re(approximate_formats(), ',', ', ')'}", ...}

custom_column_1 表:0 行   ← composite 是计算列,不存数据

Calibre-Web cps/db.py:

cc_exceptions = ['composite', 'series']
if row.datatype not in cc_exceptions:   # ← composite 直接跳过

→ composite 落在忽略名单内,不会触发 books_custom_column_N_link 查询 → issue #3643(Calibre 9 + 自定义列 → 书详情页/OPDS 失败)对本库不适用

注:cc_exceptions 里之所以有 composite,正是源于 2016 年的 cbw #20 —— 那位报告人的列也叫 formats、也是 composite,janeczku 据此把它加进了忽略名单。


四、决定性复现实验

在库副本上施加 upgrade_version_26 的等效迁移(删三列 + 重建 meta 视图 + application_id/user_version),然后同一份库分别跑新旧两个 Calibre-Web:

URL0.6.20(旧)0.6.26(新)
/ 首页500200
/login200200
/opds200200
/opds/books/letter/00500200

→ 症状精确复现,修复确认。(/login 正常是因为它不查书)


五、升级执行(三步走,每步都带回滚)

① 备份          一致快照(SQLite backup API,非裸拷贝)
                → REDACTED_BACKUP_DIR/
② 沙箱验证      库副本 + config 副本 + 独立端口(8093/8094/8095)
                不碰生产容器/配置/书库
③ 生产切换      docker rename 旧容器保留为回滚锚点 → 同规格起新容器
                → 等待 → 验证 → 失败自动回滚

升级链:0.6.20-ls225 → 0.6.26-ls388 → 0.6.27-ls402(当日发布,含 2026-09 安全批次)

最终验证(生产 8083):

/  200    /login  200    /opds  200
/book/1  200   ← 旧版必崩的页面
/opds/books/letter/00  200
restarts=0   stdout 错误签名=0   app.db 21 表 / 3 用户完整保留

终局实测(最有说服力的一条)

Farmer 升 Calibre 桌面 9.15 并成功转换一本书的格式 → 书库已升到 schema 27:

user_version     : 27
application_id   : 0x63616c69
books_pages_link : PRESENT(1065 行)
books.isbn/lccn/flags : 全部已删除
books 行数       : 1065(一本书没丢)

而 Calibre-Web 0.6.27 完全扛住:/book/1 与 /opds/* 全 200、零错误签名。 → 如果当初没升级,此刻这两个页面必定 500。整条链路验证通过。


六、镜像加速的真相(重要可复用结论)

registry-mirrors 只对 Docker Hub(docker.io)生效。

✅ linuxserver/calibre-web:0.6.27-ls402            → 命中加速,实测 5 秒
❌ lscr.io/linuxserver/calibre-web:0.6.27-ls402    → 绕过加速,直连境外 → 卡死
  • 本机 daemon 配置:/share/CACHEDEV1_DATA/.qpkg/container-station/etc/docker.json
    "registry-mirrors": ["https://docker.1ms.run", "https://docker.xuanyuan.me"]
    
  • 实测 docker pull hello-world 5 秒完成 → 加速本身完全正常
  • 规则:拉 LinuxServer 镜像一律用 Docker Hub 路径,不要用 lscr.io(其镜像同时发布在 Hub 上)
  • 不需要改 daemon.json —— 改它要重启 dockerd,会导致所有容器重启,代价大而无必要
  • ⚠️ 容器 Station UI 走的是 Hub + 加速,所以 UI 能拉、命令行用 lscr.io 不能拉 —— 差异就在仓库路径

© 2026 Farmer · 静态站(Hugo) · 分享生命的体验 · 热爱度过的每一天
无广告 · 无跟踪脚本 · 可能主要就自己看😄