备份与维护

PicFast 在管理后台内置了维护仪表盘,可查看磁盘健康度、数据库统计和 pHash 覆盖率,并提供一键清理工具。对于深层操作,则提供 picfast maintenance 命令行,用于一致性巡检、备份导出、恢复以及缩略图修复。

管理后台仪表盘

在管理后台导航至维护页面,监控系统健康状态并执行常规清理:

  • 磁盘健康: 实时查看本地存储后端的容量、使用量和 inode 统计。
  • 数据库统计: 概览记录数、表大小及 pHash 计算覆盖率。
  • 清理工具: 识别并删除存储后端中的未关联对象(即没有数据库记录的孤儿文件)。
  • 风险审计: 检查可能存在安全或运维风险的系统配置。

CLI: 执行前注意

  • 使用与线上实例一致的配置(config.yaml / 环境变量),以便 CLI 能连接 PostgreSQL 与各存储后端。
  • 下文 Compose 示例中的 <service> 须替换为你在 docker-compose.yml 里为 PicFast 定义的实际服务名(示例仓库常用 app,你的环境可能不同)。
  • 体量较大时建议在维护窗口执行:doctor 与完整备份会大量读取对象。

命令形式

docker compose exec <service> picfast maintenance <子命令> [参数]

使用 picfast maintenance --help 与各子命令的 --help 查看参数(如 --json--all--pg-dump-container 等)。

子命令

子命令作用
doctor只读巡检:数据库记录、对象存储与缩略图是否一致。
backup导出 PostgreSQL 自定义格式 dump,并可按需把对象一并打入归档。
inspect校验备份包内的 manifest.json 与校验和。
restore默认仅预检;加 --apply 才写入。目标库非空时需显式 --force
repair-thumbnails根据源对象重建缺失缩略图(默认演练,--apply 才写入)。
recalc-phash为所有符合条件的图片重新计算缺失的感知哈希 (pHash)。

推荐顺序

  1. 巡检: picfast maintenance doctor --all --batch-size 500
  2. 备份: picfast maintenance backup --output /app/data/backups/picfast-backup.tar.gz(路径请按实际卷挂载调整)
  3. 校验归档: picfast maintenance inspect /app/data/backups/picfast-backup.tar.gz
  4. 恢复(在目标环境、预检通过后): picfast maintenance restore … --apply;仅在确认要覆盖非空库时使用 --force

PostgreSQL 客户端工具

若宿主机未安装 pg_dump / pg_restore,可将 CLI 指向已有 Postgres 容器(如 --pg-dump-container--pg-restore-container),详见 backuprestore--help

自动备份

利用宿主机 cron 定时执行备份——无需修改任何代码。两种策略搭配使用:

类型频率范围保留
db-only每小时仅 PostgreSQL 元数据最近 48 份
full每天数据库 + 图片文件最近 7 份

第一步:数据库备份脚本

创建 /opt/picfast/backup-db.sh

#!/bin/bash
set -euo pipefail

CONTAINER="${1:-picfast-db}"
BACKUP_DIR="${2:-/opt/picfast/data/backups}"
DB_USER="${3:-picfast}"
DB_NAME="${4:-picfast}"
RETENTION="${5:-48}"

TIMESTAMP=$(date +%Y%m%d-%H%M)
OUTPUT="$BACKUP_DIR/db-$TIMESTAMP.dump.gz"
mkdir -p "$BACKUP_DIR"

docker exec "$CONTAINER" pg_dump --format=custom -U "$DB_USER" -d "$DB_NAME" \
    | gzip > "$OUTPUT"

echo "备份完成: $OUTPUT ($(du -h "$OUTPUT" | cut -f1))"

# 清理过期备份
ls -1t "$BACKUP_DIR"/db-*.dump.gz 2>/dev/null \
    | tail -n +$((RETENTION + 1)) \
    | xargs -r rm -v
chmod +x /opt/picfast/backup-db.sh

第二步:全量备份脚本

创建 /opt/picfast/backup-full.sh

#!/bin/bash
set -euo pipefail

PROJECT_DIR="${1:-/opt/picfast}"
COMPOSE_FILE="${2:-$PROJECT_DIR/docker/docker-compose.yml}"
RETENTION="${3:-7}"

TIMESTAMP=$(date +%Y%m%d)
OUTPUT="$PROJECT_DIR/data/backups/full-$TIMESTAMP.tar.gz"

cd "$PROJECT_DIR"
docker compose -f "$COMPOSE_FILE" run --rm app \
    picfast maintenance backup \
    --output "/app/data/backups/full-$TIMESTAMP.tar.gz"

echo "全量备份完成: $OUTPUT"
ls -1t "$PROJECT_DIR"/data/backups/full-*.tar.gz \
    | tail -n +$((RETENTION + 1)) \
    | xargs -r rm -v
chmod +x /opt/picfast/backup-full.sh

第三步:配置定时任务

crontab -e
# PicFast 自动备份
0 * * * * /opt/picfast/backup-db.sh picfast-db /opt/picfast/data/backups picfast picfast 48
0 3 * * * /opt/picfast/backup-full.sh /opt/picfast /opt/picfast/docker/docker-compose.yml 7

第四步(可选):异地同步

rclone 将备份和静态文件推送到远程存储:

30 3 * * * rclone sync /opt/picfast/data/backups   remote:bucket/picfast-backups
30 3 * * * rclone sync /opt/picfast/data/uploads   remote:bucket/picfast-uploads
30 3 * * * rclone sync /opt/picfast/data/thumbnails remote:bucket/picfast-thumbnails

从备份恢复

# 仅数据库
gunzip -c /opt/picfast/data/backups/db-20260728-1400.dump.gz | \
    docker exec -i picfast-db pg_restore --clean --if-exists --no-owner -U picfast -d picfast

# 完整恢复
docker compose -f docker/docker-compose.yml run --rm app \
    picfast maintenance restore /app/data/backups/full-20260728.tar.gz --apply --force

归档格式与完整说明

Manifest 字段、objects.jsonl 与校验账本的职责、兼容性约定及更多实现细节见 PicFast 仓库文档: docs/maintenance.md