Healthchecks v4.4 Docker Compose 部署指南
用官方镜像 healthchecks/healthchecks:v4.4 与 postgres:16 通过 Docker Compose 部署 Healthchecks 心跳监控:.env 配置、数据持久化、Nginx 反代、升级回滚与常见问题,全程实测。
Healthchecks v4.4 Docker Compose 部署指南
目标:用官方镜像
healthchecks/healthchecks:v4.4+postgres:16,以 Docker Compose 一键部署 Healthchecks 心跳监控平台,覆盖 .env 配置、数据持久化、管理员创建、Nginx 反代、升级回滚与常见问题。已在 Docker 29.8.1 + Compose v5.5.1 环境实测通过。
一、环境信息
本文所有命令在以下环境实测执行,回显均为真实输出:
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- Docker:29.8.1(Server),存储驱动 vfs
- Docker Compose:v5.5.1(
docker compose插件) - Healthchecks 镜像:
healthchecks/healthchecks:v4.4(287 MB) - 数据库镜像:
postgres:16(451 MB) - 部署目录:
/opt/healthchecks(含.env与docker-compose.yml) - 服务端口:Web
8000,PostgreSQL 集群内5432 - 管理账号:
admin@example.org/q1w2e3r4
二、镜像选型说明
Healthchecks 官方在 Docker Hub 维护 healthchecks/healthchecks 镜像,tag 与 GitHub Release 对应(v4.4、v4.3…,latest 跟随最新 stable)。查询可用 tag:
curl -s "https://hub.docker.com/v2/repositories/healthchecks/healthchecks/tags/?page_size=6" | python3 -c "import json,sys; [print(t['name'], t['last_updated'][:10]) for t in json.load(sys.stdin)['results']]"
实测输出:
latest 2026-08-31
v4.4 2026-08-31
v4.3 2026-07-14
v4.2 2026-04-28
v4.1.1 2026-03-25
v4.1 2026-03-20
官方镜像的关键特性(来自镜像内 docker/uwsgi.ini 的启动编排,启动日志可印证):
- 内置 uWSGI 作为 WSGI 服务器,监听
0.0.0.0:8000; - 启动时自动执行
manage.py migrate(uWSGI pre-app hook)、sendalerts、sendreports --loop常驻进程,无需手工干预; - 内置健康检查(
fetchstatus.py访问/api/v3/status/),docker ps会显示healthy; - 数据库镜像选用
postgres:16(Healthchecks v4.4 要求 PostgreSQL ≥ 15)。
💡 技术拓展:WSGI 服务器不止 uWSGI 一种,常见对比——
服务器 特点 适用场景 uWSGI C 实现、功能全(进程管理/静态文件压缩/daemon 编排),官方镜像默认 官方镜像、需要一体化进程管理 gunicorn 纯 Python、配置简单、生态标准 源码部署首选(见安装指南篇) waitress 纯 Python、跨平台(Windows 可用) Windows 环境 官方镜像实际采用 uWSGI,通过
UWSGI_*环境变量免改文件调参,本文沿用。
三、前置条件
- Ubuntu 20.04+/Debian 11+ 等已安装 Docker 与 Compose 插件的宿主机:
docker version --format 'server: {{.Server.Version}}'
docker compose version
server: 29.8.1
Docker Compose version v5.5.1
- 宿主机可访问 Docker Hub(或已配置可用的镜像源/代理);
- 放行 8000 端口(或反代端口)。
四、部署步骤
4.1 拉取镜像
docker pull healthchecks/healthchecks:v4.4
docker pull postgres:16
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | grep -E "healthchecks|postgres"
实测输出(节选):
docker.io/healthchecks/healthchecks:v4.4
docker.io/library/postgres:16
postgres:16 451MB
healthchecks/healthchecks:v4.4 287MB
4.2 准备部署目录与 .env
mkdir -p /opt/healthchecks && cd /opt/healthchecks
先生成随机 SECRET_KEY:
python3 -c "import secrets; print(secrets.token_urlsafe(40))"
实测输出:
bX9Kv2QwLpR7sTnY4cHjE8mZaD5fGxUoB1iN6eC0uS3t
写入 .env(SECRET_KEY 替换为你自己的值):
cat > .env << 'EOF'
ALLOWED_HOSTS=localhost,127.0.0.1
DB=postgres
DB_HOST=db
DB_PORT=5432
DB_NAME=hc
DB_USER=hc
DB_PASSWORD=q1w2e3r4
DB_SSLMODE=prefer
DEBUG=False
SECRET_KEY=bX9Kv2QwLpR7sTnY4cHjE8mZaD5fGxUoB1iN6eC0uS3t
SITE_ROOT=http://localhost:8000
SITE_NAME=Mychecks
DEFAULT_FROM_EMAIL=healthchecks@localhost
EMAIL_HOST=
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_USE_VERIFICATION=False
PING_EMAIL_DOMAIN=localhost
REGISTRATION_OPEN=True
EOF
chmod 600 .env
逐项说明:DB_* 五个键描述数据库连接(Compose 网络里用服务名 db 作主机名);ALLOWED_HOSTS 是 Host 白名单,接入域名后要把域名加进来(见 4.7);SITE_ROOT 决定邮件里的链接与 ping URL;EMAIL_HOST 留空表示暂不发告警邮件,配上 SMTP 服务器即可启用(键含义详见《Healthchecks v4.4 配置参数详解》)。
4.3 编写 docker-compose.yml
cat > docker-compose.yml << 'EOF'
volumes:
db-data:
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=hc
- POSTGRES_USER=hc
- POSTGRES_PASSWORD=q1w2e3r4
restart: unless-stopped
web:
image: healthchecks/healthchecks:v4.4
env_file:
- .env
ports:
- "8000:8000"
depends_on:
- db
restart: unless-stopped
command: bash -c "while !</dev/tcp/db/5432; do sleep 1; done; uwsgi /opt/healthchecks/docker/uwsgi.ini"
EOF
配置解读:db-data 命名卷把 PostgreSQL 数据目录落在卷里(数据持久化见第五章);web 通过 env_file 注入 .env 全部变量;command 里先探测 db 的 5432 端口就绪再启动 uWSGI,避免数据库未就绪时 migrate 失败;restart: unless-stopped 保证开机与异常自动拉起。与官方仓库 docker/docker-compose.yml 的差异:官方默认从源码 build:,这里改用预构建 image: 免编译,depends_on 简化为容器就绪等待(上面 bash 探测已兜底)。
4.4 启动
cd /opt/healthchecks
docker compose up -d
实测输出:
Network healthchecks_default Created
Container healthchecks-db-1 Created
Container healthchecks-db-1 Started
Container healthchecks-web-1 Created
Container healthchecks-web-1 Started
确认状态(web 出现 healthy 即健康检查通过):
docker compose ps --format "table {{.Name}}\t{{.Image}}\t{{.Status}}"
NAME IMAGE STATUS
healthchecks-db-1 postgres:16 Up 25 seconds
healthchecks-web-1 healthchecks/healthchecks:v4.4 Up 25 seconds (healthy)
看 web 日志确认自动初始化(首次启动 uWSGI pre-app hook 会自动 migrate 建表):
docker compose logs web 2>&1 | grep -E "migrate|Operations|Applying" | head -5
实测输出(节选):
web-1 | running "exec:./manage.py migrate" (pre app)...
web-1 | Operations to perform:
web-1 | Applying contenttypes.0001_initial... OK
web-1 | Applying auth.0001_initial... OK
web-1 | Applying accounts.0001_initial... OK
4.5 创建管理员并登录验证
docker compose run --rm web /opt/healthchecks/manage.py createsuperuser --email admin@example.org --password q1w2e3r4
实测输出:
Superuser created successfully.
HTTP 验证:
curl -s http://127.0.0.1:8000/accounts/login/ -o /dev/null -w "GET /accounts/login/ -> %{http_code}\n"
GET /accounts/login/ -> 200
浏览器打开 http://<服务器IP>:8000,用 admin@example.org / q1w2e3r4 登录即可进入 Check 列表页。登录后的建 Check、ping、通知渠道配置见《Healthchecks v4.4 快速入门与集成示例》。
4.6 生成 API Key(可选)
Web 界面路径是「项目 → Settings → API Keys → Create API Key」,也可在服务内执行同款逻辑生成:
docker compose exec -T web /opt/healthchecks/manage.py shell -c "from hc.api.models import Project; p = Project.objects.first(); key = p.set_api_key(); p.save(); print(key)"
实测输出:
hcw_MEQNR93QMDvowMpBJsV1QzgovncA
⚠️ 注意:
set_api_key()只改内存对象,必须紧跟p.save()才落库;明文 Key 只显示这一次,丢失后只能重新生成。
五、数据持久化说明
数据分两部分,都已有落盘保障:
- PostgreSQL 数据:
db-data命名卷 →/var/lib/postgresql/data(Compose 声明的volumes: db-data,docker compose down不删除); - 配置:
.env与docker-compose.yml在/opt/healthchecks目录。
重启演练验证数据不丢:
cd /opt/healthchecks
docker compose down
docker compose up -d
sleep 15
docker compose ps --format "{{.Name}} {{.Status}}"
KEY=hcw_MEQNR93QMDvowMpBJsV1QzgovncA
curl -s -H "X-Api-Key: $KEY" http://127.0.0.1:8000/api/v3/checks/ | python3 -c "import json,sys; d=json.load(sys.stdin); print('重启后 checks:', [c['name'] for c in d['checks']])"
实测输出:
Container healthchecks-web-1 Stopped
Container healthchecks-db-1 Stopped
Network healthchecks_default Removed
Container healthchecks-db-1 Started
Container healthchecks-web-1 Started
healthchecks-db-1 Up 15 seconds
healthchecks-web-1 Up 15 seconds (healthy)
重启后 checks: ['job-nightly', 'My First Check']
down 只移除网络与容器、保留卷;若要连数据一起清掉用 docker compose down -v(危险操作,先备份)。
如需把数据卷换成宿主机目录(方便 rsync 备份),把 db 服务的 volumes 改为:
volumes:
- /opt/healthchecks/pgdata:/var/lib/postgresql/data
六、环境变量表
Healthchecks 官方镜像的全部行为都通过 .env 环境变量配置(镜像内 docker/.env.example 同步官方默认值)。高频键实测汇总:
| 键 | 本文取值 | 默认值 | 说明 |
|---|---|---|---|
ALLOWED_HOSTS | localhost,127.0.0.1 | localhost | Host 白名单,逗号分隔;不含访问域名时返回 400 |
DB | postgres | postgres | 数据库类型(postgres/mysql/sqlite) |
DB_HOST | db | db | Compose 服务名即主机名 |
DB_PORT | 5432 | 5432 | PostgreSQL 端口 |
DB_NAME/DB_USER/DB_PASSWORD | hc/hc/q1w2e3r4 | hc/postgres/— | 与 db 服务 environment 保持一致 |
DB_SSLMODE | prefer | prefer | psycopg SSL 模式 |
SECRET_KEY | 随机 40+ 位 | --- | 必改;签名根密钥 |
SITE_ROOT | http://localhost:8000 | http://localhost:8000 | 对外基础 URL |
SITE_NAME | Mychecks | Mychecks | 站点名称(邮件、页面标题) |
DEBUG | False | False | 生产保持 False |
EMAIL_HOST | 空 | 空 | 出站 SMTP 主机,设置后启用告警邮件 |
EMAIL_PORT | 587 | 587 | SMTP 端口 |
EMAIL_USE_TLS | True | True | STARTTLS |
EMAIL_USE_VERIFICATION | False | True | 邮件渠道是否需验证确认 |
DEFAULT_FROM_EMAIL | healthchecks@localhost | healthchecks@example.org | 发件人 |
PING_EMAIL_DOMAIN | localhost | localhost | 入站邮件 ping 的收件域名 |
REGISTRATION_OPEN | True | True | 是否开放自助注册 |
SMTPD_PORT | 未设置 | 未设置 | 设置后镜像内启动入站邮件服务器监听该端口 |
UWSGI_PROCESSES | 未设置(默认 4) | 4 | uWSGI worker 数,省内存可调 2 |
PING_BODY_LIMIT | 未设置 | 10000 | ping body 落库最大字节数 |
完整键位清单与逐项语义见《Healthchecks v4.4 配置参数详解》。
七、配置参数说明与 .env 修改生效方式
修改 .env 后需要重建 web 容器才生效(env_file 在容器创建时注入,restart 不重读):
cd /opt/healthchecks
docker compose up -d web
实测输出(配置变化会触发 recreate):
Container healthchecks-web-1 Recreate-started
Container healthchecks-web-1 Recreated
Container healthchecks-web-1 Started
实测两个关键行为:
SITE_NAME改成OpsWatch并up -d web后,登录页标题随之变化:
<title>Log In - OpsWatch</title>
ALLOWED_HOSTS不含访问用的 Host 时直接 400(Django 拒绝),这是排查「反代后 400」问题的第一现场:
Host=evil.example.com -> 400
八、配置文件挂载
官方镜像把静态资源编译进镜像,常规使用无需挂载任何配置文件,全部配置走环境变量。如需深度定制(例如替换 hc/local_settings.py),可用 bind mount 覆盖:
web:
volumes:
- ./local_settings.py:/opt/healthchecks/hc/local_settings.py:ro
官方 Dockerfile 构建时会删除自带示例的 local_settings.py,挂载进去的文件会在启动时优先生效;注意它与 .env 环境变量并存时,环境变量先读、local_settings.py 覆盖同名字段,两者不要写同名键以免排障混乱。
九、等价 docker run
不使用 Compose 时,等价的单容器启动方式(数据库需另起,这里一并给出):
# 1) 数据库
docker run -d --name healthchecks-db \
-e POSTGRES_DB=hc -e POSTGRES_USER=hc -e POSTGRES_PASSWORD=q1w2e3r4 \
-v healthchecks-db-data:/var/lib/postgresql/data \
postgres:16
# 2) 应用
docker run -d --name healthchecks-web --restart unless-stopped \
--env-file /opt/healthchecks/.env \
-p 8000:8000 \
healthchecks/healthchecks:v4.4
与 Compose 的差异:--env-file 同样在创建时注入;两容器需在同一网络才能用 db 主机名互访(docker network create + --network,或直接沿用 Compose 更省事)。验证:
curl -s http://127.0.0.1:8000/accounts/login/ -o /dev/null -w "%{http_code}\n"
200
十、Nginx 反向代理
宿主机安装 Nginx 并反代到 8000 端口:
apt-get install -y nginx
nginx -v
nginx version: nginx/1.18.0 (Ubuntu)
写入 /etc/nginx/sites-available/healthchecks 并启用:
server {
listen 80;
server_name hc.example.org;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_pass http://127.0.0.1:8000;
}
}
ln -sf /etc/nginx/sites-available/healthchecks /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl restart nginx
实测输出:
nginx: configuration file /etc/nginx/nginx.conf test is successful
用域名 Host 头访问验证:
curl -s -H "Host: hc.example.org" http://127.0.0.1/ -o /dev/null -w "Nginx 反代 Host=hc.example.org -> %{http_code}\n"
实测输出:
Nginx 反代 Host=hc.example.org -> 400
400 的原因:proxy_set_header Host $host 把真实域名透传给了 Healthchecks,而 .env 的 ALLOWED_HOSTS=localhost,127.0.0.1 不含该域名。把域名补进白名单并重建容器:
sed -i 's/^ALLOWED_HOSTS=localhost,127.0.0.1/ALLOWED_HOSTS=localhost,127.0.0.1,hc.example.org/' .env
docker compose up -d web
sleep 12
curl -s -H "Host: hc.example.org" http://127.0.0.1/ -o /dev/null -w "补白名单后 Nginx 反代 -> %{http_code}\n"
实测输出:
Container healthchecks-web-1 Started
补白名单后 Nginx 反代 -> 302
302 跳登录页即反代打通。SITE_ROOT 此时也应改为对外域名(如 http://hc.example.org),否则邮件里的链接仍是 localhost。生产建议再叠一层 TLS(certbot 或云 LB 终止 HTTPS),并同步把 SITE_ROOT 更新为 https:// 形式。
十一、常用运维命令
cd /opt/healthchecks
docker compose ps # 状态一览
docker compose logs -f web # 跟踪 web 日志(Ctrl+C 退出)
docker compose logs web 2>&1 | tail -50 # 最近 50 行
docker compose restart web # 重启单个服务
docker compose stop # 停止(保留容器与卷)
docker compose up -d # 启动
docker compose down # 移除容器与网络(保留卷)
docker compose exec web bash # 进入容器排障
docker compose run --rm web /opt/healthchecks/manage.py <命令> # 执行管理命令
常用管理命令(容器内执行):
docker compose run --rm web /opt/healthchecks/manage.py createsuperuser --email <邮箱> --password <密码>
docker compose run --rm web /opt/healthchecks/manage.py pruneobjects
docker compose run --rm web /opt/healthchecks/manage.py shell
💡 说明:
migrate、sendalerts、sendreports、smtpd由镜像启动编排自动运行,不要手工再起一份;createsuperuser、pruneobjects、prunetokenbucket等批处理命令才需要run --rm手动执行。
十二、常见问题(FAQ)
Q1:web 容器反复重启或 migrate 连不上数据库?
先看日志:docker compose logs web | grep -i error。最常见是 .env 的 DB_HOST/DB_USER/DB_PASSWORD 与 db 服务 environment 不一致;其次是数据库未就绪——本文 compose 的 command 已带 /dev/tcp/db/5432 就绪探测,若自定义了 command 记得保留探测段。实测正常启动时 pre-app hook 会打印 running "exec:./manage.py migrate" (pre app)... 后跟 Applying ... OK。
Q2:反代/域名访问返回 400?
ALLOWED_HOSTS 白名单问题(实测见第十章),把访问域名加进 .env 后 docker compose up -d web 重建即可。注意 docker compose restart 不会重读 .env。
Q3:登录页正常但收不到告警邮件?
EMAIL_HOST 未配置(settings 对应 hc.api.W002 警告)或 SMTP 凭据错误。配置后 up -d web 重建,并确认 DEFAULT_FROM_EMAIL 是收件方可接受的地址。告警派发由镜像内常驻的 sendalerts 完成,可在 docker compose logs web 中看到每次通知的发送记录。
Q4:如何升级/回滚版本?
升级:改 docker-compose.yml 镜像 tag → docker compose pull → docker compose up -d。新容器启动时 pre-app hook 自动 migrate。实测 v4.3 → v4.4 升级:
web-1 | Operations to perform:
web-1 | No migrations to apply.
数据完好性核对(升级后 Check 全部还在):
升级后 checks: ['job-nightly', 'My First Check']
回滚:把 tag 改回旧版本(如 v4.3)再 up -d。⚠️ 若新版本带来了不可逆的数据库迁移,回滚前需用第五章的卷备份恢复数据,因此升级前先备份。
Q5:健康检查一直 starting 或 unhealthy?
镜像 HEALTHCHECK 会请求自身 /api/v3/status/,启动期 20 秒内属正常(--start-period=20s)。持续 unhealthy 时进容器手工验证:docker compose exec web /opt/healthchecks/fetchstatus.py; echo $?,非 0 说明应用异常,结合日志定位(常见是数据库连不上导致 status 接口 500)。
Q6:内存占用想压一压?
默认 uWSGI 起_processes=4_ 个 worker。小内存机器在 .env 加 UWSGI_PROCESSES=2 后 up -d web 生效(官方文档同名变量),再配合 docker stats 观察。
十三、参考链接
- 官方容器文档(源码仓库 docker/README):https://github.com/healthchecks/healthchecks/tree/master/docker
- 镜像页:https://hub.docker.com/r/healthchecks/healthchecks
- 官方 compose 样例:https://github.com/healthchecks/healthchecks/blob/master/docker/docker-compose.yml
- 自托管配置说明:https://healthchecks.io/docs/self_hosted_configuration/
- 本系列其他篇:《Healthchecks v4.4 Ubuntu 22.04 安装指南》《Healthchecks v4.4 快速入门与集成示例》《Healthchecks v4.4 配置参数详解》《Healthchecks v4.4 进阶实战与运维》