【免费下载链接】Koffan
Free selfhosted groceries list for families and shared households
Koffan 是一款免费的自托管(self-hosted)购物清单应用,适合家庭和合租住户共享使用。升级 Koffan 时最大的"陷阱"藏在数据库里:升级到 2.16.0 后数据库会被自动迁移,旧版本无法再读写迁移后的历史记录,也不存在降级路径——想回滚只能靠升级前备份的数据库文件。本文面向新手,完整讲清 Koffan 备份怎么做、升级时数据库迁移改了什么、以及降级问题该如何规避。
一、先找到数据库文件:备份的对象是它
Koffan 的所有数据(购物清单、分组、模板、自动补全历史、账户与工作区)都保存在一个 SQLite 文件里。找到它,备份就有了着落:
| 部署方式 | 数据库文件位置 |
|---|---|
| Docker(推荐) | 容器内/data/shopping.db,映射到宿主机卷(默认卷名shopping-data或 Quick Start 中的koffan-data) |
| Docker Compose | 同样挂载到/data,见 docker-compose.yaml |
源码直接运行(go run .) | 当前目录下的shopping.db,可用环境变量DB_PATH修改 |
- 数据库路径由环境变量
DB_PATH决定,默认为./shopping.db,读取逻辑见 db/db.go;Docker 镜像在构建时已固定为/data/shopping.db(见 Dockerfile)。
一键备份步骤(Docker 卷)
# 1. 停掉 Koffan,避免写入到一半 docker stop <koffan容器名> # 2. 从数据卷复制出带时间戳的备份 docker run --rm -v shopping-data:/data alpine \ sh -c 'cp /data/shopping.db /data/shopping.db.bak-$(date +%Y%m%d)' # 3. 重新启动 docker start <koffan容器名>⚠️ 先停服务再复制文件,是最稳妥的做法。备份完成后确认文件不是 0 字节,有条件的话可以多备一份到 NAS 或异地。
二、逻辑备份:JSON / CSV 导出(跨版本的"兜底")
数据库文件备份是恢复的首选,但还有一层更"人类可读"的备份:Koffan 内置数据管理功能,可以导出整个工作区的 JSON(含模板和历史)或 CSV。
入口:打开 Koffan 首页右上角的 ⚙️ 设置 →Data选项卡(入口代码在 templates/home.html)。
- Export JSON:下载
koffan-export-日期.json,包含所有清单、模板和自动补全历史,文件名与格式定义见 handlers/export.go - Export CSV:便于用 Excel 查看或做二次分析
- Import:支持把之前导出的 JSON/CSV 导入回来
注意两点:
- 启用多用户(
MULTI_USER=true)后,导出/导入只作用于当前工作区,不是整个数据库; - JSON 导出是"逻辑备份",适合做保险丝,但账户、会话等信息不在其中——所以升级前请务必先做数据库文件备份。
三、2.16.0 的数据库迁移陷阱详解
3.1 升级时自动发生什么
2.16.0 首次启动会执行迁移,无论你是否开启多用户账户(迁移入口 db/db.go 中的runMigrations(),核心逻辑在 db/workspaces.go):
- 新建
users、workspaces、workspace_members三张表,并预置默认工作区 "Home"; - 给
lists、templates、sessions等表追加workspace_id列,让历史数据自动归入 "Home"; - 重建
item_history表:自动补全历史从"全局唯一"变为"每个工作区各自独立"(SQLite 无法原地修改唯一约束,只能建新表、搬数据、删旧表)。
迁移是幂等的,正常重启不会重复执行;日志中能看到Migration completed字样,看到它们说明迁移成功了。
3.2 为什么说"没有降级路径"
官方文档(README.md 的 Upgrading 一节)说得很直接:
旧版本无法在已迁移的数据库上保存商品历史,并且会忽略工作区概念——开着共享密码的实例里,任何人登录后将看到所有工作区的清单。
翻译成大白话:
- 把 2.16.0 跑过之后的数据库换回旧版本程序,轻则历史记录悄悄丢失,重则隐私问题(跨工作区数据全部可见);
- 所以回滚唯一正确姿势 = 停服务 + 用备份文件还原数据库,还原之后,升级期间产生的新数据会丢失。
这就是"迁移陷阱"的全部:不是数据被删了,而是新旧格式互不兼容,且只能单向升级。
3.3 安全的升级清单 ✅
- 在设置 → Data 中先导出 JSON(逻辑备份兜底);
- 停止 Koffan;
- 复制数据库文件做时间戳备份(见上一节的命令);
- 拉取新镜像 / 更新源码并启动,例如 Docker Quick Start 使用
ghcr.io/pansalut/koffan:latest; - 打开应用确认真清单、模板正常,日志无
Migration failed; - 观察一两周稳定后再删除旧备份。
四、从 2.9.x 升级?记得端口变了
另一个常见的升级"坑"与数据库无关:2.10.0 起容器默认端口从80改为8080(镜像改为非 root 用户运行,80 属于特权端口)。如果你从 2.9.x 直接升级,需要同步修改端口映射和反向代理:
| 原来 | 改为 |
|---|---|
docker run -p 80:80 | docker run -p 80:8080 |
docker run -p 3000:80 | docker run -p 3000:8080 |
反向代理(nginx/Caddy/Traefik)upstream 指向80 | 指向8080 |
如果你之前是靠覆盖PORT环境变量绕过特权端口问题,现在可以直接去掉该覆盖。读取镜像EXPOSE的自动部署平台(如 Coolify)会在重新部署时自动使用新端口。
五、常见问题速查
| 场景 | 建议 |
|---|---|
| 只升小版本,未跨 2.16.0 | 正常升级即可,迁移是幂等的,可不动数据 |
| 跨 2.16.0 升级 | 必须:先备份数据库文件 + 导出 JSON,再升级 |
| 升级后想回旧版本 | 停止服务 → 用备份文件覆盖数据库 → 启动。升级期间的新数据会丢 |
开启MULTI_USER之前 | 同样先备份数据库(README"Turning accounts on" 第 1 步即要求备份) |
| 忘记密码想清账户 | 备份后按 README "Forgotten administrator password" 一节操作 |
六、总结与相关文件
- 升级前永远先备份:一个 SQLite 文件 + 一份 JSON 导出,双保险;
- 2.16.0 的迁移单向不可逆,降级 = 还原备份文件,没有"自动回滚"这回事;
- 从 2.9.x 升上来时,别忘端口
80 → 8080。
| 文件 | 说明 |
|---|---|
| README.md | 官方升级注意事项(Upgrading / Docker 一节) |
| db/db.go | 数据库初始化与迁移调度runMigrations() |
| db/workspaces.go | 2.16.0 工作区与历史表重建迁移 |
| handlers/export.go | JSON/CSV 导出实现 |
| docker-compose.yaml / docker-compose.local.yaml | 数据卷/data与DB_PATH配置 |
| VERSION | 当前版本号 |
按照这份清单操作,升级 Koffan 就能做到"随时敢升、随时能退"。
【免费下载链接】Koffan
Free selfhosted groceries list for families and shared households
相关推荐
Roundcube Webmail 升级指南:从备份到数据库迁移的完整流程
Roundcube Webmail 升级指南:从备份到数据库迁移的完整流程 前言 Roundcube Webmail 作为一款广泛使用的开源网页邮件客户端,其版
后端前端企业应用Prisma 服务升级指南:发布说明、数据备份与分版本迁移全流程
Prisma 服务升级指南:发布说明、数据备份与分版本迁移全流程 导读 升级 Prisma Server 不是简单的镜像替换,而是一个涉及配置迁移、数据安全与回
后端数据库GraphQLPot 划词翻译保姆级教程:从安装到截图翻译、本地接口调用
Pot 划词翻译保姆级教程:从安装到截图翻译、本地接口调用 在网页里选中一段外文,按一下快捷键,译文立刻浮现在光标旁边。这就是 Pot 划词翻译的日常打开方式。
桌面应用OCRAI 应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考