OneUptime Docker Agent 部署与运维完全指南:一条命令接入 Docker 主机遥测监控
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
本指南围绕 OneUptime 开源仓库中的 Docker Agent 展开,讲解如何用一条命令部署一个预配置的 OpenTelemetry Collector 容器,自动发现宿主机上的全部 Docker 容器,采集 CPU、内存、网络、块 I/O 指标与容器日志,并通过 OTLP 协议汇入 OneUptime 平台。读完本文,你将掌握 Docker Agent 的快速部署、环境变量调优、升级卸载、日志严重性推导原理以及常见故障排查,可直接在生产 Docker 主机上落地使用。
OneUptime Docker Agent 是什么
OneUptime Docker Agent 是一个预构建的容器镜像(oneuptime/docker-agent),镜像内打包了一份经过调优的 OpenTelemetry Collector 配置。把它与现有容器一起运行在同一宿主机上,它会自动完成以下工作:
- 自动发现宿主机上的每个容器;
- 采集容器的CPU / 内存 / 网络 / 块 I/O 指标;
- 采集容器日志(stdout/stderr);
- 将指标与日志统一通过OTLP协议转发到 OneUptime。
从镜像构建层面看,该镜像基于otel/opentelemetry-collector-contrib:0.154.0构建(见 DockerAgent/Dockerfile.tpl),将预调优的 DockerAgent/otel-collector-config.yaml 烘焙进/etc/otelcol-contrib/config.yaml,并在启动时通过环境变量注入(${ONEUPTIME_URL}、${ONEUPTIME_SERVICE_TOKEN}等)。因此用户只需要“一个镜像、一个命令、几个环境变量”。
容器启动时,入口脚本 DockerAgent/entrypoint.sh 会在后台启动一个库存快照轮询器(inventory poller),然后以前台方式exec启动 OTel Collector——Collector 是受监督的主进程,一旦退出容器即重启。
本文是安装指南。如需基于 Agent 采集到的数据配置 Docker 监控器与告警通知,参见 Docker Monitor(Docker 监控器配置文档)。
前置条件
部署前请确认满足以下条件:
- Docker Engine 20.10+(宿主机);
- 可以访问宿主机上的
/var/run/docker.sock(Docker 套接字); - 拥有一个OneUptime Telemetry Ingestion Token(遥测摄取令牌)——在 OneUptime 控制台的项目设置 → 遥测与 APM → Ingestion 密钥中创建,并复制其值。
需要特别注意的是:Agent 通过挂载 Docker 套接字获取容器元数据与指标,通过挂载/var/lib/docker/containers目录读取容器日志文件,因此两个卷都是必需的。
快速开始(单命令部署)
将YOUR_ONEUPTIME_URL、YOUR_TELEMETRY_INGESTION_TOKEN和主机名替换为你的环境值。主机名(DOCKER_HOST_NAME)是此 Docker 主机在 OneUptime 中显示的名称,建议取一个有业务含义的名字,如prod-docker-01:
docker run -d \ --name oneuptime-docker-agent \ --user 0:0 \ --restart unless-stopped \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /var/lib/docker/containers:/var/lib/docker/containers:ro \ -e ONEUPTIME_URL="YOUR_ONEUPTIME_URL" \ -e ONEUPTIME_SERVICE_TOKEN="YOUR_TELEMETRY_INGESTION_TOKEN" \ -e DOCKER_HOST_NAME="my-docker-host" \ oneuptime/docker-agent:release就这些。Agent 建立连接后,你的 Docker 主机将自动出现在 OneUptime 控制台的 Docker 区域中,无需手动注册。
关于上述命令的几个关键点,可从源码得到印证:
--user 0:0:必须以 root 运行才能访问/var/run/docker.sock。基础镜像默认的非 root 用户(UID 10001)在大多数主机上无法读取套接字与容器日志目录(见 DockerAgent/Dockerfile.tpl 中的USER 0:0)。-v ...:ro:两个卷均以只读方式挂载,Agent 只读不写宿主机状态。--restart unless-stopped:保证 Agent 随 Docker 守护进程自愈重启。
镜像标签
| 标签 | 说明 |
|---|---|
oneuptime/docker-agent:release | 最新稳定版(社区版) |
oneuptime/docker-agent:enterprise-release | 最新稳定版(企业版) |
oneuptime/docker-agent:<version> | 固定版本,例如10.0.31 |
ghcr.io/oneuptime/docker-agent:release | 同一镜像在 GHCR 的镜像副本 |
以上标签说明见 DockerAgent/README.md。
替代方案:Docker Compose 部署
如果偏好 Docker Compose,将以下内容写入docker-compose.yml:
services: oneuptime-docker-agent: image: oneuptime/docker-agent:release container_name: oneuptime-docker-agent user: "0:0" restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro environment: - ONEUPTIME_URL=YOUR_ONEUPTIME_URL - ONEUPTIME_SERVICE_TOKEN=YOUR_TELEMETRY_INGESTION_TOKEN - DOCKER_HOST_NAME=my-docker-host logging: driver: json-file options: max-size: "10m" max-file: "3"启动:
docker compose up -d仓库自带的 DockerAgent/docker-compose.yml 展示了同样的结构,并在注释中特别说明了一个易错点:DOCKER_API_VERSION=${DOCKER_API_VERSION-1.44}使用的是${VAR-default}而非${VAR:-default}写法,目的是保留“空字符串”这一逃生通道——若用冒号写法,显式传入的空值会被默认值吞掉。
环境变量详解
| 变量 | 是否必需 | 说明 |
|---|---|---|
ONEUPTIME_URL | 是 | 你的 OneUptime 实例 URL(例如https://oneuptime.com或自托管地址) |
ONEUPTIME_SERVICE_TOKEN | 是 | 来自项目设置 → 遥测与 APM → Ingestion 密钥的 Telemetry Ingestion Token |
DOCKER_HOST_NAME | 否 | 该主机的可读名称,默认值为docker-host。建议为每台主机设置稳定值(如prod-docker-01) |
DOCKER_API_VERSION | 否 | Agent 使用的 Docker Engine API 版本,默认1.44。旧版守护进程主机上应下调,或设为空字符串以自动协商(见故障排查) |
源码视角:DOCKER_API_VERSION 的底层行为
在 DockerAgent/otel-collector-config.yaml 中,docker_statsreceiver 的api_version直接绑定该环境变量:
receivers: docker_stats: endpoint: unix:///var/run/docker.sock api_version: "${env:DOCKER_API_VERSION}" collection_interval: 30s配置中特意使用plain ${env:...}而非${env:...:-1.44},原因是 confmap 的:-默认值只在变量未设置时生效,无法捕获 Compose 注入的空字符串;而未设置时本来就会退化为自动协商,那反而是更安全的行为。
该 receiver 在 0.154.0 版本下的行为(配置注释中已验证):
- 守护进程会拒绝比其自身最大版本更新的客户端(报错
client version 1.44 is too new),且被拒绝的 receiver 启动失败会拖垮整个 Collector; - 将
api_version留空是安全而非损坏的:receiver 会请求 Docker SDK 自动协商(先发一次HEAD /_ping,然后采用守护进程自身的最大版本),兼容新旧任何守护进程。
源码视角:被显式开启的指标
docker_statsreceiver 中还有一组默认关闭、必须显式开启的指标,因为 OneUptime 的 Docker 监控器告警模板依赖它们(容器重启次数、运行时长、PID 数、CPU 节流):
metrics: container.cpu.utilization: enabled: true container.cpu.throttling_data.throttled_periods: enabled: true container.cpu.throttling_data.throttled_time: enabled: true container.memory.percent: enabled: true container.pids.count: enabled: true container.restarts: enabled: true container.uptime: enabled: true验证安装
检查 Agent 是否运行:
docker ps --filter name=oneuptime-docker-agent查看 Agent 日志:
docker logs -f oneuptime-docker-agent重点关注日志中的这一行就绪标记:
"Everything is ready. Begin running and processing data."看到该行后,通常一分钟内,主机就会出现在 OneUptime 控制台中,指标与日志开始流入。
Agent 更新与卸载
更新(docker run 方式)
docker pull oneuptime/docker-agent:release docker rm -f oneuptime-docker-agent # 重新执行上面的 docker run 命令更新(Docker Compose 方式)
docker compose pull docker compose up -d卸载(docker run 方式)
docker rm -f oneuptime-docker-agent卸载(Docker Compose 方式)
docker compose down仓库说明(DockerAgent/README.md)还提供了本地构建镜像的方法(用于开发或离线环境):在仓库根目录执行
npm run prerun生成 Dockerfile,再docker build -f ./DockerAgent/Dockerfile -t oneuptime/docker-agent:local .。
Agent 收集哪些数据
下表汇总了 Agent 采集的数据类别:
| 类别 | 数据 |
|---|---|
| CPU 指标 | 总用量、使用百分比、节流(throttling)时间(按容器) |
| 内存指标 | 使用量、限制、百分比、RSS、Cache(按容器) |
| 网络指标 | 接收/发送的字节数与数据包数(按容器) |
| 块 I/O 指标 | 读/写的字节数与操作次数(按容器) |
| 容器信息 | 运行时长(uptime)、重启次数、进程数 |
| 容器日志 | 所有容器的 stdout/stderr 日志 |
在 DockerAgent/README.md 中可以找到这些指标对应的 OpenTelemetry 指标名:
- CPU:
container.cpu.usage.total、container.cpu.percent、container.cpu.throttling_data.throttled_time - 内存:
container.memory.usage.total、container.memory.usage.limit、container.memory.percent - 网络:
container.network.io.usage.rx_bytes、container.network.io.usage.tx_bytes - 块 I/O:
container.blockio.io_service_bytes_recursive.read、container.blockio.io_service_bytes_recursive.write - 容器信息:
container.uptime、container.restarts、container.pids.count
容器日志的处理链路
日志通过filelogreceiver 从/var/lib/docker/containers/*/*-json.log读取,并经过一串操作符(operators)处理(见 DockerAgent/otel-collector-config.yaml):
- json_parser:解析 Docker JSON 日志信封,提取时间戳;
- regex_parser:从文件路径中提取容器 ID,并提升为
resource.container.id,用于与 docker_stats 指标关联; - move:把
log字段移动到body、把stream移动到log.iostream; - recombine:把同一容器日志文件中连续的多行记录合并为一条(处理多行堆栈信息,如 Node.js 异常栈帧),
source_identifier防止不同容器的记录被错误合并; - severity 推导链(router → regex_parser → add 兜底 → severity_parser → remove);
- 日志以原生 OpenTelemetry 日志记录格式发出,
severityText、severityNumber、body、attributes、traceId、spanId字段全部填充。
日志严重性(severity)推导机制
Docker 的 json-file 日志驱动本身不记录严重级别,因此 Agent 必须自行推导。其策略是:优先从日志行正文中读取级别关键字,读取不到时才回退到 stdout/stderr 流(stderr → ERROR,stdout → INFO)。
级别关键字只有在符合以下两种“真正的级别位置”时才被采信(详见配置注释与 Tests/Ops/ContainerAgentLogSeverity.test.js 中的语料库):
- 行首前导(LINE PREAMBLE):关键字位于记录首行,其前全部是标点、数字或以结构化分隔符(
.]=-:/|)}等)结尾的词元。例如[ERROR] ...、Monolog 的app.INFO: ...、2026-08-31 07:25:04 INFO ...、logfmt 的level=error ...。普通叙述性文本不算前导——Connection error, retrying会在Connection处被截停,不会误判。 - 级别字段(LEVEL FIELD):关键字是行内 level 类键(
level/lvl/severity/severity_text/levelname/log.level/log_level)的值,无论是否加引号、以:或=分隔。例如 zap/logrus 的{"level":"info"}以及 logfmt 的非首字段级别。
这套推导链的边界行为(均由测试锁定):
- 普通消息顺带提及"error"、"panic" 等词不会被采信(如
{"status":"ok","error":null}仍是 Info,Recovered from panic不会变成 Fatal); - 前导级别优先于行内级别字段;
- 支持 PSR-3 全部八个级别(含
ALERT、EMERGENCY),nginx 的[emerg]也映射到 Fatal; - 配置中的
mapping:块补充了 stanza 内置 preset 不认识的别名(notice/crit/critical/panic/alert/emerg/emergency)。
库存快照(Inventory)
除了指标与日志,Agent 还通过 DockerAgent/inventory-snapshot.sh 每 300 秒(可通过DOCKER_INVENTORY_INTERVAL_SECONDS调整)轮询一次 Docker 守护进程,抓取全部状态的容器、镜像、网络与卷,以{"oneuptime.docker.kind":"Container","data":{...}}的 JSON 信封逐行写入/var/log/oneuptime-docker-inventory.log,再由 collector 的filelog/inventoryreceiver 读取并沿独立的logs/inventory管道转发。写盘时先写.tmp再原子重命名,避免 collector 读到写了一半的文件。
日志驱动要求(重要)
Agent只能摄取使用 Dockerjson-file日志驱动的容器日志(这是 Docker 默认驱动)。若安装被覆盖为local(二进制 protobuf,写入local-logs/)、或journald、syslog、fluentd、gelf等远程驱动,filelog receiver 将无法读取。
检查单个容器的日志驱动:
docker inspect <container> --format '{{.HostConfig.LogConfig.Type}}'检查守护进程默认驱动:
docker info --format '{{.LoggingDriver}}'为 Compose 服务切换为json-file并配置合理的轮转:
services: my-app: image: my-app:latest logging: driver: "json-file" options: max-size: "100m" max-file: "5"修改守护进程默认驱动(影响之后创建的所有容器),编辑/etc/docker/daemon.json:
{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "5" } }然后重启 Docker 并**重建(而非仅重启)**相关容器——日志驱动在容器创建时即被绑定,已存在的容器会保留旧驱动直到被删除重建。
自托管 OneUptime
如果你自托管 OneUptime,将ONEUPTIME_URL设置为自己的实例:
-e ONEUPTIME_URL="https://your-oneuptime-host.example.com"如果实例仅支持 HTTP,则使用http://并带上相应端口。
在 Collector 配置中,数据出口为${env:ONEUPTIME_URL}/otlp,并通过请求头x-oneuptime-service-token携带摄取令牌(见 DockerAgent/otel-collector-config.yaml 的exporters.otlphttp配置)。出口前还有batch(10s/1024 条)与memory_limiter(512 MiB,尖峰 128 MiB)处理器,以及一条过滤规则,用于丢弃 Collector 自身的噪音日志,避免自采集反馈循环。
故障排查
访问 Docker 套接字被拒绝
Agent 容器必须以 root(--user 0:0)运行才能访问/var/run/docker.sock。请确认--user 0:0标志(或 Compose 中的user: "0:0")存在。
Agent 不断重启,报错 "client version is too new"
Error: cannot start pipelines: failed to start "docker_stats" receiver: Error response from daemon: client version 1.44 is too new. Maximum supported API version is 1.41守护进程会拒绝比其自身最大值更新的客户端,导致 receiver 无法启动、Collector 随之退出,容器陷入重启循环。先查询守护进程的最大 API 版本:
docker version --format '{{ .Server.APIVersion }}'然后将结果传给 Agent(例如):
docker run -d ... -e DOCKER_API_VERSION=1.41 ...或在 Compose 中设置DOCKER_API_VERSION。由于较新的守护进程仍会服务较旧的 API 版本,该设置即使在后端升级后依然有效,可在自己安排的时间移除。
如果不想查版本号,可将DOCKER_API_VERSION设为空字符串,Agent 会请求 Docker SDK 与守护进程自动协商(一次HEAD /_ping,随后采用守护进程自身的最大值),新旧守护进程均适用:
docker run -d ... -e DOCKER_API_VERSION= ...Agent 显示为“已断开”
- 检查 Agent 是否运行:
docker ps --filter name=oneuptime-docker-agent - 检查 Agent 日志:
docker logs oneuptime-docker-agent | grep -i error - 核对 OneUptime URL 与服务令牌是否正确
- 确保 Docker 主机能通过网络访问 OneUptime 实例
没有指标显示
- 检查 Docker 套接字在 Agent 内部是否可访问:
docker exec oneuptime-docker-agent ls -la /var/run/docker.sock - 检查 Collector 日志是否有导出错误:
docker logs oneuptime-docker-agent | tail -100 - 确保服务令牌有效且未过期
主机名显示为容器 ID
将环境变量DOCKER_HOST_NAME设置为可读名称,然后重新创建容器。此外,若在主机自动注册后更改DOCKER_HOST_NAME,OneUptime 会以新名称创建第二个主机行,日志会显示在新的主机条目下——因为 Docker 主机页面按resource.host.name(取自该环境变量)过滤。可用以下命令确认 Agent 实际写入的主机名:
docker inspect oneuptime-docker-agent --format '{{range .Config.Env}}{{println .}}{{end}}' | grep DOCKER_HOST_NAME控制台没有容器日志(有指标但 Logs 页为空)
最常见原因是容器未使用json-file日志驱动。诊断步骤:
# 1. 检查 Agent 的 filelog receiver 是否正在监视日志文件 docker logs oneuptime-docker-agent 2>&1 | grep -E "Started watching file|no files match" # 2. 检查容器实际使用的日志驱动 docker inspect <container> --format '{{.HostConfig.LogConfig.Type}}' # 3. 检查 receiver 期望的日志文件是否存在 docker run --rm --volumes-from oneuptime-docker-agent alpine:3.19 \ sh -c 'ls /var/lib/docker/containers/*/*-json.log 2>&1 | head'若第 1 步显示no files match the configured criteria、或第 3 步对目标容器返回空,则说明容器未使用json-file。切换到json-file后,必须重建(而非仅重启)每个容器:
# Docker Compose docker compose up -d --force-recreate <service> # 纯 Docker docker rm -f <container> docker run ... <image>下一步
- 配置Docker Monitors,针对容器 CPU / 内存 / 重启次数等条件触发告警——参见 Docker Monitor;
- 若监控的是 Kubernetes 集群而非独立 Docker 主机,使用 OneUptime Kubernetes Agent;
- 若是非容器化主机(Linux / macOS / Windows 虚拟机与裸金属),使用 Host OpenTelemetry Collector;
- 需要深入了解 Agent 的完整行为、镜像标签与日志驱动要求,可继续阅读仓库中的 DockerAgent/README.md;其日志严重性推导的边界行为与回归用例,参见 Tests/Ops/ContainerAgentLogSeverity.test.js。
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考