Imagic / 妙绘
安装部署

升级与备份

镜像升级、数据卷备份、回滚、迁移

升级

官方在 Dockerhub 持续发布新镜像 (woodchen/imagic:latest + 语义化版本如 1.2.3), 升级只需拉镜像 + 滚动替换:

docker compose pull        # 拉最新镜像
docker compose up -d       # 滚动替换 imagic 容器, redis 与 db 不重启

想固定版本而不跟 latest, 在 docker-compose.yml 把 image: woodchen/imagic:latest 改成 具体 tag (如 woodchen/imagic:1.2.3), 然后 docker compose pull && docker compose up -d。 历次版本变化见 更新日志。

升级期间:

  • 已登录用户的 cookie 仍有效 (session 密钥落 Redis)
  • 正在跑的异步生图任务会被中断 — 容器停止时 task 还在内存里, 下次启动后 cron 会把卡死的 streaming 记录回收并退点 (5 min 兜底), 用户看到状态变 refunded
  • 反向代理在容器重启的几秒内会拿到 502, 客户端会自动重连 SSE

如果要做"零中断"升级, 需要在反代层挂多个 imagic 实例并接入同一份外部 Redis + PG, 压测验证后再上线。Imagic 当前是单实例为主的设计, 多实例支持是顺带具备 (Redis 已经 解决了跨进程 cancel 与 session), 但官方未提供 LB 配置脚手架。

备份

唯一需要备份的是 ./data 目录 (或你挂载的等价路径)。它包含:

子路径内容
imagic.dbSQLite 数据库 (用户 / 渠道 / 订单等) — 仅 DB_DRIVER=sqlite 时存在
<yyyy>/<mm>/<dd>/...本地存储的图片 — 仅 storage.driver=local 时存在
redis/内置 redis 容器的 AOF — 仅使用内置 redis 时存在
postgres/内置 PG 数据 — 仅启用 --profile postgres 时存在

外接 PG / 外接 Redis / S3 存储后, 各自的备份策略由对应服务负责, 这边的 ./data 就只剩配置与少量本地文件。

SQLite 备份

SQLite 在线备份不能直接 cp, 否则可能拷到不一致的中间状态。两种推荐方式:

# 方式 A: 用 sqlite3 命令行的 .backup
docker compose exec imagic sh -c \
  'apk add --no-cache sqlite >/dev/null 2>&1 || true; \
   sqlite3 /app/data/imagic.db ".backup /app/data/imagic.backup.db"'
docker cp imagic:/app/data/imagic.backup.db ./backups/

# 方式 B: 停服后冷备份 (短暂中断, 但更简单)
docker compose stop imagic
cp -a ./data/imagic.db ./backups/imagic-$(date +%Y%m%d).db
docker compose start imagic

定时备份建议用 cron + 方式 A, 避免业务中断。

图片备份 (local 驱动)

定时同步整个 ./data/<yyyy>/... 到对象存储或异地服务器:

rsync -av --delete ./data/ user@backup-host:/var/backup/imagic/

或直接挂网络文件系统 (NFS / S3FS / Rclone mount) 让写入实时镜像出去。 生产场景强烈建议用 S3 驱动而非 local + 同步方案, 后者跨主机一致性弱、扩容困难。

PostgreSQL 备份

# 内置 db 容器
docker compose exec db pg_dump -U imagic imagic | gzip > ./backups/pg-$(date +%Y%m%d).sql.gz

# 外接 PG
PGPASSWORD=xxx pg_dump -h pg-host -U imagic imagic | gzip > ./backups/pg-$(date +%Y%m%d).sql.gz

Redis (session 密钥)

仅 imagic:session:hmac_key 是关键 key, 丢失影响是用户全部需要重新登录。 内置 Redis 已开 AOF (./data/redis/), 跟着 ./data 一起备份即可。 外接 Redis 时按厂商提供的快照 / AOF 方案处理。

回滚

回滚到上一个镜像版本:

# 假设你有镜像 tag 历史
docker compose down
docker tag imagic:previous imagic:latest
docker compose up -d

或回滚 git 然后重新 build:

git checkout <previous-commit>
docker compose build
docker compose up -d

数据库 schema 基本只前进不后退, 因为 GORM AutoMigrate 只增字段不删字段。 跨大版本回滚 (期间删过字段或改过类型) 可能需要手工 DDL。建议升级前先备份 + 在测试环境 验证。

数据迁移 (机房 / 厂商之间)

整体搬迁到新机器:

# 旧机
docker compose stop imagic
tar czf imagic-data-$(date +%Y%m%d).tar.gz ./data ./docker-compose.yml
scp imagic-data-*.tar.gz new-host:/opt/

# 新机
ssh new-host
cd /opt && tar xzf imagic-data-*.tar.gz
cd imagic && docker compose up -d --build

核心约束:

  • 域名变更时, 注意 LICENSE_DOMAIN 与 license 签发记录是否需要重签
  • 反代证书要在新机器上重新申请或同步过去
  • alipay 异步通知 URL 要在支付宝商户后台同步改

监控建议

最低限度的监控点:

  • /api/v1/health 200
  • 容器状态 (docker compose ps) 全部 healthy
  • 磁盘占用 (data 目录 + redis AOF)
  • 渠道熔断状态: /admin/channels 一栏 cooldown_until, 频繁熔断说明上游有问题

复杂的监控 (调用量、点数消耗、收入) 直接用 admin /admin/stats/overview 与 /admin/stats/series, 仪表盘里看就够了。

On this page