GitHub 80k+ 星的监控神器 Uptime Kuma
对于中小团队、独立开发者或个人站长来说,部署 Zabbix 或 Prometheus+Grafana 往往显得 “杀鸡用牛刀”—— 前者配置繁琐、界面老旧,后者学习曲线陡峭,都远超轻量监控的实际需求。而我翻遍网上相关文章,发现大多要么只提基础功能、要么漏了关键配置细节,始终找不到一份全面实用的指南。正因如此,我决定整理编写这篇文章,为大家诚意推荐这款 GitHub 霸榜的开源监控工具 Uptime Kuma:它颜值极高、支持 Docker 一键部署、自带可自定义的状态页,更涵盖飞书、钉钉、Telegram 在内的 90+ 种通知方式,能轻松覆盖网站、数据库、Docker 容器等主流监控场景,用下来完全是 “小而美” 的极致体验,堪称轻量级监控的最优解。

一、简单介绍与对比
为什么选择 Uptime Kuma?
在传统的运维监控领域,我们通常面临两个极端:
- Zabbix:功能强大但配置繁琐,UI 停留在上个世纪。
- Prometheus:云原生标配,但学习曲线陡峭,且本身不带可视化面板。
Uptime Kuma 的出现填补了“轻量级、高颜值、开箱即用”的空白。
核心特性
-
监控类型丰富:支持 HTTP(s)、TCP、Ping、DNS Record、Docker 容器等。
-
UI 现代化:响应式设计,黑暗模式,看起来非常舒服。
-
通知渠道强:内置支持企业微信、飞书、钉钉、Email、TG 等国内常用渠道。
-
状态页(Status Page):不仅监控,还能自动生成类似 GitHub Status 的对外服务状态页。
官网地址
- https://github.com/louislam/uptime-kuma?tab=readme-ov-file
- 官方演示服务器(地点:德国法兰克福):https://demo.kuma.pet/start-demo

1.1 Uptime Kuma 的核心定位:轻量型黑盒可用性监控
从项目代码库的信息能明确,Uptime Kuma 主打 网络层 / 服务层的可用性监控(黑盒监控),核心能力集中在:
- 监控对象:HTTP (s)、TCP、DNS 记录、Websocket、Ping、Docker 容器(仅监控 “是否运行”)、Steam 游戏服务器、RabbitMQ/Kafka 等中间件(基础可达性);
- 核心目标:判断 “服务 / 端口 / 中间件是否在线、响应是否符合预期”(比如 HTTP 关键词匹配、JSON 响应校验、证书过期提醒);
- 优势:轻量化、自托管简单、UI 友好、多语言支持、通知渠道丰富(90+ 种)、快速搭建状态页面,适合中小团队 / 个人快速实现 “服务是否可用” 的监控;
- 短板:无原生的本地主机系统指标监控能力(比如 CPU / 内存 / 磁盘使用率、进程数、网络吞吐量等主机级指标),仅能监控 “主机上的服务是否存活”,无法深入主机内部采集指标。
1.2 Prometheus 的核心定位:企业级白盒指标监控
Prometheus 是云原生时代的时序数据库监控工具,主打 系统 / 应用层的深度指标监控(白盒监控),核心能力集中在:
- 监控对象:本地主机(node_exporter 采集 CPU / 内存 / 磁盘)、K8s 集群、微服务、中间件(Prometheus Exporter 采集 Redis/MongoDB/MySQL 等的深度指标)、自定义业务指标;
- 核心目标:采集 “系统 / 应用的内部运行指标”,做趋势分析、阈值告警、性能复盘(比如主机内存使用率 80% 告警、接口 QPS 波动分析);
- 优势:生态完善(搭配 Grafana 可视化、Alertmanager 告警、各类 Exporter)、支持自定义指标、适合大规模 / 精细化监控;
- 短板:部署和学习成本高,轻量性差,单纯做 “服务是否在线” 的监控会显得过重。
1.3 总结:场景适配而非 “优劣对比”
| 对比维度 | Uptime Kuma | Prometheus |
|---|---|---|
| 监控类型 | 黑盒监控(可用性) | 白盒监控(指标) |
| 本地主机监控能力 | 仅监控 “主机上的服务是否可达” | 深度采集主机系统指标(CPU / 内存等) |
| 中间件监控 | 基础可达性(比如 RabbitMQ 是否运行) | 深度指标(比如 RabbitMQ 队列长度) |
| 易用性 | 极低(开箱即用) | 较高(需配置 Exporter / 规则) |
| 适用场景 | 中小团队 / 个人,服务可用性监控 | 企业级 / 大规模,系统 / 应用性能监控 |
所以结论是:
- 如果你只需要监控本地主机上的服务 / 端口是否在线、中间件是否可达,Uptime Kuma 足够用,且比 Prometheus 更简单、轻量化;
- 如果你需要监控本地主机的系统资源(CPU / 内存 / 磁盘)、中间件的深度性能指标,并做趋势分析 / 性能优化,Prometheus(搭配 node_exporter 等)是更合适的选择;
- 两者甚至可以互补:用 Uptime Kuma 做服务可用性监控(快速告警),用 Prometheus 做系统 / 应用指标监控(深度分析)。
二、快速安装
需要自己提前安装好docker环境,这里就不再说明。
下面我采用docker-compose的方式进行启动
2.1 Docker 命令的方式启动
根据官网给出的命令直接运行即可:
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2
2.2 Docker Compose的方式启动
官网示例:
mkdir uptime-kuma
cd uptime-kuma
curl -o compose.yaml https://raw.githubusercontent.com/louislam/uptime-kuma/master/compose.yaml
docker compose up -d
这里在官网的基础上结合自己的的实际需求,最终采用以下配置
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: always
ports:
- "8080:3001"
volumes:
- /data/uptime-kuma:/app/data
- /var/run/docker.sock:/var/run/docker.sock
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
启动服务
启动成功后,访问 http://你的服务器IP:8080(如果是云服务器则开放相关端口),首次访问会要求你创建一个管理员账号。
根据自己的实际情况来选择,这里为了测试方便我直接选择SQLite
如果采用MySQL相关数据库则需要提前创建好相关数据库:

创建相关用户:

最后进入如下页面:

三、实战配置指南
3.1 添加监控项
3.1.1 监控 Web 服务与 SSL 证书过期
这是最常用的场景。我们不仅要监控网站是否 200 OK,还要防止 SSL 证书过期导致的事故。
- 点击左上角 “+ 添加监控项”。
- 监控类型选择 HTTP(s)。
- URL 填入你的网址(例如 https://www.baidu.com)。
- 高级设置中:
勾选 “证书过期提醒”。
设置剩余天数(例如 7 天),这样证书快过期时你会收到报警。
心跳间隔:建议设置为 60 秒。

添加后如下

3.1.2 监控 TCP 端口(Redis/MySQL)
有时候 Web 服务是好的,但数据库挂了。我们可以通过 TCP 端口探测来监控中间件。
- 监控类型选择
TCP Port。 - Hostname 填入数据库服务器 IP。
- Port 填入
3306(MySQL) 或6379(Redis)。
参考如下:

3.1.3 监控 Docker 容器
当业务服务基于 Docker 容器部署时,需直接监控容器运行状态,避免容器退出但宿主机正常导致的服务不可用问题。
- 监控类型选择
Docker - Docker 连接配置:
- 监控本地容器:无需额外配置,确保 Uptime Kuma 所在主机可访问 Docker 守护进程(默认
/var/run/docker.sock权限正确);
- 监控本地容器:无需额外配置,确保 Uptime Kuma 所在主机可访问 Docker 守护进程(默认
- 容器选择:
- 选择
Container Name/ID,直接填入容器名称(如mysql-8.0)或完整容器 ID;
- 选择
参考如下:

3.1.4 监控数据库
除 TCP 端口探测外,可通过数据库专属监控类型实现深度健康检测(不仅检测端口通断,还验证连接 / 查询可用性)。
3.1.4.1 MySQL 监控
- 监控类型选择
MySQL。 - 连接配置(适配
mysql://username:password@host:port/database格式):- Hostname:填入连接串中的
host部分(数据库服务器 IP / 域名); - Port:填入连接串中的
port部分,默认3306(若修改过端口则填实际值); - Database:填入连接串中
/后的数据库名(如mysql,需确保该数据库存在); - Username/Password:填写有连接权限的数据库账号(建议创建只读监控账号)。
- Hostname:填入连接串中的
- 高级配置(可选):
- 填写
SQL Query:自定义检测 SQL(如SELECT 1),验证数据库查询能力; - 设置
Timeout:建议 5-10 秒,避免连接超时导致误告警。
- 填写
参考如下:

3.1.4.2 Redis 监控
- 监控类型选择
Redis。 - 连接配置(适配
redis://[user:]password@host:port格式):- Hostname:填连接串中的
host(如192.168.1.10); - Port:填连接串中的
port(默认6379); - Password:填连接串
@前的密码(如123456);(若无则留空); - Username:Redis 5.x 留空,Redis 6.0+ 填
default(无自定义用户时)
- Hostname:填连接串中的
参考如下:

还有其他的监控这里就不一一补充了。
3.2 配置监控警告
监控警告是 Uptime Kuma 核心功能之一,用于在监控项状态异常(如服务 Down、证书到期)时,通过指定渠道及时推送告警通知,帮助运维人员快速响应故障。
更多监控请访问:https://huangjingblog.cn/post/github-80k-xing-de-jian-kong-shen-qi-uptime-kuma
该文章为学习大佬总结的内容,该文章相关内容由该博主提供。
3.2.1 飞书机器人
飞书机器人支持通过 Webhook 接收告警消息,适配 Markdown 富文本格式,可清晰展示监控详情(如服务名称、状态、问题详情等),适合团队内部协同通知。
3.2.1.1 自定义告警模板
feishu_robot.py内容如下:
import os
import json
import time
import base64
import hmac
import hashlib
import requests
from flask import Flask, request
app = Flask(__name__)
FEISHU_WEBHOOK_URL = os.getenv("FEISHU_WEBHOOK_URL", "https://open.feishu.cn/open-apis/bot/v2/hook/xxxx")
FEISHU_SECRET = os.getenv("FEISHU_SECRET", "").strip() # 开启“签名校验”才需要
HTTP_TIMEOUT = float(os.getenv("HTTP_TIMEOUT", "5"))
def gen_feishu_sign(secret: str, timestamp: int) -> str:
"""
飞书自定义机器人“签名校验”算法:
把 timestamp + "\n" + secret 当做 key,对空字符串做 HmacSHA256,再 Base64。
官方文档描述就是这个逻辑。:contentReference[oaicite:3]{index=3}
"""
key = f"{timestamp}\n{secret}".encode("utf-8")
h = hmac.new(key, b"", digestmod=hashlib.sha256)
return base64.b64encode(h.digest()).decode("utf-8")
def send_to_feishu(card: dict):
payload = {
"msg_type": "interactive",
"card": card,
}
if FEISHU_SECRET:
ts = int(time.time())
payload["timestamp"] = str(ts)
payload["sign"] = gen_feishu_sign(FEISHU_SECRET, ts)
resp = requests.post(
FEISHU_WEBHOOK_URL,
headers={"Content-Type": "application/json"},
data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
timeout=HTTP_TIMEOUT,
)
if resp.status_code != 200:
raise RuntimeError(f"Feishu HTTP {resp.status_code}: {resp.text}")
try:
data = resp.json()
except Exception:
raise RuntimeError(f"Feishu response not json: {resp.text}")
# 飞书成功一般是 {"code":0,"msg":"success"}
if isinstance(data, dict) and str(data.get("code")) not in ("0", "None"):
raise RuntimeError(f"Feishu send failed: {data}")
return data
def safe_dict(v):
return v if isinstance(v, dict) else {}
def get_base_info(data: dict):
monitor = safe_dict(data.get("monitor") or {})
heartbeat = safe_dict(data.get("heartbeat") or {})
status_raw = heartbeat.get("status")
is_up = (status_raw == 1)
status_text = "Up" if is_up else "Down"
status_template = "green" if is_up else "red"
return monitor, heartbeat, status_text, status_template
def md(v) -> str:
if v is None:
return "-"
s = str(v)
return s if s.strip() else "-"
def build_md(title: str, pairs: list[tuple[str, str]]) -> str:
lines = [f"**{md(title)}**"]
for k, v in pairs:
lines.append(f"**{md(k)}:** {md(v)}")
return "\n".join(lines)
def build_card(monitor_type: str, monitor: dict, heartbeat: dict, status_text: str, status_template: str) -> dict:
name = monitor.get("name")
msg = heartbeat.get("msg")
local_dt = heartbeat.get("localDateTime")
monitor_id = heartbeat.get("monitorID")
if monitor_type == "http":
content_md = build_md("【Uptime Kuma 监控告警】/ HTTP(s)", [
("项目名称", name),
("监控地址", monitor.get("url")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type == "port":
content_md = build_md("【Uptime Kuma 监控告警】/ TCP Port", [
("项目名称", name),
("监控主机", monitor.get("hostname")),
("监控端口", monitor.get("port")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type == "ping":
content_md = build_md("【Uptime Kuma 监控告警】/ Ping", [
("项目名称", name),
("监控主机", monitor.get("hostname")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type == "dns":
content_md = build_md("【Uptime Kuma 监控告警】/ DNS", [
("项目名称", name),
("监控域名", monitor.get("hostname")),
("DNS服务器", monitor.get("dns_resolve_server")),
("查询类型", monitor.get("dns_resolve_type")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type == "snmp":
content_md = build_md("【Uptime Kuma 监控告警】/ SNMP", [
("项目名称", name),
("监控主机", monitor.get("hostname")),
("对象标识符", monitor.get("snmpOid")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type == "smtp":
content_md = build_md("【Uptime Kuma 监控告警】/ SMTP", [
("项目名称", name),
("监控主机", monitor.get("hostname")),
("监控端口", monitor.get("port")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type == "docker":
content_md = build_md("【Uptime Kuma 监控告警】/ Docker 容器", [
("项目名称", name),
("监控容器", monitor.get("docker_container")),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
elif monitor_type in ("postgres", "mysql", "redis", "mongodb"):
content_md = build_md(f"【Uptime Kuma 监控告警】/ {monitor_type.upper()}", [
("项目名称", name),
("问题详情", msg),
("检测时间", local_dt),
("当前状态", status_text),
("监控ID", monitor_id),
])
else:
raw = json.dumps({"monitor": monitor, "heartbeat": heartbeat}, ensure_ascii=False)
if len(raw) > 4000:
raw = raw[:4000] + " ... (truncated)"
content_md = build_md(f"【Uptime Kuma 监控告警】/ 未知类型:{monitor_type}", [
("原始数据", f"```json\n{raw}\n```"),
])
# ✅ 修复点:Card JSON 2.0 的 elements 必须在 body.elements 下
card = {
"schema": "2.0",
"config": {
"wide_screen_mode": True
},
"header": {
"template": status_template,
"title": {
"tag": "plain_text",
"content": "Uptime Kuma 监控告警"
}
},
"body": {
"direction": "vertical",
"padding": "12px 12px 12px 12px",
"elements": [
{
"tag": "div",
"text": {
"tag": "lark_md",
"content": content_md
}
}
]
}
}
return card
@app.route("/sendnotify", methods=["POST"])
def sendnotify():
try:
data = request.json
if not data or not isinstance(data, dict):
return "invalid data", 400
monitor_obj = data.get("monitor")
monitor_type = monitor_obj.get("type") if isinstance(monitor_obj, dict) else "unknown"
monitor, heartbeat, status_text, status_template = get_base_info(data)
card = build_card(monitor_type, monitor, heartbeat, status_text, status_template)
send_to_feishu(card)
return "ok"
except Exception as e:
app.logger.error(f"处理失败: {str(e)}", exc_info=True)
return f"处理失败: {str(e)}", 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8090)
编辑 feishu_robot.py,修改 webhook URL(云服务器则需要打开对应的端口):
运行效果如下:

3.2.1.2 配置使用
设置 -> 通知 -> 设置通知 -> 通知类型(Webhook)

可以点击测试查看一下api是否能正常使用,在飞书中可以看到如下测试信息即可

范例:关闭监控中的某一网站进行测试
首先进入监控项开启通知

尝试关闭服务查看警告信息

完成
3.2.2 邮箱告警
3.2.2.1 基础使用
设置 -> 通知 -> 设置通知 -> 通知类型(电子邮箱SMTP)

注意,该密码为:

参考模板:
【Uptime Kuma 监控告警】/ <font color="{% if status == 'Up' %}green{% else %}red{% endif %}">HTTP(s)</font><br>
项目名称:<b>{{ name | default: "未命名服务" }}</b><br>
监控地址:{{ hostnameOrURL | default: "未配置" }}<br>
问题详情:<font color="{% if status == 'Up' %}green{% else %}red{% endif %}">{{ msg | default: "无详情" }}</font><br>
检测时间:{{ heartbeatJSON.localDateTime | default: "未获取" }}<br>
当前状态:<font color="{% if status == 'Up' %}green{% else %}red{% endif %}">{{ status | default: "未知状态" }}</font><br>
监控ID:{{ heartbeatJSON.monitorID | default: "未获取" }}

范例:关闭监控中的某一网站进行测试(需要自行在监控项当中启用配置)
服务宕机邮件显示:

服务恢复正常邮件显示:

总结
回过头来看,Uptime Kuma 恰好解决了中小团队、独立开发者和个人站长的核心痛点 —— 无需面对 Zabbix 的繁琐配置,也不用攻克 Prometheus+Grafana 的陡峭学习曲线,用 Docker 一键部署就能快速落地。它不仅集齐了高颜值界面、自定义状态页、90+ 种通知渠道等实用功能,更能全面覆盖网站、数据库、Docker 容器等主流监控场景,填补了轻量监控工具的市场空白。
在此感谢: https://huangjingblog.cn/ 大佬与 J神 如此全面的帮助,让鄙人可以迅速了解并开始全流程的配置与方案实现,如果想使用企业微信、钉钉等告警方案,前往访问https://huangjingblog.cn/post/github-80k-xing-de-jian-kong-shen-qi-uptime-kuma。
而 Uptime Kuma 本身从部署到监控项配置,再到告警渠道对接,全程简单易操作,资源占用低且稳定性强,完全是 “小而美” 的极致体现。如果你正需要一套轻量化、全面且好上手的监控系统,Uptime Kuma 绝对值得一试,它会用实力证明:轻量监控也能兼顾全面性与实用性。
更多推荐



所有评论(0)