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)实测。

BeszelBeszel监控Docker2026/10/17

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/beszelHub(仪表盘/API/存储/告警)47.1 MB必需,全局 1 个
henrygd/beszel-agentAgent(指标采集)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_ed25519Hub 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 节逐项说明互为索引):

参数位置实测值调整影响
imagehub/agenthenrygd/beszel:latest / henrygd/beszel-agent:latest生产建议固定版本标签(2.2 节)
container_namehub/agentbeszel-0.21.0-hub / beszel-0.21.0-agent固定名便于日志与排障;改名后 docker logs 需用新名
restarthub/agentunless-stopped开机自启 + 崩溃拉起(技术拓展见 4.1 节)
ports(Hub)hub8090:8090改宿主端口只需改左值,如 18090:8090
ports(Agent)agent45876:45876与 PORT 环境变量、节点端口三处一致
volumes(Hub)hub/opt/data/beszel:/beszel_data全部持久化状态所在,路径变更需迁移旧数据
volumes(docker.sock)agent只读提供本机 Docker 统计采集能力,删除后 Docker 统计功能消失
volumes(sys-sensors)agent只读温度采集目录,配合 SYS_SENSORS 使用
KEYagentHub 公钥换 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;真机(裸金属)一般无需任何配置即可显示。

十二、参考链接