不用先搭 Prometheus:用 Beszel 的 Hub + Agent 建立可回溯的多机 Docker 监控
服务器刚从一台扩展到三五台时,最容易出现一种“看上去都还活着”的错觉:容器仍在运行,业务也没有立刻报错,但某个进程已经连续数小时吃满 CPU、磁盘空间缓慢下降,或者夜间的网络尖峰根本没有留下可追溯的证据。docker stats 能看见当下,却不能回答“从什么时候开始异常”。
Beszel 是一个 MIT 许可证的轻量服务器监控项目。它把管理端称为 Hub,把每台被监控机器上的采集端称为 Agent。Hub 提供 Web 界面、历史数据与告警;Agent 负责读取主机和容器指标并连接回 Hub。对小型自托管环境而言,这种拆分很实用:不用先拼装一整套 Prometheus、时序数据库和 Grafana,也能先获得多机视图与历史趋势。
本文只走官方提供的“Hub 与本机 Agent 同机运行”的 Docker Compose 路径,并把关键边界说清楚:它适合先建立可见性,不等于把监控面板直接暴露到公网。
先判断它是否适合你的环境
Beszel 的 README 明确列出 Docker 统计、历史数据和告警;官方文档还覆盖多用户、OAuth、API、备份、GPU 与 S.M.A.R.T. 等主题。因此,它特别适合以下场景:一两台 VPS 加 NAS 或家用服务器、多个 Docker/Podman 容器、希望查看资源变化并在阈值触发时收到通知的个人或小团队。
它并不是所有场合的替代品。如果你已依赖 Prometheus 的大量 exporter、复杂的指标聚合语言或跨团队既有告警体系,那么 Beszel 更适合作为轻量补充。另一个重要事实是:本机容器指标采集需要挂载 Docker socket;即使使用只读挂载,socket 仍是敏感的高权限接口,不能把它当作普通日志文件处理。
架构:Hub 保存视图,Agent 采集机器状态
可以把部署理解为两条数据路径:
- 浏览器访问 Hub 的 Web 服务;Hub 保存配置、历史数据并展示仪表盘。
- 每台机器上的 Agent 读取系统与容器信息,再按 Hub 创建系统时生成的连接参数完成注册和通信。
官方同机示例用 Unix socket 让本机 Agent 连接 Hub。这个选择避免了同机 Agent 再经网络端口绕行,也意味着在 Web UI 添加该系统时,Host / IP 应填写 /beszel_socket/beszel.sock,而不是猜测一个 TCP 地址。
用官方 Compose 跑通第一台机器
先在 Linux 主机准备一个专用目录:
mkdir -p ~/beszel cd ~/beszel
创建 compose.yml。下面的服务、镜像、卷、socket 路径与环境变量来自 Beszel 官方同机 Compose 示例;TOKEN 与 KEY 故意保留为空占位,不能自行编造。
services:
beszel:
image: henrygd/beszel:latest
container_name: beszel
restart: unless-stopped
environment:
APP_URL: http://localhost:8090
ports:
- 8090:8090
volumes:
- ./beszel_data:/beszel_data
- ./beszel_socket:/beszel_socket
beszel-agent:
image: henrygd/beszel-agent:latest
container_name: beszel-agent
restart: unless-stopped
network_mode: host
volumes:
- ./beszel_agent_data:/var/lib/beszel-agent
- ./beszel_socket:/beszel_socket
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LISTEN: /beszel_socket/beszel.sock
HUB_URL: http://localhost:8090
TOKEN:
KEY: ""
先启动服务:
docker compose up -d docker compose ps
随后在浏览器打开 http://<服务器地址>:8090,完成 Hub 的首次初始化。在 UI 中创建系统时,按官方说明复制该系统生成的 public key 和 token,分别替换 Compose 中的 KEY、TOKEN,然后再次执行:
docker compose up -d
此时为本机系统填写 Unix socket 路径 /beszel_socket/beszel.sock。如果系统未上线,优先看两项:占位符是否已替换为 UI 生成的实际值,以及容器是否真的重建并读取了新环境变量。不要把 token 或私钥贴进工单、聊天记录,更不要提交到 Git;若要版本管理 Compose,建议把凭据移到未纳入版本控制的 env 文件或部署系统的 secret 管理中。
把“能打开面板”变成可验证的监控闭环
部署完成后,别只看首页是否出现。先用以下命令确认两个容器都处于预期状态:
docker compose ps docker compose logs --tail=100 beszel-agent
然后在 Hub 中检查该系统是否开始产生 CPU、内存、磁盘、网络与容器历史数据。第一次观察至少要覆盖一个完整业务周期,例如白天的批量任务、夜间备份或定时同步。这样才有基线可以对比:某容器的内存曲线是否持续爬升、磁盘写入是否只在备份窗口出现、负载高峰是否与某个容器同步。
告警不要一开始就为所有指标设很低的静态阈值。更可靠的顺序是先看历史趋势,再为明确风险设置门槛:磁盘可用空间、关键容器停止、持续高负载,通常比一次短暂 CPU 尖峰更值得优先通知。若机器具备相关硬件与权限,也可以继续按官方文档配置 GPU、传感器或 S.M.A.R.T. 数据;这些能力应以目标主机实际支持情况为准,不能因为面板提供入口就假定每台服务器都会出现。
四个容易被忽略的运维边界
第一,APP_URL 不是装饰项。 官方环境变量文档说明它用于邮件和通知中的 Hub 链接;如果日后经反向代理或子路径提供服务,应相应设置正确的外部访问 URL,避免通知跳回不可访问的本地地址。
第二,network_mode: host 要按主机网络模型评估。 官方同机样例使用它,但这会让 Agent 采用宿主机网络命名空间。部署前应确认端口规划和防火墙策略,不要以为容器存在就天然隔离了网络暴露面。
第三,只读 socket 不是低风险 socket。 /var/run/docker.sock:/var/run/docker.sock:ro 降低了写入需求,却仍允许读取 Docker API 所暴露的元数据。在共享主机上,应限制谁能改动 Compose 文件、谁能访问 Hub 管理账号,并避免把监控服务放在不受信任的租户边界里。
第四,监控自身也需要备份与升级策略。 beszel_data 保存 Hub 数据,升级镜像前应先备份这个持久化目录;生产环境更适合固定验证过的镜像版本,再安排升级窗口,而不是长期无审查地追随 latest。官方文档也提供自动备份和 S3 兼容存储相关配置,可按现有备份体系选择。
从第一台到多台:不要复制错误的连接方式
本机示例的 Unix socket 只适用于 Hub 与 Agent 同机。添加第二台机器时,应改走官方 Agent 安装与系统注册流程,让远程 Agent 使用该系统对应的 Hub URL、public key 与 token;不要把本机的 /beszel_socket/beszel.sock 复制到远程主机。远程连接还应先处理 TLS、Hub 可达性和防火墙,只允许必要通信路径。
这也是 Beszel 最有价值的地方:先用一台 Hub 收拢多个原本分散的“瞬时视图”,再用历史曲线与有节制的告警缩短定位时间。它不会替你修复容器内存泄漏或即将故障的磁盘,但能让这些问题从“偶然看到”变成“有时间线、有责任边界、可复查”的运维事件。
一个可复现的排障练习:为趋势建立证据
首次部署当天,不妨挑选一个非关键容器做一次短时、可撤销的负载练习,而不是立刻等待真实故障。目标不是制造性能事故,而是验证“采集、显示、告警、复盘”这条链路是否贯通。例如,在确认测试环境可承受的前提下,先记录容器空闲时的 CPU、内存和网络基线;再运行一段已有的测试任务;最后回到系统页面确认曲线能够区分两个时间段。
排障时应把面板数据与容器事实分开验证。Beszel 负责告诉你哪一段时间出现了资源变化,Docker 负责让你进一步确认当时有哪些容器和日志。下面两条命令是 Docker Compose 的常规观察方式,不依赖 Beszel 的私有 CLI:
docker compose ps docker compose logs --since 30m --tail=200
如果曲线显示内存持续抬升,但日志没有明显错误,不要马上把它定性为泄漏。还要对照发布记录、定时任务、缓存预热和流量变化;如果只有某一次部署后开始抬升,才更值得把镜像版本、配置差异和请求模式纳入调查。反过来,若容器重启造成指标归零,历史曲线可以帮助区分“正常滚动发布”与“异常反复退出”。
最小化上线清单
在把 Hub 交给日常使用之前,建议逐项完成以下检查:
- 访问面:不要直接把 8090 管理端口裸露在公网。优先放在 VPN、受限内网或已配置 HTTPS 与访问控制的反向代理之后。
- 凭据面:创建系统后生成的 token 与 public key 只保存在部署密钥管理位置;轮换凭据时,更新 Agent 后立即检查它能重新上线。
- 数据面:确认
beszel_data已纳入备份。恢复演练至少应验证备份文件能被读取,而不是只看到备份任务显示成功。 - 告警面:先给磁盘空间和关键服务离线等高信号事件设通知,再逐步增加阈值;没有明确处理人的告警只会制造噪声。
- 变更面:升级前导出或备份数据目录,记录当前镜像版本与 Compose 文件变更;升级后重复检查系统上线和历史数据是否连续。
完成这些动作后,Beszel 才不只是一个“好看的服务器页面”,而成为轻量但可操作的观测入口:异常出现时先定位范围,再用系统日志和业务指标寻找原因,而不是从 SSH 登录和临时命令开始盲猜。