Gathio 1.6.7 日常运维与升级指南
Gathio 1.6.7(Docker Compose + MongoDB 7.0)的日常运维手册:巡检项与基线、mongodump/mongorestore 备份恢复实测、无 /healthz 下的监控信号设计、多实例扩展实测、1.6.7↔1.6.6 升降级与回滚实测、故障分诊入口,全部回显真实采集。
Gathio 1.6.7 日常运维与升级指南
目标:给出 Gathio 1.6.7 自托管实例的巡检项与基线、备份恢复、监控信号、扩展、升级回滚与故障分诊的完整运维流程。全部命令与回显实测于 Ubuntu 24.04.5 LTS + Docker Compose(
gathio-app/gathio-db,宿主 8153)环境;部署基线见 《Gathio 1.6.7 Docker Compose 部署指南》,逐条故障复现见 《Gathio 1.6.7 排错FAQ》。
一、环境信息
- 操作系统:Ubuntu 24.04.5 LTS;Docker 29.9.2(build a82e528)、Docker Compose v5.6.1
- 应用:
ghcr.io/lowercasename/gathio:1.6.7,容器名gathio-app,重启策略unless-stopped,宿主 8153→容器 3000 - 数据库:
mongo:7.0(服务端 v7.0.45),容器名gathio-db,命名卷gathio_mongodb_data_db - 持久化目录:
/opt/gathio/{config,static,images}(bind mount) - 数据集合:
events/eventgroups/logs;容器时区 UTC - 本文实测时点数据规模:3 活动、1 群组、22 条审计日志(个人/小团队实例量级)
二、日常巡检
巡检回答四个问题:进程活着吗、链路通吗、数据在涨吗、资源正常吗。以下命令构成每日巡检清单。
2.1 容器与重启计数
cd /opt/gathio && docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
gathio-app ghcr.io/lowercasename/gathio:1.6.7 "docker-entrypoint.s…" gathio 10 minutes ago Up 10 minutes 0.0.0.0:8153->3000/tcp, [::]:8153->3000/tcp
gathio-db mongo:7.0 "docker-entrypoint.s…" mongo 16 minutes ago Up 16 minutes 27017/tcp
docker inspect gathio-app --format 'RestartCount={{.RestartCount}} RestartPolicy={{.HostConfig.RestartPolicy.Name}}'
RestartCount=0 RestartPolicy=unless-stopped
解读:RestartCount 是崩溃循环的最硬指标——正常应为 0 且长期不增长;一旦持续上涨,直接查日志(2.2)。
2.2 日志健康检查
docker logs gathio-app --tail 6
> gathio@1.6.7 start
> node dist/start.js
You have not configured this Gathio instance to send emails! This means that event creators will not receive emails when their events are created, which means they may end up locked out of editing events. Consider setting up an email service.
Welcome to gathio! The app is now running on http://localhost:3000
Mongoose connection open!
解读:Mongoose connection open! 存在=数据库链路正常;邮件警告为 mail_service = "none" 的预期输出。异常关键字:Configuration file not found、Error parsing configuration、MongoParseError、buffering timed out(含义与处置见 FAQ Q1–Q5)。
2.3 HTTP 与数据库链路探测
curl -s -o /dev/null -w "GET / -> HTTP %{http_code} (%{time_total}s)\n" http://localhost:8153/
GET / -> HTTP 200 (0.031734s)
curl -s -o /dev/null -w "GET event -> HTTP %{http_code} (%{time_total}s)\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
GET event -> HTTP 200 (0.023877s)
解读:首页是静态渲染,200 不代表数据库可用;活动页必须纳入探测——DB 不可达时活动页呈「404 + 恰好约 10 秒」特征(Mongoose 缓冲超时,FAQ Q5 实测 10.007787s)。活动页响应时间 time_total > 5s 即可判定链路故障。
2.4 数据规模与审计
docker exec gathio-db mongosh --quiet gathio --eval 'printjson({events:db.events.countDocuments({}),groups:db.eventgroups.countDocuments({}),logs:db.logs.countDocuments({})})'
{
events: 3,
groups: 1,
logs: 22
}
docker exec gathio-db mongosh --quiet gathio --eval 'db.logs.find({},{_id:0,process:1,status:1}).sort({timestamp:-1}).limit(5).toArray()'
[
{ status: 'error', process: 'addEventComment' },
{ status: 'success', process: 'createEvent' },
{ status: 'success', process: 'createEvent' },
{ status: 'success', process: 'startup' },
{ status: 'success', process: 'startup' }
]
解读:logs 集合是 Gathio 唯一的审计面(startup/createEvent/editEvent/addEventComment/deleteOldEvents 等 process 值);上面首条 error addEventComment 正是排错 FAQ Q11「评论字段名错」测试留下的痕迹——应用层错误不进容器日志、只落这里。events 数长期不降需确认自毁任务在跑(查 deleteOldEvents 记录,见「常见问题」时区条目)。
2.5 资源基线
docker stats --no-stream --format '{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}' | grep gathio-
gathio-app 0.00% 100MiB / 15.57GiB
gathio-db 0.27% 74.76MiB / 15.57GiB
解读:空闲基线两容器合计约 175MB(负载态实测 app ~120MB、db ~131MB),无内存泄漏迹象;磁盘侧关注 images/(封面图)与 MongoDB 卷,个人实例常年 <100MB。
三、备份与恢复
Gathio 状态由两部分构成:MongoDB 三集合 + 宿主三个目录。两者必须同批备份,缺一即恢复不完整。
3.1 数据库备份(mongodump)
docker exec gathio-db mongodump --db gathio --archive=/tmp/gathio-backup.tar --gzip 2>&1
2026-11-01T16:15:15.073+0000 writing `gathio.logs` to "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:15.073+0000 writing `gathio.events` to "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:15.074+0000 writing `gathio.eventgroups` to "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:15.079+0000 done dumping `gathio.events` (3 documents)
2026-11-01T16:15:15.079+0000 done dumping `gathio.logs` (22 documents)
2026-11-01T16:15:15.085+0000 done dumping `gathio.eventgroups` (1 document)
docker cp gathio-db:/tmp/gathio-backup.tar /opt/gathio/backup/gathio-backup.tar
ls -l /opt/gathio/backup/gathio-backup.tar
-rw-r--r-- 1 root root 13126 Nov 2 00:15 gathio-backup.tar
💡 技术拓展:MongoDB 备份常见三种口径——
方式 一致性 特点 mongodump(逻辑备份) 单集合快照级 跨版本兼容最好,Gathio 小库首选(本文采用) 文件系统快照(LVM/卷组) 需冻结或副本 快,但依赖存储层 复制集滚动备份 高 为 HA 设计,个人实例过重 Gathio 数据量小(实测全库 gzip 后约 13KB),mongodump 秒级完成。
3.2 文件目录备份
cd /opt/gathio && tar czf backup/gathio-files-backup.tar.gz config static images
tar tzf backup/gathio-files-backup.tar.gz
config/
config/config.toml
static/
static/privacy-policy.md
static/instance-description.md
static/instance-description-en.md
images/
ls -l backup/gathio-files-backup.tar.gz
-rw-r--r-- 1 root root 707 Nov 2 00:15 gathio-files-backup.tar.gz
config.toml 若含 ${GATHIO_SMTP_PASSWORD} 类变量引用则无明文密钥,备份可安全异地存放;若曾明文写入 SMTP 密码,备份文件按密钥等级管控。
3.3 恢复演练(mongorestore)
实测「删库→恢复」完整闭环:
docker exec gathio-db mongosh --quiet gathio --eval 'printjson(db.events.deleteMany({}))'
{
acknowledged: true,
deletedCount: 3
}
curl -s -o /dev/null -w "GET event -> HTTP %{http_code}\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
GET event -> HTTP 404
docker cp /opt/gathio/backup/gathio-backup.tar gathio-db:/tmp/gathio-backup.tar
docker exec gathio-db mongorestore --db gathio --drop --archive=/tmp/gathio-backup.tar --gzip 2>&1
2026-11-01T16:15:21.141+0000 The --db and --collection flags are deprecated for this use-case; please use --nsInclude instead, i.e. with --nsInclude=${DATABASE}.${COLLECTION}
2026-11-01T16:15:21.149+0000 preparing collections to restore from
2026-11-01T16:15:21.156+0000 reading metadata for `gathio.logs` from "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:21.156+0000 reading metadata for `gathio.events` from "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:21.157+0000 reading metadata for `gathio.eventgroups` from "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:21.159+0000 dropping collection `gathio.events` before restoring
2026-11-01T16:15:21.166+0000 restoring `gathio.events` from "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:21.178+0000 finished restoring `gathio.events` (3 documents, 0 failures)
2026-11-01T16:15:21.178+0000 dropping collection `gathio.logs` before restoring
2026-11-01T16:15:21.183+0000 restoring `gathio.logs` from "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:21.201+0000 finished restoring `gathio.logs` (22 documents, 0 failures)
2026-11-01T16:15:21.201+0000 dropping collection `gathio.eventgroups` before restoring
2026-11-01T16:15:21.208+0000 restoring `gathio.eventgroups` from "archive `/tmp/gathio-backup.tar`"
2026-11-01T16:15:21.219+0000 finished restoring `gathio.eventgroups` (1 document, 0 failures)
2026-11-01T16:15:21.219+0000 no indexes to restore for collection `gathio.logs`
2026-11-01T16:15:21.219+0000 restoring indexes for collection `gathio.events` from metadata
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"attendees.removalPassword_1", "sparse":true, "unique":true, "v":2}, Key:bson.D{bson.E{Key:"attendees.removalPassword", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"attendees.id_1", "sparse":true, "unique":true, "v":2}, Key:bson.D{bson.E{Key:"attendees.id", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"comments.id_1", "sparse":true, "unique":true, "v":2}, Key:bson.D{bson.E{Key:"comments.id", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"comments.replies.id_1", "sparse":true, "unique":true, "v":2}, Key:bson.D{bson.E{Key:"comments.replies.id", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"activityPubMessages.id_1", "sparse":true, "unique":true, "v":2}, Key:bson.D{bson.E{Key:"activityPubMessages.id", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"id_1", "unique":true, "v":2}, Key:bson.D{bson.E{Key:"id", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.219+0000 restoring indexes for collection `gathio.eventgroups` from metadata
2026-11-01T16:15:21.219+0000 index: &idx.IndexDocument{Options:bson.M{"background":true, "name":"id_1", "unique":true, "v":2}, Key:bson.D{bson.E{Key:"id", Value:1}}, PartialFilterExpression:(*bson.D)(nil)}
2026-11-01T16:15:21.264+0000 26 document(s) restored successfully. 0 document(s) failed to restore.
curl -s -o /dev/null -w "GET event -> HTTP %{http_code}\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
GET event -> HTTP 200
解读:--drop 整库覆盖恢复;回显首行是 mongorestore 的弃用告警(提示改用 --nsInclude 命名空间写法,旧的 --db 写法实测仍可用)。恢复时 events 集合的 6 个 unique 索引(attendees.removalPassword_1、attendees.id_1、comments.id_1、comments.replies.id_1、activityPubMessages.id_1、id_1)与 eventgroups 的 id_1 自动重建,无需手工建索引。
3.4 备份节奏建议
- 个人/小团队实例:每日一次 mongodump + 文件 tar,保留 7~14 份滚动(与
delete_after_days=7的自毁窗口对齐,最坏可回滚一周); - 宿主 crontab 示例(凌晨低峰,产物落
/opt/gathio/backup):
0 3 * * * docker exec gathio-db mongodump --db gathio --archive=/tmp/gathio-backup.tar --gzip && docker cp gathio-db:/tmp/gathio-backup.tar /opt/gathio/backup/gathio-$(date +\%F).tar && cd /opt/gathio && tar czf backup/files-$(date +\%F).tar.gz config static images && find /opt/gathio/backup -mtime +14 -delete
四、监控告警
4.1 探测端点选择
Gathio 没有健康检查路由(实测 GET /healthz → 404)。可用的监控信号按可靠性排序:
| 信号 | 采集方式 | 异常判据 |
|---|---|---|
| 活动页响应时间 | curl -w '%{time_total}' http://localhost:8153/<固定eventID> | >5s(DB 不可达特征为恰好 10s) |
| 容器重启计数 | docker inspect --format '{{.RestartCount}}' gathio-app | 两次采集间增长 |
| HTTP 存活 | GET / 状态码 | ≠200 |
| 审计错误 | db.logs.find({status:"error"}) | 出现即查(字段错/邮件失败等) |
| 磁盘 | df + du /opt/gathio/images | 卷/盘使用率阈值 |
固定 eventID 探测法:自建一个长期存在的「心跳活动」(结束时间设远、delete_after_days 内不会被删,或把实例 delete_after_days 设 0 的专用实例),比只探首页更能覆盖数据库链路。
4.2 审计面查询
docker exec gathio-db mongosh --quiet gathio --eval 'db.logs.find({status:"error"},{_id:0,process:1,message:1}).sort({timestamp:-1}).limit(3).toArray()'
[
{
process: 'addEventComment',
message: 'Attempt to add comment to event _0nu7QEITrI8SXhvQhEzc failed with error: ValidationError: comments.1.author: Path `author` is required., comments.1.content: Path `content` is required.'
}
]
logs 集合承载全部操作审计与错误(如评论 ValidationError、邮件失败),是应用层无 metrics 端点时唯一的「业务监控」数据源。上面这条即排错 FAQ Q11 场景的真实入库形态:HTTP 层返回 200、错误只在 message 里可见。
五、扩容与缩容
Gathio 官方按单实例设计,无 HA 文档;但应用进程本身接近无状态(配置只读、会话不落地、编辑凭证在 URL/DB),实测验证了多应用实例共享同一 MongoDB 可行——在部署时另起第二个应用容器指向同一数据库与目录:
docker run -d --name gathio-runtest --network gathio_default -p 8157:3000 \
-e NODE_ENV=production \
-v /opt/gathio/config:/app/config \
-v /opt/gathio/static:/app/static \
-v /opt/gathio/images-run:/app/public/events \
ghcr.io/lowercasename/gathio:1.6.7
9e98702bd73154bed5ec8f3c80c4f09fc5b845f7589ec8b044ba0fa2fcd24ee4
curl -s -o /dev/null -w "GET :8157 -> HTTP %{http_code}\n" http://localhost:8157/
GET :8157 -> HTTP 200
docker logs gathio-runtest | tail -1
Mongoose connection open!
扩缩容结论(基于该实测与架构):
- 横向扩:多应用实例 + 反代负载均衡可行,前提是共享同一
config/static/images挂载(封面图写入必须同路径);实例间无本地状态需要同步; - 瓶颈在 MongoDB:单
mongo:7.0容器是单点,Gathio 无多写设计;数据量级(个人活动页)远低于 MongoDB 单实例能力,真到高可用需求时先做副本集再谈应用多实例; - 缩容:直接减应用容器即可,无状态迁移需求;数据库缩容= mongodump 导出 + 新实例 mongorestore(见「备份与恢复」);
- 资源规格:空闲 ~175MB、负载 <300MB(实测基线见 2.5),1 核 2GB 机型足够,无需调优参数(Node 堆默认即可,无 Java 进程)。
六、升级与回滚
6.1 版本节奏与渠道
上游发布活跃(releases.atom 实测:v1.6.7 2026-09-07、v1.6.6 2026-09-02、v1.6.5 2026-08-15、v1.6.4 2026-08-13、v1.6.3 2026-07-07),镜像 tag 与版本号一一对应,无 latest 依赖。升级前动作:按「备份与恢复」做一次 mongodump + 文件 tar。
6.2 升级操作(以 1.6.6 → 1.6.7 为例)
docker pull ghcr.io/lowercasename/gathio:1.6.7
1.6.7: Pulling from lowercasename/gathio
Digest: sha256:f061733f5688363d1316d76d2b6700cafc4d1936bd67e4d34809a01ef2ee18df
Status: Image is up to date for ghcr.io/lowercasename/gathio:1.6.7
ghcr.io/lowercasename/gathio:1.6.7
sed -i 's|gathio:1.6.6|gathio:1.6.7|' /opt/gathio/docker-compose.yml
cd /opt/gathio && docker compose up -d
Container gathio-db Running
Container gathio-app Recreate
Container gathio-app Recreated
Container gathio-app Starting
Container gathio-app Started
docker exec gathio-app node -p "require('./package.json').version"
1.6.7
curl -s -o /dev/null -w "GET event -> HTTP %{http_code}\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
GET event -> HTTP 200
解读:compose 仅重建应用容器,gathio-db 与数据卷不动;node -p 读容器内 package.json 是版本生效的最直接验证。本例 docker pull 显示 Image is up to date 是因为本机已有 1.6.7 缓存;全新宿主上会显示逐层下载进度,Digest 值相同。
6.3 回滚操作(1.6.7 → 1.6.6 实测)
sed -i 's|gathio:1.6.7|gathio:1.6.6|' /opt/gathio/docker-compose.yml
docker compose up -d
Container gathio-db Running
Container gathio-app Recreate
Container gathio-app Recreated
Container gathio-app Starting
Container gathio-app Started
docker exec gathio-app node -p "require('./package.json').version"
1.6.6
docker logs gathio-app 2>&1 | grep -m1 "gathio@"
> gathio@1.6.6 start
curl -s -o /dev/null -w "GET / -> HTTP %{http_code}\n" http://localhost:8153/
GET / -> HTTP 200
curl -s -o /dev/null -w "GET event -> HTTP %{http_code}\n" http://localhost:8153/_0nu7QEITrI8SXhvQhEzc
GET event -> HTTP 200
6.4 兼容性说明
实测 1.6.7 写入的数据(活动/群组/RSVP/评论)降级到 1.6.6 后页面全部 200 可读,再升回 1.6.7 依旧正常——MongoDB 无 schema 强约束、Gathio 无迁移脚本机制,小版本间数据双向兼容。注意两点:升级前备份仍不可省(结构性变更风险);若新版本引入配置项,旧 config.toml 缺键时按内置默认运行——升级前可从镜像内取出新版 config.example.toml 与当前配置对照一遍新增键即可(示例文件全文见部署指南)。
七、故障排查手册
分诊顺序:先看容器状态,再看日志关键字,最后按症状定位。
| 症状 | 第一步命令 | 指向 |
|---|---|---|
docker ps 显示 Restarting | docker logs gathio-app --tail 20 | 配置缺失 Q1 / TOML 错 Q2 / MongoParseError Q3 |
| up 失败报 networking 错误 | ss -lntp(查看 8153 是否被其他进程占用) | 端口占用 Q4 |
| 页面 404 且响应约 10s | docker exec gathio-app nc -zv mongo 27017 | DB 不可达 Q5、进程崩溃 Q6 |
| 数据丢失 | docker exec gathio-db mongosh gathio --eval 'db.events.countDocuments({})' | 恢复 Q7 / 自毁 Q8 |
| 某功能「没报错但没效果」 | db.logs.find({status:"error"}) | 评论字段 Q11、邮件 Q10、ICS Q12 |
| 403 Forbidden | 核对 URL ?e= 令牌 | Q13/Q14 |
| 联邦/Mastodon 不工作 | curl http://localhost:8153/.well-known/nodeinfo | domain/HTTPS Q16 |
全部 Q 编号对应的报错回显与处置在 《Gathio 1.6.7 排错FAQ》 逐条实测。
八、常见问题
8.1 自毁任务的时间怎么算
调度 cron 59 23 * * * 按容器本地时区执行,官方镜像未设 TZ、实际为 UTC:即北京时间次日 07:59 删除「结束满 delete_after_days 天」的活动。容器内确认时区:
docker exec gathio-app date
Sun Nov 1 15:40:15 UTC 2026
不要按「本地 23:59」理解删除时点;审计看 db.logs.find({process:"deleteOldEvents"})。
8.2 千万别用 down -v
docker compose down -v 会删除命名卷 gathio_mongodb_data_db(全部活动数据即丢),日常停止只用 docker compose down。误删后唯一出路是 mongorestore(Q7)。
8.3 主办编辑令牌要不要入库备份
Gathio 无账号体系,?e=<editToken> 链接即管理权。运维侧建议:活动创建回执(POST /event 的 JSON 响应)落库存档;忘存时可用 db.events.find({},{id:1,editToken:1}) 直查找回(FAQ Q14 实测)。
8.4 升级后行为异常如何快速归因
顺序:RestartCount 是否增长 → docker logs 关键字 → 用备份恢复法回滚(mongorestore 上一版备份 + compose 改回旧 tag + up -d)。小版本回滚本身实测无损(6.3)。
九、参考链接
- 部署基线与配置参数:《Gathio 1.6.7 Docker Compose 部署指南》
- 故障逐条实测:《Gathio 1.6.7 排错FAQ》
- 组件定位与功能:《Gathio 1.6.7 介绍与选型指南》
- 官方文档:https://docs.gath.io/
- 发布记录:https://github.com/lowercasename/gathio/releases
- mongodump/mongorestore:https://www.mongodb.com/docs/database-tools/mongodump/