Add daily production database backups

This commit is contained in:
openclaw 2026-07-22 23:11:13 +08:00
parent 4bff90ec84
commit 1f6e82bc95
6 changed files with 91 additions and 3 deletions

View File

@ -3,6 +3,7 @@
.env.* .env.*
node_modules node_modules
dist dist
backups
apps/*/dist apps/*/dist
services/*/dist services/*/dist
packages/*/dist packages/*/dist

2
.gitignore vendored
View File

@ -1,9 +1,9 @@
legacy-cent-app/ legacy-cent-app/
node_modules/ node_modules/
dist/ dist/
backups/
.env .env
.env.* .env.*
!.env.example !.env.example
*.log *.log
.DS_Store .DS_Store

View File

@ -78,7 +78,30 @@ docker compose --env-file .env -f compose.pro.yaml down
```bash ```bash
docker compose --env-file .env -f compose.pro.yaml exec api \ docker compose --env-file .env -f compose.pro.yaml exec api \
npm run user:add --workspace @cents/api -- '用户名' '至少8位的密码' npm run user:add -- '用户名' '至少8位的密码'
``` ```
用户与唯一的“个人账本”会在同一个数据库事务内创建。 用户与唯一的“个人账本”会在同一个数据库事务内创建。
## 生产数据库备份
`backup` 容器每天北京时间 `03:00` 将 PostgreSQL 备份到生产 clone 目录下的 `./backups`。备份采用 PostgreSQL custom format并在写入后校验超过 30 天的备份会自动删除。
查看调度和备份日志:
```bash
docker compose --env-file .env -f compose.pro.yaml logs -f backup
```
立即手动备份一次:
```bash
docker compose --env-file .env -f compose.pro.yaml exec backup \
/usr/local/bin/cents-backup run
```
备份文件位于宿主机:
```text
./backups/cents-YYYYMMDD-HHMMSS.dump
```

View File

@ -32,6 +32,30 @@ services:
networks: networks:
- app - app
backup:
image: postgres:17-alpine
restart: unless-stopped
environment:
TZ: Asia/Shanghai
PGHOST: db
PGDATABASE: ${POSTGRES_DB:-cents}
PGUSER: ${POSTGRES_USER:-cents}
PGPASSWORD: ${POSTGRES_PASSWORD}
entrypoint: ["/usr/local/bin/cents-backup"]
volumes:
- ./backups:/backups
- ./deploy/postgres-backup.sh:/usr/local/bin/cents-backup:ro
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "pgrep crond >/dev/null"]
interval: 30s
timeout: 3s
retries: 3
networks:
- app
web: web:
build: build:
context: . context: .

40
deploy/postgres-backup.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
set -eu
backup_dir=${BACKUP_DIR:-/backups}
run_backup() {
umask 077
mkdir -p "$backup_dir"
timestamp=$(date +%Y%m%d-%H%M%S)
target="$backup_dir/cents-$timestamp.dump"
temporary="$target.tmp"
trap 'rm -f "$temporary"' EXIT INT TERM
pg_dump --format=custom --file="$temporary"
pg_restore --list "$temporary" >/dev/null
mv "$temporary" "$target"
trap - EXIT INT TERM
find "$backup_dir" -maxdepth 1 -type f -name 'cents-*.dump' -mtime +29 -delete
printf 'Backup created: %s\n' "$target"
}
case "${1:-cron}" in
run)
run_backup
;;
cron)
printf '%s\n' \
'0 3 * * * /usr/local/bin/cents-backup run >> /proc/1/fd/1 2>> /proc/1/fd/2' \
> /etc/crontabs/root
printf 'Backup scheduler started: daily at 03:00 %s, retaining 30 days\n' "${TZ:-local time}"
exec crond -f -l 2
;;
*)
printf 'Unknown command: %s\n' "$1" >&2
exit 2
;;
esac

View File

@ -20,7 +20,7 @@ npm run user:add -- '用户名' '至少8位的密码'
```bash ```bash
docker compose -f compose.pro.yaml exec api \ docker compose -f compose.pro.yaml exec api \
npm run user:add --workspace @cents/api -- '用户名' '至少8位的密码' npm run user:add -- '用户名' '至少8位的密码'
``` ```
用户与个人账本在同一数据库事务内创建;用户名已存在或任一步失败时都不会留下半成品数据。 用户与个人账本在同一数据库事务内创建;用户名已存在或任一步失败时都不会留下半成品数据。