对于中小团队、独立开发者或个人站长来说,部署 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 的对外服务状态页。

官网地址

在这里插入图片描述

1.1 Uptime Kuma 的核心定位:轻量型黑盒可用性监控

从项目代码库的信息能明确,Uptime Kuma 主打 网络层 / 服务层的可用性监控(黑盒监控),核心能力集中在:

  1. 监控对象:HTTP (s)、TCP、DNS 记录、Websocket、Ping、Docker 容器(仅监控 “是否运行”)、Steam 游戏服务器、RabbitMQ/Kafka 等中间件(基础可达性);
  2. 核心目标:判断 “服务 / 端口 / 中间件是否在线、响应是否符合预期”(比如 HTTP 关键词匹配、JSON 响应校验、证书过期提醒);
  3. 优势:轻量化、自托管简单、UI 友好、多语言支持、通知渠道丰富(90+ 种)、快速搭建状态页面,适合中小团队 / 个人快速实现 “服务是否可用” 的监控;
  4. 短板无原生的本地主机系统指标监控能力(比如 CPU / 内存 / 磁盘使用率、进程数、网络吞吐量等主机级指标),仅能监控 “主机上的服务是否存活”,无法深入主机内部采集指标。

1.2 Prometheus 的核心定位:企业级白盒指标监控

Prometheus 是云原生时代的时序数据库监控工具,主打 系统 / 应用层的深度指标监控(白盒监控),核心能力集中在:

  1. 监控对象:本地主机(node_exporter 采集 CPU / 内存 / 磁盘)、K8s 集群、微服务、中间件(Prometheus Exporter 采集 Redis/MongoDB/MySQL 等的深度指标)、自定义业务指标;
  2. 核心目标:采集 “系统 / 应用的内部运行指标”,做趋势分析、阈值告警、性能复盘(比如主机内存使用率 80% 告警、接口 QPS 波动分析);
  3. 优势:生态完善(搭配 Grafana 可视化、Alertmanager 告警、各类 Exporter)、支持自定义指标、适合大规模 / 精细化监控;
  4. 短板:部署和学习成本高,轻量性差,单纯做 “服务是否在线” 的监控会显得过重。

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相关数据库则需要提前创建好相关数据库:

image-20260129215651498

创建相关用户:

image-20260129215727721

最后进入如下页面:

在这里插入图片描述

三、实战配置指南

3.1 添加监控项

3.1.1 监控 Web 服务与 SSL 证书过期

这是最常用的场景。我们不仅要监控网站是否 200 OK,还要防止 SSL 证书过期导致的事故。

  1. 点击左上角 “+ 添加监控项”。
  2. 监控类型选择 HTTP(s)。
  3. URL 填入你的网址(例如 https://www.baidu.com)。
  4. 高级设置中:
    勾选 “证书过期提醒”。
    设置剩余天数(例如 7 天),这样证书快过期时你会收到报警。
    心跳间隔:建议设置为 60 秒。

在这里插入图片描述

添加后如下

在这里插入图片描述

3.1.2 监控 TCP 端口(Redis/MySQL)

有时候 Web 服务是好的,但数据库挂了。我们可以通过 TCP 端口探测来监控中间件。

  1. 监控类型选择 TCP Port
  2. Hostname 填入数据库服务器 IP。
  3. Port 填入 3306 (MySQL) 或 6379 (Redis)。

参考如下:

image-20260201190840418

3.1.3 监控 Docker 容器

当业务服务基于 Docker 容器部署时,需直接监控容器运行状态,避免容器退出但宿主机正常导致的服务不可用问题。

  1. 监控类型选择 Docker
  2. Docker 连接配置:
    • 监控本地容器:无需额外配置,确保 Uptime Kuma 所在主机可访问 Docker 守护进程(默认 /var/run/docker.sock 权限正确);
  3. 容器选择:
    • 选择 Container Name/ID,直接填入容器名称(如 mysql-8.0)或完整容器 ID;

参考如下:

image-20260201190513314

3.1.4 监控数据库

除 TCP 端口探测外,可通过数据库专属监控类型实现深度健康检测(不仅检测端口通断,还验证连接 / 查询可用性)。

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

参考如下:

image-20260201190137102

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

参考如下:

image-20260201185451559

还有其他的监控这里就不一一补充了。

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: "未获取" }}

image-20260201160306326

范例:关闭监控中的某一网站进行测试(需要自行在监控项当中启用配置)

服务宕机邮件显示:

在这里插入图片描述

服务恢复正常邮件显示:

在这里插入图片描述

总结

回过头来看,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 绝对值得一试,它会用实力证明:轻量监控也能兼顾全面性与实用性。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐