Beszel Docker Compose 部署指南
用 Docker Compose 从零部署 Beszel(Hub+Agent):镜像选型、compose.yml 逐项解读、管理员初始化、节点接入、数据持久化 down/up 实测、等价 docker run 与常用运维命令——全部步骤已在 Ubuntu 22.04(Docker 29.8.1,Beszel 0.21.0)实测。
Beszel Docker Compose 部署指南
目标:用 Docker Compose 从零部署 Beszel 监控平台(Hub + Agent 双服务),完成管理员初始化、被监控节点接入与指标上报验证——全流程已在 Ubuntu 22.04 服务器(Docker 29.8.1 + Compose v5.5.1,Beszel 0.21.0)实测通过,文中所有命令输出均为实测原文。
一、环境信息
本文所有部署与验证在以下环境完成(数据采集时间 2026-10-17):
- 操作系统:Ubuntu 22.04.4 LTS(x86_64)
- Docker Engine:29.8.1(
docker --version实测) - Docker Compose:v5.5.1(
docker compose version实测) - Beszel Hub:henrygd/beszel:latest(实测为 0.21.0,47.1 MB)
- Beszel Agent:henrygd/beszel-agent:latest(实测为 0.21.0,15.5 MB)
- 端口规划:Hub 8090(Web/仪表盘/API)、Agent 45876(SSH 监听)
- 编排文件目录:
/opt/data/beszel-lab(compose.yml、.env) - 数据目录:
/opt/data/beszel(挂载到 Hub 容器内/beszel_data)
版本核对方法(部署完成后随时复查):
# 查看本机 Docker 与 Compose 版本
docker --version && docker compose version
实测输出:
Docker version 29.8.1, build 4a63305
Docker Compose version v5.5.1
# Hub 版本:调用信息接口($TOKEN 为管理员登录返回的认证 Token,获取方式见 4.3 节)
curl -s http://localhost:8090/api/beszel/info -H "Authorization: $TOKEN"
实测输出:
{"key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j","v":"0.21.0","cu":false}
v 字段即 Hub 实际运行版本,本文环境为 0.21.0。
二、镜像选型说明
2.1 官方镜像与体积
Beszel 官方在 Docker Hub 发布两个镜像,分别对应 Hub(服务端)与 Agent(采集端),均为 Go 静态编译的单二进制镜像,体积非常小:
# 查看本机已拉取的 Beszel 镜像与摘要
docker images --digests 'henrygd/*' --format '{{.Repository}}:{{.Tag}} {{.Digest}} {{.Size}}'
实测输出:
henrygd/beszel-agent:latest sha256:f27b1aa2c68404bc5b9e1a2ab36653bd9b4ee14f6299862f09cd5051a4134767 15.5MB
henrygd/beszel:latest sha256:6b39a8b64f9b15d00a25e7683e31a93c46161182a54f62713525107064e10599 47.1MB
Hub 镜像内 ENTRYPOINT 为 /beszel、默认 CMD 为 serve --http=0.0.0.0:8090;Agent 镜像内 ENTRYPOINT 为 /agent(docker inspect 实测)。两镜像均为单进程静态二进制,无运行时依赖,这是 Beszel 资源占用低的直接原因(Hub 常驻约 13 MiB、Agent 约 9 MiB 实测)。
2.2 版本标签与固定建议
官方镜像以语义化版本发布标签(如 henrygd/beszel:v0.21.0),latest 跟随最新版。本文实测时 latest 即 0.21.0。生产环境建议把镜像标签固定到具体版本号,升级时按《Beszel 运维手册》的升级流程显式变更标签后重建,避免 latest 漂移导致各节点版本不一致。
💡 说明:通过国内镜像加速源拉取非
latest版本标签时,可能遇到加速源未同步该标签返回denied的情况(本文实测出现过,见 11.5 节),重试或直连 Docker Hub 即可。
2.3 镜像选型结论
| 镜像 | 角色 | 实测体积 | 是否必需 |
|---|---|---|---|
| henrygd/beszel | Hub(仪表盘/API/存储/告警) | 47.1 MB | 必需,全局 1 个 |
| henrygd/beszel-agent | Agent(指标采集) | 15.5 MB | 每台被监控机器 1 个 |
关键差异:Hub 是唯一的中心服务,负责存储与页面;Agent 只采集不存储。本文采用 Docker Hub 官方镜像 + Compose 编排,这也是官方入门文档推荐形态。
三、前置条件
3.1 服务器与端口
- 一台 Linux 服务器(本文 Ubuntu 22.04)作为 Hub 宿主机;被监控机器上只需运行 Agent。
- Hub 端口 8090 对访问者开放;Agent 端口 45876 需允许 Hub 来源 IP 的入站访问(Hub 主动 SSH 连接 Agent)。
- 部署前确认端口未被占用:
ss -lntp | grep -E ':8090|:45876'
实测输出(本机已在运行,若为空闲机器应无输出):
LISTEN 0 4096 0.0.0.0:8090 0.0.0.0:* users:(("docker-proxy",pid=2673588,fd=8))
LISTEN 0 4096 0.0.0.0:45876 0.0.0.0:* users:(("docker-proxy",pid=2673484,fd=8))
LISTEN 0 4096 [::]:8090 [::]:* users:(("docker-proxy",pid=2673595,fd=8))
LISTEN 0 4096 [::]:45876 [::]:* users:(("docker-proxy",pid=2673491,fd=8))
3.2 Docker 环境
需要 Docker Engine 20.10+ 与 Docker Compose v2 插件(docker compose 子命令形式)。验证命令与实测输出见第一章。
3.3 目录准备
创建编排目录与数据目录:
mkdir -p /opt/data/beszel-lab /opt/data/beszel
实测无输出(mkdir -p 对新建目录静默成功),用 ls -ld 确认:
ls -ld /opt/data/beszel-lab /opt/data/beszel
实测输出:
drwxr-xr-x 2 root root 4096 Oct 17 19:30 /opt/data/beszel
drwxr-xr-x 2 root root 4096 Oct 17 19:30 /opt/data/beszel-lab
四、部署步骤
本章按真实顺序执行:先写编排文件 → 启动 Hub → 初始化管理员 → 取 SSH 公钥写入 Agent 配置 → 启动 Agent → 添加被监控节点 → 验证上报。
4.1 编写 compose.yml
在 /opt/data/beszel-lab/compose.yml 写入以下内容(双服务 + 专用网络):
services:
hub:
image: henrygd/beszel:latest
container_name: beszel-0.21.0-hub
restart: unless-stopped
ports:
- "8090:8090"
volumes:
- /opt/data/beszel:/beszel_data
networks:
- beszel-net
agent:
image: henrygd/beszel-agent:latest
container_name: beszel-0.21.0-agent
restart: unless-stopped
ports:
- "45876:45876"
environment:
PORT: "45876"
KEY: ${KEY}
SYS_SENSORS: "/sys-sensors"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /opt/data/beszel-lab/sys-sensors:/sys-sensors:ro
networks:
- beszel-net
networks:
beszel-net:
driver: bridge
配置逐项说明(Hub):
image:官方 Hub 镜像,版本策略见第二章;container_name:固定容器名,便于docker logs/docker exec定位;restart: unless-stopped:宿主机重启或进程崩溃时自动拉起,除非手动 stop;ports "8090:8090":宿主机 8090 → 容器 8090,仪表盘与 API 入口;volumes /opt/data/beszel:/beszel_data:数据落盘到宿主机,SQLite 数据库与 SSH 私钥都在这里,删除容器不丢数据;networks:自定义 bridge 网络,Agent 与 Hub 通过容器名互访。
配置逐项说明(Agent):
environment PORT:Agent SSH 监听端口,与ports映射及后续添加节点时填写的端口一致;environment KEY:Hub 的 ed25519 公钥(注意是公钥不是私钥),Agent 用它校验 Hub 身份;值来自.env(见 4.2 与 4.4);environment SYS_SENSORS:指定容器内温度传感器目录,用于受限环境温度采集(详见 8.3 节,不需要温度采集可删除该行及对应挂载);volumes /var/run/docker.sock:ro:只读挂载宿主机 Docker 套接字,Agent 借此采集本机全部 Docker 统计对象(CPU/内存/网络),只读权限避免反向操作 Docker;ports "45876:45876":Agent SSH 监听端口暴露给 Hub。
💡 技术拓展:
restart策略不止unless-stopped一种。四种策略对比——
策略 行为 适用场景 no(默认) 不自动重启 调试、一次性任务 on-failure[:N] 仅非零退出时重启,最多 N 次 可能预期内失败的任务 always 总是重启(含守护进程重启后) 需要开机自启的常驻服务 unless-stopped 总是重启,但手动 stop 后不再拉起 生产常驻服务的通用选择 本文采用
unless-stopped:既能随宿主机自启,又保留手动维护停机的意图。
💡 技术拓展:容器网络驱动不止
bridge一种。常见驱动对比——
驱动 特点 适用场景 bridge(默认) 宿主机内虚拟网桥 + NAT,端口映射进出 单机多容器互通(本文场景) host 容器直接用宿主机网络栈,无端口映射 追求极致网络性能 macvlan 容器获得独立 MAC/局域网 IP 需要在局域网内可见的设备 overlay 跨宿主机隧道网络 多机 Swarm/K8s 集群 本文 Hub 与 Agent 同机部署,用默认
bridge即可;若 Agent 部署在其他机器,则无需同一网络,Hub 通过「宿主机 IP:45876」连接即可。
4.2 编写 .env(KEY 占位与注入)
Agent 的 KEY 值通过同目录 .env 注入(这也是官方 Compose 模板的做法),本节先建立文件,真实公钥在 4.4 步从 Hub 读取后回填:
# 先写入空值占位,4.4 步回填
echo 'KEY=' > /opt/data/beszel-lab/.env
4.4 步完成后 .env 实际内容(KEY 为 Hub 生成的 ed25519 公钥,公钥非机密,可明文存放):
KEY=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j
docker compose 启动时自动读取同目录 .env,把 ${KEY} 解析为上述公钥(解析结果可用 docker compose config 核对,见 4.5 节)。
4.3 启动 Hub 并初始化管理员
首次部署先单独启动 Hub(此时 .env 的 KEY 还未回填,Agent 服务暂不启动也不影响):
cd /opt/data/beszel-lab && docker compose up -d hub
实测输出(首次启动,全新环境):
Network beszel-lab_beszel-net Creating
Network beszel-lab_beszel-net Created
Container beszel-0.21.0-hub Creating
Container beszel-0.21.0-hub Created
Container beszel-0.21.0-hub Starting
Container beszel-0.21.0-hub Started
等待约 5 秒后验证 Hub 已监听:
ss -lntp | grep 8090
实测输出:
LISTEN 0 4096 0.0.0.0:8090 0.0.0.0:* users:(("docker-proxy",pid=2673588,fd=8))
LISTEN 0 4096 [::]:8090 [::]:* users:(("docker-proxy",pid=2673595,fd=8))
初始化管理员账号(演示账号 admin@quzuo.net / q1w2e3r4;页面操作等价于首次打开 http://<服务器IP>:8090 按提示创建,API 等价操作如下):
curl -s -X POST http://localhost:8090/api/beszel/create-user \
-H 'Content-Type: application/json' \
-d '{"email":"admin@quzuo.net","password":"q1w2e3r4","name":"admin"}'
实测输出:
{"msg":"User created"}
登录获取认证 Token(后续 API 命令统一使用;Token 为运行期凭据,实测长度约 224 字符,不落明文):
curl -s -X POST http://localhost:8090/api/collections/users/auth-with-password \
-H 'Content-Type: application/json' \
-d '{"identity":"admin@quzuo.net","password":"q1w2e3r4"}'
实测输出(节选,Token 中段截断):
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...","record":{"id":"egb5322xmdbhc47","email":"admin@quzuo.net","role":"admin","verified":true}}
记录 id(实测 egb5322xmdbhc47)就是后续添加节点的授权用户 ID。把 Token 取到变量,供后续命令复用:
TOKEN=$(curl -s -X POST http://localhost:8090/api/collections/users/auth-with-password \
-H 'Content-Type: application/json' \
-d '{"identity":"admin@quzuo.net","password":"q1w2e3r4"}' \
| python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
验证登录态(输出含 SSH 公钥与版本号即成功):
curl -s http://localhost:8090/api/beszel/info -H "Authorization: $TOKEN"
实测输出:
{"key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j","v":"0.21.0","cu":false}
4.4 获取 SSH 公钥并回填 .env
上一步 info 接口返回的 key 字段就是 Hub 自动生成的 ed25519 公钥(Hub 首次启动时在数据目录生成密钥对 id_ed25519,实测文件 387 字节、权限 600)。把它写入 .env(以 4.3 步实测输出的公钥为例):
echo 'KEY=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j' > /opt/data/beszel-lab/.env
核对数据目录中密钥对与数据库文件已生成:
ls -la /opt/data/beszel/
实测输出(全新 Hub 首启后):
total 976
drwxr-xr-x 3 root root 4096 Oct 17 19:25 .
drwxr-xr-x 3 root root 4096 Oct 17 19:25 ..
-rw-r--r-- 1 root root 4096 Oct 17 19:25 auxiliary.db
-rw-r--r-- 1 root root 32768 Oct 17 19:25 auxiliary.db-shm
-rw-r--r-- 1 root root 24752 Oct 17 19:25 auxiliary.db-wal
-rw-r--r-- 1 root root 4096 Oct 17 19:25 data.db
-rw-r--r-- 1 root root 32768 Oct 17 19:25 data.db-shm
-rw-r--r-- 1 root root 877592 Oct 17 19:25 data.db-wal
-rw------- 1 root root 387 Oct 17 19:25 id_ed25519
drwxr-xr-x 2 root root 4096 Oct 17 19:25 .notify
要点:id_ed25519 是 Hub 连接 Agent 的私钥,丢失或更换后所有 Agent 都会拒绝连接(对应 11.2 节故障),务必纳入备份(见《Beszel 运维手册》备份章节)。
4.5 启动 Agent 并核对解析配置
启动全部服务(Compose 自动带上刚回填的 .env):
cd /opt/data/beszel-lab && docker compose up -d
实测输出:
Container beszel-0.21.0-hub Running
Container beszel-0.21.0-agent Creating
Container beszel-0.21.0-agent Created
Container beszel-0.21.0-agent Starting
Container beszel-0.21.0-agent Started
用 docker compose config 核对 ${KEY} 已被正确解析(节选 Agent 服务部分):
cd /opt/data/beszel-lab && docker compose config
实测输出(节选,Agent 服务段):
agent:
container_name: beszel-0.21.0-agent
environment:
KEY: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j
PORT: "45876"
SYS_SENSORS: /sys-sensors
image: henrygd/beszel-agent:latest
networks:
beszel-net: null
ports:
- mode: ingress
target: 45876
published: "45876"
protocol: tcp
restart: unless-stopped
volumes:
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
read_only: true
bind: {}
- type: bind
source: /opt/data/beszel-lab/sys-sensors
target: /sys-sensors
read_only: true
bind: {}
确认两个服务状态:
cd /opt/data/beszel-lab && docker compose ps
实测输出:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
beszel-0.21.0-agent henrygd/beszel-agent:latest "/agent" agent 2 hours ago Up 2 hours 0.0.0.0:45876->45876/tcp, [::]:45876->45876/tcp
beszel-0.21.0-hub henrygd/beszel:latest "/beszel serve --htt…" hub 3 hours ago Up 2 hours 0.0.0.0:8090->8090/tcp, [::]:8090->8090/tcp
再看一眼 Agent 启动日志,确认 SSH 服务与传感器目录就绪:
docker logs beszel-0.21.0-agent 2>&1 | head -6
实测输出:
2026/10/17 08:27:50 INFO Data directory path=/var/lib/beszel-agent
2026/10/17 08:27:50 INFO SYS_SENSORS path=/sys-sensors
2026/10/17 08:27:50 INFO Detected disk name=sda3 device=sda3 mount=/etc/hostname io=sda3 root=true
2026/10/17 08:27:50 INFO Detected network interface name=eth0 sent=42 recv=110
2026/10/17 08:27:50 INFO Starting SSH server addr=:45876 network=tcp
2026/10/17 08:28:45 INFO SSH connected addr=172.31.0.2:45290
4.6 添加被监控节点(System)
在页面点 Add System,Host 填 Agent 地址(同机部署填 agent 即容器名,跨机填对方 IP)、Port 填 45876。API 等价操作:
curl -s -X POST http://localhost:8090/api/collections/systems/records \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"beszel-agent-node1","host":"agent","port":"45876","users":["egb5322xmdbhc47"]}'
实测输出:
{"id":"u3q4gtml3pv3us0","name":"beszel-agent-node1","host":"agent","port":"45876","status":"pending"}
users 填 4.3 步登录返回的记录 id(实测 egb5322xmdbhc47),表示该节点的授权可见用户。刚创建时状态为 pending,Hub 会在约 8 秒内完成首次 SSH 握手并采集首条数据。
4.7 验证指标上报
查询系统状态与最新指标记录:
curl -s "http://localhost:8090/api/collections/systems/records/u3q4gtml3pv3us0?fields=status,info.cpu,info.mp,info.dp" \
-H "Authorization: $TOKEN"
实测输出:
{"status":"up","info":{"cpu":3.22,"mp":27.63,"dp":20.29}}
curl -s "http://localhost:8090/api/collections/system_stats/records?perPage=1&sort=-created" \
-H "Authorization: $TOKEN"
实测输出(节选):
{"items":[{"created":"2026-10-17 08:07:45.616Z","type":"1m",
"stats":{"cpu":3.2,"mu":8.77,"mp":28.02,"du":152.4,"dp":20.3,
"b":[191,62],"la":[1.02,0.85,0.51]}}]}
至此部署闭环完成:状态 up、system_stats 出现 1 分钟粒度记录,打开 http://<服务器IP>:8090 即可看到实时与历史图表。
五、数据持久化说明
5.1 持久化位置
Beszel 的全部持久化状态集中在 Hub 数据目录(挂载自宿主机 /opt/data/beszel):
| 文件 | 作用 | 是否需备份 |
|---|---|---|
data.db(及 WAL 伴生文件) | 主库:系统、指标、告警、用户 | 必需 |
id_ed25519 | Hub SSH 私钥,连接 Agent 的身份凭据 | 必需 |
auxiliary.db | 辅助库 | 建议一并备份 |
.notify/ | 通知相关内部数据 | 建议一并备份 |
Agent 无状态(指标只推不存),容器可随时重建。
5.2 down/up 数据保持实测
对编排执行完整的 down(删容器删网络)再 up(重建),验证数据不丢:
cd /opt/data/beszel-lab && docker compose down
实测输出:
Container beszel-0.21.0-agent Stopping
Container beszel-0.21.0-hub Stopping
Container beszel-0.21.0-agent Stopped
Container beszel-0.21.0-agent Removing
Container beszel-0.21.0-hub Stopped
Container beszel-0.21.0-hub Removing
Container beszel-0.21.0-agent Removed
Container beszel-0.21.0-hub Removed
Network beszel-lab_beszel-net Removing
Network beszel-lab_beszel-net Resource is still in use
⚠️ 注意:最后两行是实测真实输出——
beszel-net网络上还挂着本文 11.2 节排障用的测试 Agent(不在本编排内),Compose 提示网络仍被占用而跳过删除。这正好验证了「down 只清理本编排资源,不碰其他容器」。若网络被无关容器占用导致残留,处理方法见 11.3 节。
确认宿主机数据仍在(WAL 已在正常停止时合并回主库,-wal/-shm 文件消失):
ls -la /opt/data/beszel/ | grep -E 'data.db|id_ed25519'
实测输出:
-rw-r--r-- 1 root root 790528 Oct 17 19:18 data.db
-rw------- 1 root root 387 Oct 17 16:03 id_ed25519
重建:
cd /opt/data/beszel-lab && docker compose up -d
实测输出:
Container beszel-0.21.0-hub Creating
Container beszel-0.21.0-agent Creating
Container beszel-0.21.0-hub Created
Container beszel-0.21.0-agent Created
Container beszel-0.21.0-hub Starting
Container beszel-0.21.0-agent Starting
Container beszel-0.21.0-hub Started
Container beszel-0.21.0-agent Started
验证系统记录与告警历史完好:
TOKEN=$(curl -s -X POST http://localhost:8090/api/collections/users/auth-with-password -H 'Content-Type: application/json' -d '{"identity":"admin@quzuo.net","password":"q1w2e3r4"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
curl -s 'http://localhost:8090/api/collections/systems/records?perPage=10&fields=name,status,info.v' -H "Authorization: $TOKEN" | python3 -c "import sys,json; [print(i['name'], i['status'], i.get('info',{}).get('v')) for i in json.load(sys.stdin)['items']]"
curl -s 'http://localhost:8090/api/collections/alerts/records?perPage=5&fields=name,value,triggered' -H "Authorization: $TOKEN" | python3 -c "import sys,json; d=json.load(sys.stdin); print('alerts total:', d.get('totalItems'))"
实测输出:
beszel-agent-node2 up 0.21.0
beszel-agent-node1 up 0.21.0
alerts total: 1
两个系统记录、版本信息、告警历史全部保留——数据持久化验证通过。
5.3 备份建议
日常请按《Beszel 运维手册》的备份章节执行定时备份(打包数据目录 + 恢复演练),本篇不展开。
六、环境变量表
6.1 Agent 环境变量(本文实测验证过的完整清单)
| 变量 | 必填 | 实测值 | 说明 |
|---|---|---|---|
KEY | 是 | ssh-ed25519 AAAA…8j(Hub 公钥) | Agent 校验 Hub 身份的公钥;与 Hub 数据目录的 id_ed25519 配对。不匹配时 Agent 拒绝连接(11.2 节实测) |
PORT | 否 | 45876(默认值) | Agent SSH 监听端口,需与 ports 映射、添加节点时填写的端口一致 |
SYS_SENSORS | 否 | /sys-sensors(本文指定) | 温度传感器目录;受限环境(虚拟机/容器)通过挂载宿主机 hwmon 目录开启温度采集,实测开启后指标记录出现 t: {"coretemp_package_id_0": 45.5} |
💡 说明:Agent 还支持 TLS 证书等更多环境变量,详见官方文档 https://www.beszel.dev/guide/agent (本文只列实测验证过的项)。
6.2 Hub 侧配置方式
Hub 镜像默认 ENTRYPOINT/CMD 为 /beszel serve --http=0.0.0.0:8090(docker inspect 实测),无需任何环境变量即可工作;监听端口通过 Compose 的 ports 映射调整(如 "18090:8090" 把页面暴露到宿主机 18090)。Hub 的更多配置(OIDC、备份策略等)通过页面后台设置完成,详见官方文档 https://www.beszel.dev/guide/getting-started 。
七、配置参数说明
compose.yml 中的关键参数汇总(与 4.1 节逐项说明互为索引):
| 参数 | 位置 | 实测值 | 调整影响 |
|---|---|---|---|
image | hub/agent | henrygd/beszel:latest / henrygd/beszel-agent:latest | 生产建议固定版本标签(2.2 节) |
container_name | hub/agent | beszel-0.21.0-hub / beszel-0.21.0-agent | 固定名便于日志与排障;改名后 docker logs 需用新名 |
restart | hub/agent | unless-stopped | 开机自启 + 崩溃拉起(技术拓展见 4.1 节) |
ports(Hub) | hub | 8090:8090 | 改宿主端口只需改左值,如 18090:8090 |
ports(Agent) | agent | 45876:45876 | 与 PORT 环境变量、节点端口三处一致 |
volumes(Hub) | hub | /opt/data/beszel:/beszel_data | 全部持久化状态所在,路径变更需迁移旧数据 |
volumes(docker.sock) | agent | 只读 | 提供本机 Docker 统计采集能力,删除后 Docker 统计功能消失 |
volumes(sys-sensors) | agent | 只读 | 温度采集目录,配合 SYS_SENSORS 使用 |
KEY | agent | Hub 公钥 | 换 Hub 重装时必须同步更新(11.2 节) |
networks | 全部 | 自定义 beszel-net(bridge) | 同网络内容器名互访;跨机部署不共享网络 |
八、配置文件挂载
8.1 Docker 套接字(Docker 统计功能的来源)
Agent 只读挂载 /var/run/docker.sock 后自动上报本机全部 Docker 统计对象。实测本机 30 个对象全部入库(0.21.0 起 Docker 统计存入独立 container_stats 集合,每分钟一条记录):
[{"n":"onedev-16.9.3-restore","c":0.05,"m":618.24},
{"n":"umami-16-db","c":0.06,"m":30.78,"b":[1,3]},
{"n":"beszel-0.21.0-agent","c":0,"m":9.42,"b":[78,18]}]
(输出节选,实测原文共 30 项、此处取首尾;n 名称 / c CPU% / m 内存 MB / b 网络 KB/s 收发。)
8.2 数据目录
见 5.1 节。挂载方式为宿主机目录 bind mount,路径即真实数据位置,备份恢复直接面向该目录操作。
8.3 温度传感器目录(受限环境开启温度采集)
虚拟机/容器内通常没有 hwmon 设备,Agent 默认无温度项。本文通过把宿主机传感器目录挂载进来并设置 SYS_SENSORS 开启:
environment:
SYS_SENSORS: "/sys-sensors"
volumes:
- /opt/data/beszel-lab/sys-sensors:/sys-sensors:ro
实测开启后指标记录出现温度字段(来自宿主机 coretemp 传感器):
{"t":{"coretemp_package_id_0":45.5}}
不需要温度采集时,删除该环境变量与对应挂载即可,不影响其他指标。
九、等价 docker run
不用 Compose 时,以下命令与 4.1 节 compose.yml 等价(参数一一对应):
# 1. 创建专用网络
docker network create beszel-net
# 2. 启动 Hub(数据目录挂载 + 端口映射 + 重启策略)
docker run -d \
--name beszel-0.21.0-hub \
--restart unless-stopped \
--network beszel-net \
-p 8090:8090 \
-v /opt/data/beszel:/beszel_data \
henrygd/beszel:latest
# 3. 启动 Agent(KEY 用 Hub 公钥,docker.sock 只读挂载)
docker run -d \
--name beszel-0.21.0-agent \
--restart unless-stopped \
--network beszel-net \
-p 45876:45876 \
-e PORT=45876 \
-e KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j" \
-e SYS_SENSORS=/sys-sensors \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v /opt/data/beszel-lab/sys-sensors:/sys-sensors:ro \
henrygd/beszel-agent:latest
等价性依据:docker compose config 渲染出的最终配置(4.5 节实测)与上述 -p/-v/-e/--restart/--network 参数逐项一致。验证方式相同:docker compose ps 换成 docker ps、查看 8090 页面与 info 接口。
💡 说明:单机双服务场景推荐 Compose(一键启停、配置可版本化);
docker run方式适合临时验证或与既有脚本集成。跨机部署 Agent 时,把第 3 步放到目标机器执行,--network一行删除、Hub 用宿主机 IP 连接即可。
十、常用运维命令
以下命令均在本文环境实测(cd /opt/data/beszel-lab 后执行):
# 查看服务状态
docker compose ps
实测输出:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
beszel-0.21.0-agent henrygd/beszel-agent:latest "/agent" agent 2 hours ago Up 2 hours 0.0.0.0:45876->45876/tcp, [::]:45876->45876/tcp
beszel-0.21.0-hub henrygd/beszel:latest "/beszel serve --htt…" hub 3 hours ago Up 2 hours 0.0.0.0:8090->8090/tcp, [::]:8090->8090/tcp
# 查看日志(实时跟踪加 -f)
docker compose logs hub --tail 3
实测输出:
beszel-0.21.0-hub | 2026/10/17 11:19:18 Server started at http://0.0.0.0:8090
beszel-0.21.0-hub | ├─ REST API: http://0.0.0.0:8090/api/
beszel-0.21.0-hub | └─ Dashboard: http://0.0.0.0:8090/_/
# 重启单个服务
docker compose restart hub
实测输出:
Container beszel-0.21.0-hub Restarting
Container beszel-0.21.0-hub Started
# 停止(保留容器)
docker compose stop
实测输出:
Container beszel-0.21.0-agent Stopping
Container beszel-0.21.0-hub Stopping
Container beszel-0.21.0-agent Stopped
Container beszel-0.21.0-hub Stopped
停止后验证 8090 已不可达(连接被拒,curl 无回显返回):
curl -s --max-time 3 http://localhost:8090/api/beszel/info
实测输出:空(无任何回显)。
# 再次启动
docker compose start
实测输出:
Container beszel-0.21.0-hub Starting
Container beszel-0.21.0-agent Starting
Container beszel-0.21.0-hub Started
Container beszel-0.21.0-agent Started
# 拉取新镜像(升级第一步,配合运维手册升级流程使用)
docker compose pull
实测输出:
Image henrygd/beszel-agent:latest Pulling
Image henrygd/beszel:latest Pulling
Image henrygd/beszel:latest Pulled
Image henrygd/beszel-agent:latest Pulled
# 强制重建容器(镜像更新后应用变更;数据在宿主机目录不受影响)
docker compose up -d --force-recreate
实测输出:
Container beszel-0.21.0-hub Recreated
Container beszel-0.21.0-agent Recreated
Container beszel-0.21.0-agent Starting
Container beszel-0.21.0-hub Starting
Container beszel-0.21.0-agent Started
Container beszel-0.21.0-hub Started
重建后核对版本与数据完好(实测 v 仍为 0.21.0、系统记录与告警历史保留,命令见 5.2 节)。
十一、常见问题(FAQ)
Q1:访问 /api/beszel/info 返回 401?
0.21.0 实测该接口必须携带认证 Token。未带 Token 的回显:
{"data":{},"message":"The request requires valid record authorization token.","status":401}
解决:先按 4.3 节登录拿 $TOKEN,请求加 -H "Authorization: $TOKEN"。
Q2:系统状态一直是 down,Agent 日志出现 Invalid SSH key?
这是 Agent 端 KEY 与 Hub 公钥不匹配(Hub 重装/换数据目录后常见)。实测复现:给测试 Agent 配置一把错误公钥并添加节点,约 60 秒后 Agent 日志出现:
2026/10/17 11:17:03 WARN Invalid SSH key addr=172.31.0.2:48742
Hub 侧系统状态保持 down。解决:从 Hub 的 info 接口(4.4 节)或页面 Add System 弹窗重新复制公钥,更新 .env 的 KEY 后 docker compose up -d agent 重建 Agent;Agent 端实测恢复日志:
2026/10/17 08:28:45 INFO SSH connected addr=172.31.0.2:45290
Q3:docker compose down 报 Network ... Resource is still in use?
网络上有不属于本编排的容器在用(本文 5.2 节实测复现)。处理:docker network inspect <网络名> 找到占用容器后逐一 docker stop 或 docker network disconnect,或保留网络只做 docker compose stop。Compose 的这一保护行为是预期设计,不会误删其他容器的网络。
Q4:Hub 日志出现 Error getting container stats?
个别 Docker 统计对象的瞬态错误,实测出现过三类:
ERROR Error getting container stats err="infallible_lichterman - bad memory stats - see https://github.com/henrygd/beszel/issues/144"
ERROR Error getting container stats err="container stats request failed: 404 Not Found"
WARN Bad network delta container=surreal-curl-helper
第一条对应内核未给某容器提供有效 memory 统计(cgroup 差异,官方 issue #144),第二条对应统计瞬间容器已退出的竞态。均不影响其他对象的采集——实测同时刻 Docker 统计仍有 30 个对象正常入库(8.1 节)。无需处理,日志可忽略。
Q5:docker pull 报 denied 或 502?
镜像加速源未同步目标标签或临时限流。本文实测:拉 v0.21.0 标签时加速源返回
Error response from daemon: error from registry: denied
而数分钟后拉 latest 成功(10 节 docker compose pull 输出)。解决:重试、更换加速源或直连 Docker Hub。
Q6:页面没有温度数据?
宿主机有 hwmon 传感器但运行环境内看不到时,按 8.3 节挂载传感器目录并设置 SYS_SENSORS;真机(裸金属)一般无需任何配置即可显示。
十二、参考链接
- 官方入门指南:https://www.beszel.dev/guide/getting-started
- Agent 配置(环境变量):https://www.beszel.dev/guide/agent
- GitHub 仓库:https://github.com/henrygd/beszel
- Docker Hub:https://hub.docker.com/r/henrygd/beszel
- 日常巡检/备份/升级/排障:见《Beszel 运维手册》
- 架构与选型说明:见《Beszel 介绍与选型指南》
- 相关文档:《Uptime Kuma Docker Compose 部署指南》《Prometheus 3.x Docker Compose 部署指南》《Grafana Docker Compose 部署指南》