在法国用 Docker 自建 Umami,Postgres 备份别只 dump 数据库

我家里那台机器上跑着一个 Umami 统计,给两个小站用,日 PV 三千出头,Postgres 数据量不到 200MB。上个月迁移一次,按老习惯只 pg_dump 了库,结果恢复到新机器后 Umami 页面能打开、图表一片空——website_event 里最新的事件都还在,但 7 天前的聚合全丢了。后来才想起来,Umami 有独立的聚合任务,数据不是唯一来源。

现在我的做法是三层,都在同一个 compose 里:

services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    env_file: .env
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:16-alpine
    env_file: .env
    volumes:
      - ./pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
      interval: 10s
      retries: 5

备份脚本不放容器里,放宿主机 cron,每天 04:10:

#!/bin/sh
set -eu
STAMP=$(date +%F)
docker compose exec -T db pg_dump -U umami -Fc umami > /backup/umami-$STAMP.dump
find /backup -name 'umami-*.dump' -mtime +14 -delete

-Fc 是为了恢复时能 pg_restore 挑表,别学我第一次用纯 SQL dump,恢复到一半报错只能重来。恢复顺序也有讲究:先 pg_restore 到空库,再启动 Umami,让它自己跑一次聚合,别反过来,否则新容器启动时读到的还是空表。

为什么不全靠卷备份?./pgdata 直接复制在运行中很可能拿到不一致的页,尤其 cron 撞上写入。dump 是逻辑一致快照,代价是恢复慢、占空间小、能跨大版本。卷备份我只在停机迁移时用,平时不开。

会失效的地方:docker compose exec 在容器名冲突或者项目目录换了之后找不到 service,脚本里必须带 -f 指到 compose 文件;另外 -T 不能省,否则 cron 里没有 TTY 会挂住。还有一次我把 dump 存到同一块盘,盘满了 Postgres 直接拒绝写入,Umami 前端还在,但所有上报静默丢,日志里只有一行 could not extend file。现在 /backup 挂的是另一块小 SSD,满了至少不影响主库。

聚合丢了能不能补?我试过改 website_event 的时间戳骗 Umami 重算,没成功,最后是接受 7 天数据缺口。你们自建 Umami 的,是只 dump 库,还是连聚合状态一起想办法保住?

0
赞同度 100% · 0 条评论 · 7 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。