HyperDX 2.41.0 Docker Compose 部署指南

HyperDX 2.41.0 Docker Compose 部署指南:单服务器部署 ClickStack 开源版 4 服务栈(HyperDX UI+API、OTel Collector、ClickHouse 26.1、MongoDB)的全流程实测,覆盖镜像选型、数据持久化、环境变量表、OpAMP 动态配置说明、等价 all-in-one docker run 实测,以及健康检查误报、TimestampTime 表达式错配、OTLP 不监听等 6 个排障实录。

HyperDX可观测性自托管2026/10/23

HyperDX 2.41.0 Docker Compose 部署指南

目标:用 Docker Compose 在单台服务器上部署 HyperDX 2.41.0(ClickStack 开源版)的完整 4 服务栈(HyperDX UI+API、OTel Collector、ClickHouse、MongoDB),完成首用户注册、OTLP 测试数据摄入与检索验证的端到端闭环,并沉淀镜像选型、持久化、环境变量与健康检查误报等实测结论。本文全部命令与回显均在 2026-10-23 于 Linux 服务器实测执行。

一、环境信息

实测环境(2026-10-23,真实服务器视角):

$ free -h
               total        used        free      shared  buff/cache   available
Mem:            31Gi        17Gi       3.9Gi       524Mi        10Gi        12Gi
Swap:          2.0Gi       2.0Gi       2.0Mi

$ df -h /opt | tail -1
/dev/sda3       786G  448G  304G  60% /

$ docker --version
Docker version 29.8.1, build 4a63305
$ docker compose version
Docker Compose version v5.5.1
  • 软件版本:HyperDX 2.41.0(GitHub Releases 于 2026-10-13 发布,app/api/collector 同版本波次),查询日期 2026-10-23
  • 栈内组件版本:hyperdx/hyperdx:2.41.0(UI+API 双进程)、clickhouse/clickstack-otel-collector:2.41.0、clickhouse/clickhouse-server:26.1-alpine(实测引擎版本 26.1.12.23)、mongo:5.0.32-focal——前三个镜像 tag 与官方仓库 docker-compose.yml 一致
  • 端口规划(本机均实测空闲):UI 8130、API 8136、OTLP gRPC 8137、OTLP HTTP 8138、collector 健康检查 8139、fluentd receiver 8152、collector 指标 8888
  • Docker 网络槽位:显式指定子网 10.89.56.0/24,避免与宿主机其他 bridge 网络冲突
  • 资源占用参考:空载稳定运行后四容器 RSS 合计约 940 MiB(app 337 / otel-collector 40 / clickhouse 478 / mongo 84 MiB),free -h 显示 3.9 GiB 空闲内存的服务器即可承载最小栈;ClickHouse 空载即占 ~0.5 GB,评估硬件时按此打底
  • 官方部署文档:https://clickhouse.com/docs/clickstack/deployment/docker-compose(查询日期 2026-10-23)

二、镜像选型说明

ClickStack 开源版有两种镜像形态,按用途选择:

形态镜像适用本篇取舍
多容器 Composehyperdx/hyperdx + clickhouse/clickstack-otel-collector + clickhouse/clickhouse-server + mongo演示、测试、生产基线✅ 本篇主部署形态:组件隔离、可独立升级/扩容、数据卷各自独立
All-in-One 单容器clickhouse/clickstack-all-in-one快速体验、临时演示官方明确不建议生产使用(无组件隔离、cgroup 限额全局共享);作为「等价 docker run」节实测对照

镜像命名注意(来源:官方 All-in-One 文档的 Image Name Update 说明,查询日期 2026-10-23):镜像已统一发布为 clickhouse/clickstack-*,旧的 docker.hyperdx.io/hyperdx/* 通道为历史名称;HyperDX UI/API 镜像仍在 hyperdx/hyperdx。

版本对齐是选型关键:hyperdx/hyperdx 与 clickhouse/clickstack-otel-collector 必须使用同一版本号(如本文的 2.41.0)——collector 的 OTLP receiver 配置由 app 通过 OpAMP 协议下发,跨大版本混搭可能导致 receiver 配置无法下发(详见「常见问题」第 3 条实测)。

三、前置条件

  1. Docker 29.x + Docker Compose v2 及以上(本机实测 29.8.1 / v5.5.1);
  2. 端口空闲:ss -ltn | grep -E ':(8130|8136|8137|8138|8139|8152|8888)\b' 无输出即为空闲;
  3. 内存 ≥4 GiB 空闲(空载栈 ~940 MiB,加上 ClickHouse 合并任务与查询余量按 4 GiB 起评);
  4. 磁盘 ≥20 GiB(ClickHouse 数据卷随日志量增长,2.41.0 默认 30 天 TTL 兜底);
  5. 可访问 Docker Hub(如经代理拉取,docker pull 前先配置好代理)。

四、部署步骤

4.1 目录结构

在工作目录(本文以 /opt/data/quzuo/tmp/hyperdx/deploy 为例)准备以下文件:

deploy/
├── docker-compose.yml
└── clickhouse/
    ├── config.xml
    └── users.xml

clickhouse/config.xml 与 users.xml 取自官方仓库 docker/clickhouse/local/ 目录(config.xml 定义监听 0.0.0.0:8123/9000、debug 级 console 日志;users.xml 定义 default 空密码用户并开启 access management)。最简获取方式是克隆官方仓库:

git clone --depth 1 https://github.com/hyperdxio/hyperdx.git clickstack-repo
cp clickstack-repo/docker/clickhouse/local/*.xml clickhouse/

4.2 docker-compose.yml 完整内容

以下为本专栏实测通过的全量编排(在官方 compose 基础上:显式 name、显式子网、宿主端口改用 813x 槽位、DEFAULT_SOURCES 时间列表达式修正——原因见「常见问题」第 2 条、app 健康检查覆盖——原因见「常见问题」第 1 条):

name: hyperdx-2410-stack
services:
  db:
    image: mongo:5.0.32-focal
    volumes:
      - ./volumes/db:/data/db
    networks:
      - internal
    restart: always
  otel-collector:
    image: clickhouse/clickstack-otel-collector:2.41.0
    environment:
      CLICKHOUSE_ENDPOINT: "tcp://ch-server:9000?dial_timeout=10s"
      HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE: default
      HYPERDX_LOG_LEVEL: info
      OPAMP_SERVER_URL: "http://app:4320"
      HYPERDX_OTEL_EXPORTER_CREATE_LEGACY_SCHEMA: "true" # 官方默认值;2.41.0 实测仅影响 hyperdx_sessions(保留 TimestampTime 列),otel_logs/otel_traces 恒为新 schema
    ports:
      - "8139:13133" # health_check extension
      - "8152:24225" # fluentd receiver
      - "8137:4317"  # OTLP gRPC receiver
      - "8138:4318"  # OTLP http receiver
      - "8888:8888"  # metrics extension
    restart: always
    networks:
      - internal
    depends_on:
      - ch-server
  app:
    image: hyperdx/hyperdx:2.41.0
    ports:
      - "8136:8136"
      - "8130:8130"
    environment:
      FRONTEND_URL: http://localhost:8130
      HYPERDX_API_KEY: ${HYPERDX_API_KEY:-}
      HYPERDX_API_PORT: 8136
      HYPERDX_APP_PORT: 8130
      HYPERDX_APP_URL: http://localhost
      HYPERDX_LOG_LEVEL: info
      MINER_API_URL: "http://miner:5123"
      MONGO_URI: "mongodb://db:27017/hyperdx"
      SERVER_URL: http://127.0.0.1:8136
      OPAMP_PORT: 4320
      OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4318"
      OTEL_SERVICE_NAME: "hdx-oss-app"
      USAGE_STATS_ENABLED: "false"
      DEFAULT_CONNECTIONS: '[{"name":"Local ClickHouse","host":"http://ch-server:8123","username":"default","password":""}]'
      DEFAULT_SOURCES: '[{"from":{"databaseName":"default","tableName":"otel_logs"},"kind":"log","timestampValueExpression":"Timestamp","name":"Logs","displayedTimestampValueExpression":"Timestamp","implicitColumnExpression":"Body","serviceNameExpression":"ServiceName","bodyExpression":"Body","eventAttributesExpression":"LogAttributes","resourceAttributesExpression":"ResourceAttributes","defaultTableSelectExpression":"Timestamp,ServiceName,SeverityText,Body","severityTextExpression":"SeverityText","traceIdExpression":"TraceId","spanIdExpression":"SpanId","connection":"Local ClickHouse","traceSourceId":"Traces","sessionSourceId":"Sessions","metricSourceId":"Metrics"},{"from":{"databaseName":"default","tableName":"otel_traces"},"kind":"trace","timestampValueExpression":"Timestamp","name":"Traces","displayedTimestampValueExpression":"Timestamp","implicitColumnExpression":"SpanName","serviceNameExpression":"ServiceName","eventAttributesExpression":"SpanAttributes","resourceAttributesExpression":"ResourceAttributes","defaultTableSelectExpression":"Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName","traceIdExpression":"TraceId","spanIdExpression":"SpanId","durationExpression":"Duration","durationPrecision":9,"parentSpanIdExpression":"ParentSpanId","spanNameExpression":"SpanName","spanKindExpression":"SpanKind","statusCodeExpression":"StatusCode","statusMessageExpression":"StatusMessage","connection":"Local ClickHouse","logSourceId":"Logs","sessionSourceId":"Sessions","metricSourceId":"Metrics"},{"from":{"databaseName":"default","tableName":""},"kind":"metric","timestampValueExpression":"TimeUnix","name":"Metrics","resourceAttributesExpression":"ResourceAttributes","metricTables":{"gauge":"otel_metrics_gauge","histogram":"otel_metrics_histogram","sum":"otel_metrics_sum","_id":"682586a8b1f81924e628e808","id":"682586a8b1f81924e628e808"},"connection":"Local ClickHouse","logSourceId":"Logs","traceSourceId":"Traces","sessionSourceId":"Sessions"},{"from":{"databaseName":"default","tableName":"hyperdx_sessions"},"kind":"session","timestampValueExpression":"Timestamp","name":"Sessions","displayedTimestampValueExpression":"Timestamp","implicitColumnExpression":"Body","serviceNameExpression":"ServiceName","bodyExpression":"Body","eventAttributesExpression":"LogAttributes","resourceAttributesExpression":"ResourceAttributes","defaultTableSelectExpression":"Timestamp,ServiceName,SeverityText,Body","severityTextExpression":"SeverityText","traceIdExpression":"TraceId","spanIdExpression":"SpanId","connection":"Local ClickHouse","logSourceId":"Logs","traceSourceId":"Traces","sessionSourceId":"Sessions"}]'
    networks:
      - internal
    depends_on:
      - ch-server
      - db
    # 镜像内置 healthcheck 硬编码探测 8000 端口;自定义 HYPERDX_API_PORT 后必须覆盖,
    # 否则容器永远 unhealthy(服务本身正常,仅为误报)
    healthcheck:
      test: ["CMD-SHELL", "node -e \"require('http').get('http://localhost:' + (process.env.HYPERDX_API_PORT || 8000) + '/health',r=>r.statusCode===200?process.exit(0):process.exit(1)).on('error',()=>process.exit(1))\""]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 60s
  ch-server:
    image: clickhouse/clickhouse-server:26.1-alpine
    environment:
      CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
    volumes:
      - ./clickhouse/config.xml:/etc/clickhouse-server/config.xml
      - ./clickhouse/users.xml:/etc/clickhouse-server/users.xml
      - ./volumes/ch_data:/var/lib/clickhouse
      - ./volumes/ch_logs:/var/log/clickhouse-server
    restart: on-failure
    networks:
      - internal
networks:
  internal:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.56.0/24

先做配置校验(无输出即通过):

$ docker compose config --quiet && echo 'config OK'
config OK

4.3 启动与状态确认

$ mkdir -p volumes/db volumes/ch_data volumes/ch_logs
$ docker compose up -d

首次执行会依次拉取 4 个镜像并创建容器;变更编排后重建时的实测回显形态如下:

 Container hyperdx-2410-stack-otel-collector-1 Starting
 Container hyperdx-2410-stack-otel-collector-1 Started
 Container hyperdx-2410-stack-app-1 Starting
 Container hyperdx-2410-stack-app-1 Started

等待 1~2 分钟(app 内部含 UI/API/告警任务三进程与 ClickHouse 建表),确认状态:

$ docker compose ps --format 'table {{.Name}}\t{{.Status}}'
NAME                                  STATUS
hyperdx-2410-stack-app-1              Up About a minute (healthy)
hyperdx-2410-stack-ch-server-1        Up 22 minutes
hyperdx-2410-stack-db-1               Up 22 minutes
hyperdx-2410-stack-otel-collector-1   Up About a minute (healthy)

API 健康检查通过即栈可用(ip 字段为请求来源地址,每次请求不同,属正常):

$ curl -s http://localhost:8136/health
{"data":"OK","version":"2.41.0","ip":"::ffff:10.89.56.1","env":"production"}

ClickHouse 建表确认(2.41.0 新 schema:otel_logs/otel_traces 仅 Timestamp 时间列,并新增 <table>_kv_rollup_15m 元数据物化视图):

$ docker exec hyperdx-2410-stack-ch-server-1 clickhouse-client --query "SELECT name, engine FROM system.tables WHERE database='default' ORDER BY name FORMAT TSV"
hyperdx_sessions        MergeTree
otel_logs       MergeTree
otel_logs_attr_kv_rollup_15m_mv MaterializedView
otel_logs_kv_rollup_15m SummingMergeTree
otel_metrics_exponential_histogram      MergeTree
otel_metrics_gauge      MergeTree
otel_metrics_histogram  MergeTree
otel_metrics_sum        MergeTree
otel_metrics_summary    MergeTree
otel_traces     MergeTree
otel_traces_kv_rollup_15m       SummingMergeTree
otel_traces_kv_rollup_15m_mv    MaterializedView
otel_traces_trace_id_ts MergeTree
otel_traces_trace_id_ts_mv      MaterializedView

4.4 首用户注册(Web 登录闭环)

浏览器访问 http://<服务器IP>:8130,注册首个用户与团队。密码策略(实测强制):≥12 位、含大小写字母与特殊字符、且需重复输入 confirmPassword——用弱密码 q1w2e3r4 会被 Zod 校验拒绝。命令行注册(与 UI 等价,打 API 端口 8136 而非 UI 端口):

$ curl -s -X POST http://localhost:8136/register/password \
    -H 'Content-Type: application/json' \
    -d '{"email":"root@quzuo.net","password":"Q1w2e3r4t5y6!","confirmPassword":"Q1w2e3r4t5y6!","teamName":"quzuo"}'
{"status":"success"}

登录(成功返回 303 重定向并下发会话 Cookie):

$ curl -s -i --max-time 10 -c cookies.txt -X POST http://localhost:8136/login/password \
    -H 'Content-Type: application/json' \
    -d '{"email":"root@quzuo.net","password":"Q1w2e3r4t5y6!"}' | head -3
HTTP/1.1 303 See Other
Access-Control-Allow-Origin: http://localhost:8130
Vary: Origin, Accept, Accept-Encoding

⚠️ 注意:注册/登录接口只在 API 端口(默认 8000,本文 8136)上,UI 端口(8130)不代理这两个路径,直接向 UI 端口 POST 会得到 Next.js 404 页(实测)。

4.5 获取 ingest key 并摄入测试数据

团队级 ingest key 存于 MongoDB hyperdx.teams(UI 中在 Team Settings 页可见):

$ docker exec hyperdx-2410-stack-db-1 mongosh --quiet hyperdx --eval 'JSON.stringify(db.teams.find({},{apiKey:1}).toArray())'
[{"_id":"6adaae2ed640de28d174c2ad","apiKey":"cca923a9-201f-4aa6-9d2d-98d016261d61"}]

用 ingest key 向 OTLP HTTP 端口发一条测试日志(注意 authorization 头直接填 key,不加 Bearer 前缀):

$ NOW_NANO="$(date +%s)000000000"
$ curl -s -i --max-time 10 -X POST "http://localhost:8138/v1/logs" \
    -H "Content-Type: application/json" \
    -H "authorization: cca923a9-201f-4aa6-9d2d-98d016261d61" \
    --data-binary "{\"resourceLogs\":[{\"resource\":{\"attributes\":[{\"key\":\"service.name\",\"value\":{\"stringValue\":\"compose-final-check\"}}]},\"scopeLogs\":[{\"scope\":{\"name\":\"b2-doc\"},\"logRecords\":[{\"timeUnixNano\":\"${NOW_NANO}\",\"severityText\":\"INFO\",\"body\":{\"stringValue\":\"B2 部署闭环验证 ${NOW_NANO}\"}}]}]}]}" | head -1
HTTP/1.1 200 OK

约 5 秒后(collector 批量导出周期)在 ClickHouse 验证落库:

$ docker exec hyperdx-2410-stack-ch-server-1 clickhouse-client --query "SELECT Timestamp, ServiceName, Body FROM default.otel_logs WHERE Body LIKE '%部署闭环验证%' ORDER BY Timestamp DESC LIMIT 1"
2026-10-23 01:08:19.000000000   compose-final-check     B2 部署闭环验证 1792717699000000000

最后在 UI 的 Search 视图检索 部署闭环验证 能看到该条日志——至此「部署 → 注册登录 → 摄入 → 检索」闭环完成。

五、数据持久化说明

组件容器内路径宿主挂载(本编排)内容
HyperDX app无状态–UI/API 进程状态在 MongoDB
MongoDB/data/db./volumes/db用户、团队、ingest key、仪表盘、告警规则、Source 定义
ClickHouse/var/lib/clickhouse./volumes/ch_data全部遥测数据(默认 30 天 TTL)
ClickHouse 日志/var/log/clickhouse-server./volumes/ch_logs查询与服务器日志

实测说明:

  • 首次 up -d 前需 mkdir -p 三个 volumes 子目录,否则 Docker 会以 root 自动创建(目录属主为 root,后续 chown 麻烦);
  • Mongo 侧的 /data/db 必须挂载,否则删除容器即丢失全部账号与 ingest key(遥测数据虽在 ClickHouse 仍在,但团队与 Source 定义全失);
  • ClickHouse 数据默认 TTL 30 天(collector exporter 的 ${env:HYPERDX_OTEL_EXPORTER_TABLES_TTL:-720h}),核心表定义可查证:
$ docker exec hyperdx-2410-stack-ch-server-1 clickhouse-client --query "SELECT table, engine_full FROM system.tables WHERE database='default' AND table IN ('otel_logs','otel_traces') FORMAT TSV"
otel_logs       MergeTree PARTITION BY toDate(Timestamp) ORDER BY (toStartOfFiveMinutes(Timestamp), ServiceName, Timestamp) TTL toDateTime(Timestamp) + toIntervalDay(30) SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1, enable_block_number_column = 1, enable_block_offset_column = 1
otel_traces     MergeTree PARTITION BY toDate(Timestamp) ORDER BY (ServiceName, SpanName, toDateTime(Timestamp)) TTL toDate(Timestamp) + toIntervalDay(30) SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1

六、环境变量表

6.1 app 服务(hyperdx/hyperdx)

变量本篇取值说明
HYPERDX_API_PORT8136API 监听端口(镜像默认 8000)。改动后必须覆盖 healthcheck(见常见问题 1)
HYPERDX_APP_PORT8130UI(Next.js)监听端口(镜像默认 8080)
MONGO_URImongodb://db:27017/hyperdx应用状态库连接串
OPAMP_PORT4320OpAMP 服务端口,collector 通过它接收动态 receiver 配置
OPAMP_SERVER_URLhttp://127.0.0.1:8136app 自身回访 API 的地址
SERVER_URLhttp://127.0.0.1:8136UI 前端调 API 的内部地址
FRONTEND_URLhttp://localhost:8130对外 UI 地址(CORS 允许来源)
MINER_API_URLhttp://miner:5123内置 miner 服务的地址(镜像内置,保持容器名访问)
HYPERDX_LOG_LEVELinfoapp+api 日志级别
USAGE_STATS_ENABLEDfalse匿名使用统计上报开关
OTEL_EXPORTER_OTLP_ENDPOINThttp://otel-collector:4318app 自身遥测上报地址(自观测链路)
HYPERDX_API_KEY–可选:预设团队 ingest key(不设则注册时自动生成)
DEFAULT_CONNECTIONS见编排首次启动自动创建的 ClickHouse 连接
DEFAULT_SOURCES见编排首次启动自动创建的 Logs/Traces/Metrics/Sessions 四源;官方模板的 Traces 源表达式与 2.41.0 实际表结构不符,本篇已修正(见常见问题 2)
EXPRESS_SESSION_SECRET–可选:固定会话密钥;不设则每次重启随机生成、所有用户被登出(app 启动日志实测提示)
TOKEN_ENCRYPTION_KEY–可选:第三方令牌加密;不设则明文存储(app 启动日志实测提示)

6.2 otel-collector 服务(clickhouse/clickstack-otel-collector)

变量本篇取值说明
OPAMP_SERVER_URLhttp://app:4320OpAMP 上游(app),动态 receiver 配置来源
CLICKHOUSE_ENDPOINTtcp://ch-server:9000?dial_timeout=10sClickHouse 原生 TCP 地址
CLICKHOUSE_USER / CLICKHOUSE_PASSWORD–未设时用 default 用户
HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASEdefault遥测数据落库
HYPERDX_OTEL_EXPORTER_CREATE_LEGACY_SCHEMAtrue(官方默认)实测 2.41.0 中仅影响 hyperdx_sessions(保留 TimestampTime 列);otel_logs/otel_traces 无论真假均建为新 schema(仅 Timestamp + kv_rollup 视图)
HYPERDX_OTEL_EXPORTER_TABLES_TTL720h(默认)数据保留期,改小即缩短 TTL
HYPERDX_OTEL_EXPORTER_CLICKHOUSE_JSON_ENABLEfalse(默认)JSON 类型 schema 开关(beta,官方不建议默认启用)
HYPERDX_LOG_LEVELinfocollector 日志级别

七、配置参数说明

collector 是「动态配置」架构:容器内静态配置只声明 processors 与 OpAMP 上游,OTLP receiver(4317/4318 的鉴权与绑定)由 app 通过 OpAMP 在运行时下发。两个实测推论:

  1. 查看生效配置要看 supervisor 生成的 effective 文件而非容器命令行参数:
$ docker exec hyperdx-2410-stack-otel-collector-1 sh -c "head -8 /etc/otel/supervisor-data/effective.yaml"
connectors:
    routing/logs:
        default_pipelines:
            - logs/out-default
        error_mode: ignore
        table:
            - context: log
              pipelines:
                - logs/out-rrweb
  1. 静态 validate 校验对动态 receiver 部分必然缺席,属预期行为(校验三场景的实测见 《HyperDX 2.41.0 常用 CLI 命令详解》第六章)。

DEFAULT_SOURCES 表达式对齐:Source 的 timestampValueExpression 必须指向真实存在的列。2.41.0 实测列名分布——otel_logs/otel_traces 只有 Timestamp,hyperdx_sessions 同时有 Timestamp 与 TimestampTime:

$ docker exec hyperdx-2410-stack-ch-server-1 clickhouse-client --query "SELECT table, countIf(name='TimestampTime') AS tt, countIf(name='Timestamp') AS ts FROM system.columns WHERE database='default' AND table IN ('otel_logs','otel_traces','hyperdx_sessions') GROUP BY table FORMAT TSV"
hyperdx_sessions        1       1
otel_logs       0       1
otel_traces     0       1

密钥体系:团队 ingest key(OTLP 摄入,authorization 头裸值)与用户 accessKey(/api/v2 外部 API,Bearer 头)是两套独立凭据,后者可在 UI Team Settings 或 PATCH /me/accessKey 轮换(获取与 Bearer 调用实测见 《HyperDX 2.41.0 常用 CLI 命令详解》第七章 7.1 节)。

八、配置文件挂载

本编排仅挂载 ClickHouse 的两个 XML(config.xml 全局配置、users.xml 用户定义)。实测要点:

  • users.xml 中 default 用户为空密码 + access_management=1(由 CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1 环境变量叠加生效),app 的 DEFAULT_CONNECTIONS 即用该用户连接 http://ch-server:8123;
  • 若要收紧 ClickHouse 面向容器网络的密码,在 users.xml 为 default 设置 password 后,同步修改 DEFAULT_CONNECTIONS 的 password 字段并重启 app;
  • collector 的静态配置文件在容器内 /etc/otel/ 下,自定义接收器需求(如加 fluentd、文件日志采集)推荐在 app 侧 Source/Team 设置里完成或用 CUSTOM_OTELCOL_CONFIG_FILE 挂载注入(collector 启动日志实测打印 CUSTOM_OTELCOL_CONFIG_FILE not set, using default configuration);
  • Mongo 与 app 无需额外配置文件,全部走环境变量。

九、等价 docker run

单容器等价形态用 all-in-one 镜像(内置四个组件),适合快速体验(实测端口改为 8146 避让):

$ docker run -d --name hyperdx-2410-allinone \
    -p 8146:8080 -p 4317:4317 -p 4318:4318 \
    clickhouse/clickstack-all-in-one:2.41.0
1a6e2c9c5799773ddad437f10616257a8faf2275a04d7b67e850dee6c51fe3dc

$ docker ps --filter name=hyperdx-2410-allinone --format '{{.Status}}'
Up 59 seconds (healthy)

UI 就绪验证(all-in-one 的 /health 在 UI 进程上不存在,用登录页探活):

$ curl -s -o /dev/null -w '/login http_code=%{http_code}\n' http://localhost:8146/login
/login http_code=200

实测发现(重要):all-in-one 首次启动存在 OpAMP 启动竞态——collector 的 supervisor 先于 app 的 OpAMP 服务(4320)就绪,日志打印 dial tcp 127.0.0.1:4320: connect: connection refused 后虽然重连成功,但 OTLP receiver 配置未成功下发,4317/4318 不监听(netstat -ltn 实测无 4317/4318,otelcontribcol 以 --feature-gates service.AllowNoPipelines 空转)。docker restart 一次即可恢复:

$ docker restart hyperdx-2410-allinone >/dev/null && sleep 45 \
  && docker exec hyperdx-2410-allinone netstat -ltn | grep -E ':(4317|4318)'
tcp        0      0 :::4317                 :::*                    LISTEN
tcp        0      0 :::4318                 :::*                    LISTEN

恢复后走同样闭环(注册 → Mongo 取 key → OTLP 200 → ClickHouse 落行),实测 ingest key 与落库均正常:

{"partialSuccess":{}}
HTTP_CODE=200

$ docker exec hyperdx-2410-allinone clickhouse-client --query "SELECT Timestamp, ServiceName, Body FROM default.otel_logs WHERE Body LIKE '%all-in-one%' FORMAT TSV"
2026-10-23 01:04:28.000000000   aio-test        all-in-one docker run test

生产部署仍选第四节的多容器 Compose;all-in-one 仅用于本地评估,测完 docker rm -f hyperdx-2410-allinone 清理。

十、常用运维命令

# 状态与健康
docker compose ps --format 'table {{.Name}}\t{{.Status}}'
curl -s http://localhost:8136/health

# 日志排查(app 内含 [API]/[APP]/[ALERT-TASK] 三路日志)
docker compose logs -f app
docker compose logs --tail=100 otel-collector

# 重启单个组件
docker compose restart otel-collector

# 修改编排后的增量生效(只重建受影响容器,数据卷不动)
docker compose up -d

# 配置校验
docker compose config --quiet

# ClickHouse 快速体检
docker exec hyperdx-2410-stack-ch-server-1 clickhouse-client --query "SELECT version()"
# 26.1.12.23

# 停止与销毁(-v 连同匿名卷;本编排数据在 bind mount,需另行清理 volumes/ 目录)
docker compose down
docker compose down -v

十一、常见问题

1. app 容器永远 (unhealthy),但 UI/API 都正常。 镜像内置 healthcheck 硬编码探测 http://localhost:8000/health(镜像默认 API 端口);一旦用 HYPERDX_API_PORT 改成 8136,探针必然失败——纯误报(实测 /health 在 8136 正常返回、容器持续 unhealthy)。解法:在 compose 中覆盖 healthcheck 指向真实 API 端口(见第四节编排文件内的 healthcheck 段),重建后 (healthy)。

2. 搜索报 UNKNOWN_IDENTIFIER: Unknown expression identifier TimestampTime。 官方仓库 docker-compose.yml 的 DEFAULT_SOURCES 中 Traces 源(及个别源)使用 "timestampValueExpression":"TimestampTime",而 2.41.0 collector 建出的 otel_traces/otel_logs 实测只有 Timestamp 列(官方模板滞后于新 schema)。解法:把 DEFAULT_SOURCES 中的 TimestampTime 全部改为 Timestamp(本篇编排已修正);若已用错误 Source 注册,可在 UI Team Settings → Sources 编辑,或清空 Mongo 集合重建。

3. OTLP 端口 4317/4318 不监听、发数据连接被拒。 OpAMP 动态配置未下发,常见三个原因(均实测):① all-in-one 首启竞态——docker restart 一次(见第九节);② app 与 collector 版本不对齐——两镜像统一 tag;③ app 尚未就绪(OpAMP 4320 未监听)——等 app healthy 后看 collector 日志 Connected to the OpAMP server。

4. 弱密码注册被拒。 密码策略为 Zod 强校验:≥12 位 + 大小写 + 特殊字符 + confirmPassword 必填,q1w2e3r4 不合格。用 Q1w2e3r4t5y6! 一类即可。

5. 向 UI 端口调 API 得到 Next.js 404。 注册/登录/health 等接口只挂 API 端口(默认 8000/本文 8136);UI 端口(默认 8080/本文 8130)只服务页面与静态资源。注意 hdx CLI 的 --app-url 反而要指 UI 端口(CLI 依赖 Next.js 侧代理路径),两者别混。

6. 首次启动 app 起来慢、Up (health: starting) 持续一两分钟。 app 内部要等 MongoDB 连接、ClickHouse 建表、UI 编译产物加载;编排已给 60s start_period,属预期,无需干预。

十二、参考链接