用 Healthchecks 检查定时备份是否按时执行
首页正常,凌晨备份也可能没有执行。Healthchecks 接收任务心跳,帮助发现失败和漏跑的定时任务。
文章目录
网站首页能打开,不代表凌晨的备份任务执行过。Cron 路径写错、脚本卡住或磁盘写满,都可能让备份连续几天没有更新,却没有人在第一时间发现。
Healthchecks 接收任务主动发来的心跳,超过设定时间没有收到就通知你。最好部署在另一台 VPS 上;如果它和被监控任务一起停机,同机监控很难及时报告这个故障。
把监控服务放在另一台机器
检查定时备份的服务最好不要和被检查的任务一起故障。若要为 Healthchecks 准备独立 VPS,可以从 雨云云服务器 查看服务器,部署位置也要与现有备份环境一起考虑。 优惠码 KuZhuJi。如有消费返利,以购买页所选规格显示的金额为准。
以下命令在 Linux VPS 上执行,需要有 Docker 操作权限。先运行 docker version 和 docker compose version,确认引擎与 Compose v2 都能工作。没有安装 Docker 时,按 Docker 官方安装说明选择对应发行版;不要把其他发行版的仓库配置直接复制过来。
示例工作目录为 /opt/healthchecks,所有相对路径都以这个目录为基准。VPS_IP、SSH 用户和示例域名需要换成自己的值。端口 8000 若已被占用,只改映射左侧的宿主机端口,并同步修改访问地址。
sudo install -d -m 0750 -o "$(id -u)" -g "$(id -g)" /opt/healthchecks
cd /opt/healthchecks
umask 077
创建 database 目录,在 .env 保存以下设置。数据库密码与 SECRET_KEY 分别用 openssl rand -hex 32 生成:
DB=postgres
DB_HOST=db
DB_PORT=5432
DB_NAME=hc
DB_USER=hc
DB_PASSWORD=REPLACE_WITH_RANDOM_DB_PASSWORD
SECRET_KEY=REPLACE_WITH_RANDOM_SESSION_KEY
SITE_ROOT=https://hc.example.com
ALLOWED_HOSTS=hc.example.com
REGISTRATION_OPEN=False
DEFAULT_FROM_EMAIL=alerts@example.com
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=REPLACE_WITH_SMTP_USERNAME
EMAIL_HOST_PASSWORD=REPLACE_WITH_SMTP_PASSWORD
mkdir -p database
chmod 600 .env
启动后创建管理员,密码通过交互输入:
docker compose run --rm web /opt/healthchecks/manage.py createsuperuser
镜像启动时处理迁移和后台通知任务,不必再另起一份相同告警进程。反向代理应覆盖客户端提交的转发协议与地址头;不要允许公网请求伪造这些头绕过登录限速。
将下面内容保存为 compose.yaml:
services:
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_DB: hc
POSTGRES_USER: hc
POSTGRES_PASSWORD: ${DB_PASSWORD:?set db password}
volumes:
- ./database:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U hc -d hc"]
interval: 10s
timeout: 5s
retries: 10
web:
image: healthchecks/healthchecks:latest
restart: unless-stopped
env_file: .env
ports:
- "127.0.0.1:8000:8000"
depends_on:
db:
condition: service_healthy
在工作目录启动并检查日志:
docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=80
启动后按下面的步骤试用。遇到目录不可写的报错,先核对 UID 和挂载路径,不要直接改成 chmod 777。
让域名通过 HTTPS 访问
把 hc.example.com 的 DNS 指向 VPS。下面是已经安装在宿主机上的 Caddy可添加的站点配置;已有网站时只添加这一段,不覆盖整个配置文件。若反向代理也在 Docker 中,容器内的 127.0.0.1 不是宿主机,需要改用共享网络中的服务名。
hc.example.com {
reverse_proxy 127.0.0.1:8000
}
确认服务器允许访问 80、443,检查 Caddy 配置并按现有服务方式重载,再访问 https://hc.example.com。应用端口仍绑定在宿主机回环地址,数据库端口不向公网发布。应用中的外部地址也要设置为这个 HTTPS 地址,否则邀请链接或登录回调可能指向错误位置。
给测试任务加开始、成功和失败信号
创建一个测试检查,先设置较短周期与宽限时间,复制它的专用 ping 地址。用测试脚本演示流程,PING_URL 应替换为真实地址,并妥善保管,别贴进公开仓库:
#!/usr/bin/env bash
set -euo pipefail
PING_URL='https://hc.example.com/ping/REPLACE_WITH_CHECK_UUID'
curl -fsS --max-time 10 "$PING_URL/start" >/dev/null || true
if /usr/local/bin/your-backup-script; then
curl -fsS --max-time 10 "$PING_URL" >/dev/null || true
else
curl -fsS --max-time 10 "$PING_URL/fail" >/dev/null || true
exit 1
fi
先用一个无破坏性的测试脚本替换备份命令。正常执行应变绿;模拟非零退出应报告失败;暂停测试任务超过周期和宽限时间,应收到漏跑通知。告警出现在网页中还不够,邮箱或其他通知入口也要真正收到。
接到真实告警后,检查任务日志与备份文件,再进行一次恢复验证。收到成功心跳只说明脚本按它定义的成功条件结束,不能证明备份内容完整。
保留检查项与通知配置
恢复后检查检查项、历史记录、通知渠道和一次漏跑告警。固定 PostgreSQL 16,主版本升级另走数据库迁移流程,不直接更换镜像标签。
在工作目录执行下面的停机备份,压缩包保存在应用目录之外。停止全部服务会带来短暂不可用;确认停止成功后再打包。
docker compose stop
sudo install -d -m 0700 /var/backups/docker-apps
backup_file="/var/backups/docker-apps/$(basename "$PWD")-$(date +%Y%m%d-%H%M%S).tar.gz"
sudo tar -czpf "$backup_file" compose.yaml database .env
sudo chmod 0600 "$backup_file"
sudo tar -tzf "$backup_file" | head
docker compose start
将压缩包复制到 VPS 之外。恢复时,在另一台测试机器的空目录解包,保留文件所有者和相对路径,用原镜像版本启动,检查前面提到的数据。不要直接覆盖正在使用的原数据目录。
升级前先记录镜像 ID 或摘要,并保存这份备份。阅读项目更新说明后再拉取镜像;涉及数据库迁移时,回滚需要恢复旧数据与旧镜像,不能只把标签改回去。
安装参数和数据路径可对照Healthchecks Docker 文档。