SIPCAPTURE Homer 11 Docker Compose 部署指南
使用官方 ghcr.io/sipcapture/homer:11.0.369 镜像与 Docker Compose 部署 SIPCAPTURE Homer 11:homer 全模块 + RustFS S3 兼容冷层 + DuckDB 扩展离线灌注,含环境变量全表、冷卷排障实录与等价 docker run,全部命令实测回显。
SIPCAPTURE Homer 11 Docker Compose 部署指南
目标:在 Ubuntu 22.04 服务器上用 Docker Compose 一键部署 SIPCAPTURE Homer 11 官方镜像(ghcr.io/sipcapture/homer:11.0.369)——homer 全模块 + RustFS 对象存储冷层 + DuckDB 扩展离线灌注,覆盖镜像选型、部署步骤、数据持久化、环境变量全表、冷卷排障实录与等价 docker run,全部命令实测回显。单机二进制安装(deb/systemd)路线见本专栏 《Ubuntu 22.04 安装 SIPCAPTURE Homer 11 指南》。
一、环境信息
本文所有操作均在以下环境中实测完成,实测回显均为原始输出:
| 项目 | 内容 |
|---|---|
| 操作系统 | Ubuntu 22.04 LTS(x86_64) |
| Docker Engine | 29.9.2 |
| Docker Compose | v5.6.1(docker compose version 实测:Docker Compose version v5.6.1) |
| Homer 镜像 | ghcr.io/sipcapture/homer:11.0.369(官方 all-in-one,入口 /homer) |
| 冷层对象存储镜像 | rustfs/rustfs:latest(S3 兼容,承载冷数据卷) |
| 辅助镜像 | alpine:3.20(初始化作业)、rustfs/rc:latest(建桶) |
| 部署目录 | /opt/homer-compose |
| 宿主端口 | 8131(Web/API)、9060(HEP UDP/TCP)、9080(HTTP ingest)、50051(gRPC)、9090(Prometheus) |
| 数据卷 | homer_data(数据湖与扩展)、rustfs_data(冷层桶数据) |
| 文档撰写日期 | 2026-10-27 |
二、镜像选型说明
2.1 Homer 官方镜像
Homer 11 的官方镜像发布在 GitHub Container Registry:ghcr.io/sipcapture/homer,tag 与 homer-core 版本一致(本文实测 11.0.369)。镜像为 all-in-one 形态:
- 单一入口二进制
/homer,同一进程按需启用 ingest(采集)、storage(存储)、node(查询节点)、coordinator(协调/API/UI)四个模块; - Web UI 静态资源内置于镜像
/usr/local/homer-core/dist,由 coordinator 模块直接伺服,无需另装 homer-ui; - 镜像内不带默认配置文件(实测
/usr/local/homer-core/下仅有dist/目录),配置完全由HOMER_*环境变量注入,这是 Compose 形态与 deb 安装形态最大的差异(详见第七、八章); - 以普通用户
1000:1000运行,数据目录/data/homer需要该 UID 属主——这也是第四章初始化作业存在的原因。
版本查询:镜像 tag 跟随 https://github.com/sipcapture/homer/releases 的 Release tag,11.0.x 数日一版,生产建议锁定具体版本号而非 latest。
2.2 冷层对象存储选型
Homer 11 的 DuckLake 存储支持"热卷(本地 Parquet)+ 冷卷(S3 对象存储)"分层:新数据写本地热卷,按 TTL 策略搬迁到 S3 冷卷。Compose 栈需要一个 S3 兼容对象存储承载冷卷。
💡 技术拓展:S3 兼容对象存储不止本文所用 RustFS。常见选项对比——
方案 特点 适用场景 RustFS Rust 编写的新兴 S3 兼容存储,单二进制、资源占用低 轻量自托管冷层(本文采用) MinIO 生态最成熟的 S3 兼容存储,社区版功能收敛后仍可用 存量部署、需要成熟生态 SeaweedFS 带文件系统语义的分布式存储,S3 网关可选 海量小文件混合场景 Ceph RGW 分布式存储 families 的 S3 网关 已有 Ceph 集群的企业 云上 S3/OSS/COS 托管服务,免运维 不想自托管对象存储 本文选 RustFS:单容器即可拉起、自带健康检查与管理控制台,适合演示与中小规模冷层;生产可无缝替换为 MinIO 或云对象存储,只需改 S3 端点与密钥环境变量。
2.3 辅助镜像
alpine:3.20:两个一次性初始化作业(修数据卷属主、灌注 DuckDB 扩展);rustfs/rc:RustFS 官方管理客户端镜像,用于创建冷数据桶homer-data-cold。
三、前置条件
3.1 软硬件要求
- Docker Engine 24+ 与
docker compose插件(docker compose version可执行); - 内存 ≥ 4GB:内置 DuckDB writer 默认
MEMORY_LIMIT=4GB(可通过环境变量下调,见第六章); - 磁盘:热卷 Parquet 与冷层桶按话务量规划,镜像本体约 1GB;
- 服务器可访问外网(拉镜像与下载扩展);完全离线部署的扩展灌注方法见 3.3 与常见问题 Q1。
3.2 端口规划
部署前确认以下宿主端口未被占用(ss -ltn | grep -E '8131|9060|9080|50051|9090' 无输出即空闲;冲突时改 Compose 文件冒号左侧的宿主端口即可):
| 宿主端口 | 服务内端口 | 协议 | 用途 |
|---|---|---|---|
| 8131 | 8080 | TCP | REST API + Web UI |
| 9060 | 9060 | UDP/TCP | HEP 采集(heplify 等代理投递) |
| 9080 | 9080 | TCP | HTTP/JSON 批量投递 |
| 50051 | 50051 | TCP | Airport gRPC 查询节点 |
| 9090 | 9090 | TCP | Prometheus /metrics |
3.3 关键认知:DuckDB 扩展为什么必须预灌注
Homer 11 的存储层是 DuckLake(基于 DuckDB),首次启动时 DuckDB 需要 ducklake、aws、httpfs 等扩展。DuckDB 的默认行为是启动时自动从 extensions.duckdb.org 下载扩展——这意味着:
- 服务器可直连外网时,无需任何准备,首次启动自动拉取;
- 服务器不通外网或下载失败时,writer 模块直接启动失败(实测报错见常见问题 Q1);
- S3 冷卷场景对
aws/httpfs扩展有硬依赖,扩展缺失时冷卷 attach 会长时间挂起。
因此可靠的部署姿势是:把 5 个官方扩展文件预下载到部署目录,由初始化作业在启动时灌注到数据卷,彻底摆脱对 extensions.duckdb.org 的运行时依赖。这正是第四章 4.1 步骤存在的目的。
四、部署步骤
4.1 目录与 DuckDB 扩展准备
创建部署目录并下载 5 个官方扩展(版本目录 v1.5.6 必须与 Homer 11.0.369 内置 DuckDB 版本精确匹配,启动日志会打印 duckdb version version=v1.5.6):
mkdir -p /opt/homer-compose/duckdb-extensions && cd /opt/homer-compose/duckdb-extensions
wget https://extensions.duckdb.org/v1.5.6/linux_amd64/aws.duckdb_extension.gz
wget https://extensions.duckdb.org/v1.5.6/linux_amd64/azure.duckdb_extension.gz
wget https://extensions.duckdb.org/v1.5.6/linux_amd64/ducklake.duckdb_extension.gz
wget https://extensions.duckdb.org/v1.5.6/linux_amd64/httpfs.duckdb_extension.gz
wget https://extensions.duckdb.org/v1.5.6/linux_amd64/sqlite_scanner.duckdb_extension.gz
gunzip *.duckdb_extension.gz
实测落盘结果(约 140MB):
-rw-r--r-- 1 root root 28466502 aws.duckdb_extension
-rw-r--r-- 1 root root 24548926 azure.duckdb_extension
-rw-r--r-- 1 root root 36475990 ducklake.duckdb_extension
-rw-r--r-- 1 root root 21580734 httpfs.duckdb_extension
-rw-r--r-- 1 root root 34833582 sqlite_scanner.duckdb_extension
⚠️ 注意:下载的 5 个扩展是本架构验证过的完整集合——
ducklake(DuckLake 湖仓表格式,writer 启动硬依赖)、httpfs与aws(HTTP/S3 访问,冷卷 attach 依赖)、sqlite_scanner(SQLite catalog 读取)、azure(Azure Blob 冷卷可选)。只灌ducklake一个时,纯本地盘可启动,但 S3 冷卷场景会在 attach 阶段挂起。
4.2 编写 docker-compose.yml
在 /opt/homer-compose/docker-compose.yml 写入以下内容(与实测运行版本一致;显式 name: homer-11-stack 锁定项目名,避免多套栈互相干扰):
name: homer-11-stack
services:
homer-init:
image: alpine:3.20
volumes:
- homer_data:/data/homer
- ./duckdb-extensions:/ext:ro
command: sh -c "chown -R 1000:1000 /data/homer && mkdir -p /data/homer/.duckdb/extensions/v1.5.6/linux_amd64 && cp /ext/*.duckdb_extension /data/homer/.duckdb/extensions/v1.5.6/linux_amd64/ && chown -R 1000:1000 /data/homer && echo homer data volume ok"
restart: "no"
networks:
- homer-compose
rustfs-init:
image: alpine:3.20
volumes:
- rustfs_data:/data
command: sh -c "chown -R 10001:10001 /data && echo rustfs data volume ok"
restart: "no"
networks:
- homer-compose
rustfs:
image: rustfs/rustfs:latest
security_opt:
- "no-new-privileges:true"
environment:
RUSTFS_VOLUMES: /data
RUSTFS_ADDRESS: 0.0.0.0:9000
RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001
RUSTFS_CONSOLE_ENABLE: "true"
RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS: "*"
RUSTFS_ACCESS_KEY: rustfsadmin
RUSTFS_SECRET_KEY: rustfsadmin
RUSTFS_OBS_LOGGER_LEVEL: info
RUSTFS_UNSAFE_BYPASS_DISK_CHECK: "false"
volumes:
- rustfs_data:/data
healthcheck:
test:
[
"CMD",
"sh",
"-c",
"curl -fsS http://127.0.0.1:9000/health && curl -fsS http://127.0.0.1:9001/rustfs/console/health",
]
interval: 15s
timeout: 10s
retries: 6
start_period: 45s
depends_on:
rustfs-init:
condition: service_completed_successfully
networks:
- homer-compose
restart: unless-stopped
rustfs-init-volume:
image: rustfs/rc:latest
depends_on:
rustfs:
condition: service_healthy
entrypoint: >
/bin/sh -c "
until (/usr/bin/rc alias set rustfs http://rustfs:9000 rustfsadmin rustfsadmin) do echo '...waiting...' && sleep 1; done;
/usr/bin/rc mb rustfs/homer-data-cold;
echo 'RustFS initialization complete';
"
restart: "no"
networks:
- homer-compose
homer:
image: ghcr.io/sipcapture/homer:11.0.369
user: "1000:1000"
working_dir: /data/homer
security_opt:
- "no-new-privileges:true"
cap_drop:
- ALL
depends_on:
rustfs:
condition: service_healthy
homer-init:
condition: service_completed_successfully
volumes:
- homer_data:/data/homer
ports:
- "8131:8080/tcp"
- "9060:9060/udp"
- "9060:9060/tcp"
- "9080:9080/tcp"
- "50051:50051/tcp"
- "9090:9090/tcp"
networks:
- homer-compose
restart: unless-stopped
environment:
HOMER_INGEST_ENABLE: "true"
HOMER_STORAGE_ENABLE: "true"
HOMER_NODE_ENABLE: "true"
HOMER_COORDINATOR_ENABLE: "true"
HOMER_INGEST_WORKER_COUNT: "8"
HOMER_INGEST_QUEUE_SIZE: "80000"
HOMER_INGEST_UDP_ENABLE: "true"
HOMER_INGEST_UDP_HOST: 0.0.0.0
HOMER_INGEST_UDP_PORT: "9060"
HOMER_INGEST_UDP_MULTICORE: "true"
HOMER_INGEST_TCP_ENABLE: "true"
HOMER_INGEST_TCP_HOST: 0.0.0.0
HOMER_INGEST_TCP_PORT: "9060"
HOMER_INGEST_TCP_MULTICORE: "true"
HOMER_INGEST_TLS_ENABLE: "false"
HOMER_INGEST_HTTP_ENABLE: "true"
HOMER_INGEST_HTTP_HOST: 0.0.0.0
HOMER_INGEST_HTTP_PORT: "9080"
HOMER_INGEST_HTTP_READ_TIMEOUT: "30"
HOMER_INGEST_HTTP_WRITE_TIMEOUT: "30"
HOMER_INGEST_HTTP_WEBSOCKET_ENABLE: "false"
HOMER_INGEST_HTTPS_ENABLE: "false"
HOMER_INGEST_HEP_HEPV3_ENABLE: "true"
HOMER_INGEST_HEP_PROTOBUF_ENABLE: "true"
HOMER_STORAGE_DUCKLAKE_CATALOG_TYPE: sqlite
HOMER_STORAGE_DUCKLAKE_CATALOG_PATH: /data/homer/homer_catalog.sqlite
HOMER_STORAGE_DUCKLAKE_DATA_PATH: /data/homer/parquet
HOMER_STORAGE_DUCKLAKE_LAKE_NAME: homer_lake
HOMER_STORAGE_DUCKLAKE_BATCH_SIZE: "10000"
HOMER_STORAGE_DUCKLAKE_FLUSH_INTERVAL_SEC: "30"
HOMER_STORAGE_DUCKLAKE_TUNING_MEMORY_LIMIT: "4GB"
HOMER_STORAGE_DUCKLAKE_TUNING_THREADS: "2"
HOMER_STORAGE_DUCKLAKE_TUNING_TEMP_DIRECTORY: /data/homer/.duckdb_spill
HOMER_NODE_DUCKLAKE_TUNING_THREADS: "2"
HOMER_NODE_DUCKLAKE_TUNING_TEMP_DIRECTORY: /data/homer/.duckdb_spill
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_ENABLE: "true"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_TTL_MOVE_INTERVAL_SEC: "3600"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_MOVE_FACTOR: "0.8"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_CONCURRENT_MOVES: "2"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_MOVE_ON_STARTUP: "true"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_0_NAME: hot
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_0_TYPE: local
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_0_PATH: /data/homer/parquet
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_0_PRIORITY: "0"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_0_MAX_DATA_AGE_DAYS: "2"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_0_MAX_SIZE_GB: "100"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_NAME: cold
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_TYPE: s3
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_PATH: s3://homer-data-cold
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_PRIORITY: "1"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_MAX_DATA_AGE_DAYS: "0"
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_S3_REGION: us-east-1
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_S3_ACCESS_KEY_ID: rustfsadmin
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_S3_SECRET_ACCESS_KEY: rustfsadmin
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_S3_ENDPOINT: http://rustfs:9000
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_S3_USE_SSL: "false"
HOMER_STORAGE_DUCKLAKE_COMPACTION_ENABLE: "true"
HOMER_STORAGE_DUCKLAKE_COMPACTION_CHECK_INTERVAL_SEC: "1800"
HOMER_STORAGE_DUCKLAKE_COMPACTION_RETENTION_DAYS: "30"
HOMER_STORAGE_DUCKLAKE_COMPACTION_SNAPSHOT_EXPIRE_INTERVAL_SEC: "3600"
HOMER_STORAGE_DUCKLAKE_COMPACTION_MIN_AGE_SEC: "3600"
HOMER_STORAGE_DUCKLAKE_COMPACTION_MIN_FILE_SIZE_BYTES: "0"
HOMER_STORAGE_DUCKLAKE_COMPACTION_MAX_FILE_SIZE_BYTES: "134217728"
HOMER_STORAGE_DUCKLAKE_COMPACTION_MAX_COMPACTED_FILES: "100"
HOMER_NODE_FLIGHT_SERVER_HOST: 0.0.0.0
HOMER_NODE_FLIGHT_SERVER_PORT: "50051"
HOMER_NODE_FLIGHT_SERVER_MAX_MESSAGE_SIZE: "16777216"
HOMER_NODE_DUCKLAKE_LAKE_NAME: homer_lake
HOMER_NODE_DUCKLAKE_VOLUMES_0_NAME: hot
HOMER_NODE_DUCKLAKE_VOLUMES_0_TYPE: local
HOMER_NODE_DUCKLAKE_VOLUMES_0_CATALOG_TYPE: sqlite
HOMER_NODE_DUCKLAKE_VOLUMES_0_CATALOG_PATH: /data/homer/homer_catalog.sqlite
HOMER_NODE_DUCKLAKE_VOLUMES_0_PATH: /data/homer/parquet
HOMER_NODE_DUCKLAKE_VOLUMES_1_NAME: cold
HOMER_NODE_DUCKLAKE_VOLUMES_1_TYPE: s3
HOMER_NODE_DUCKLAKE_VOLUMES_1_CATALOG_TYPE: sqlite
HOMER_NODE_DUCKLAKE_VOLUMES_1_CATALOG_PATH: /data/homer/homer_catalog_cold.sqlite
HOMER_NODE_DUCKLAKE_VOLUMES_1_PATH: s3://homer-data-cold
HOMER_NODE_DUCKLAKE_VOLUMES_1_S3_REGION: us-east-1
HOMER_NODE_DUCKLAKE_VOLUMES_1_S3_ACCESS_KEY_ID: rustfsadmin
HOMER_NODE_DUCKLAKE_VOLUMES_1_S3_SECRET_ACCESS_KEY: rustfsadmin
HOMER_NODE_DUCKLAKE_VOLUMES_1_S3_ENDPOINT: http://rustfs:9000
HOMER_NODE_DUCKLAKE_VOLUMES_1_S3_USE_SSL: "false"
HOMER_COORDINATOR_HTTP_SERVER_ENABLE: "true"
HOMER_COORDINATOR_HTTP_SERVER_HOST: 0.0.0.0
HOMER_COORDINATOR_HTTP_SERVER_PORT: "8080"
HOMER_COORDINATOR_HTTP_SERVER_STATIC_PATH: /usr/local/homer-core/dist
HOMER_COORDINATOR_NODES_0_NAME: local
HOMER_COORDINATOR_NODES_0_HOST: 127.0.0.1
HOMER_COORDINATOR_NODES_0_PORT: "50051"
HOMER_COORDINATOR_NODES_0_FLIGHTSQL_PORT: "0"
HOMER_COORDINATOR_NODES_0_USE_TLS: "false"
HOMER_COORDINATOR_NODES_0_PRIORITY: "1"
HOMER_COORDINATOR_SETTINGS_DB_PATH: /data/homer/homer_settings.duckdb
HOMER_COORDINATOR_JWT_EXPIRE_HOURS: "24"
HOMER_COORDINATOR_AUTH_ADMIN_USER: admin
HOMER_COORDINATOR_AUTH_ADMIN_PASSWORD_HASH: 13a5c202e320d0bf9bb2c6e2c7cf380a6f7de5d392509fee260b809c893ff2f9
HOMER_LOG_LEVEL: info
HOMER_LOG_JSON: "false"
HOMER_LOG_OUTPUT_0: stdout
HOMER_PROMETHEUS_ENABLE: "true"
HOMER_PROMETHEUS_HOST: 0.0.0.0
HOMER_PROMETHEUS_PORT: "9090"
HOMER_PROMETHEUS_PATH: /metrics
networks:
homer-compose:
driver: bridge
ipam:
config:
- subnet: 10.89.61.0/24
volumes:
rustfs_data:
homer_data:
配置解读(关键项):
| 项 | 含义与取舍 |
|---|---|
name: homer-11-stack | Compose 项目名显式锁定;同一服务器上多套 Homer 栈时互不干扰 |
homer-init / rustfs-init | 一次性作业(restart: "no"):把数据卷属主修成服务运行 UID,并把扩展灌进数据卷 |
rustfs + healthcheck | 冷层对象存储;homer 以 service_healthy 条件依赖它,保证冷卷 attach 时 S3 已就绪 |
rustfs-init-volume | 等健康检查通过后创建冷数据桶 homer-data-cold |
cap_drop: [ALL] + no-new-privileges | 最小权限加固;homer 以 UID 1000 运行不需要任何特权 |
VOLUMES_0/1 两级卷 | hot 本地卷优先级 0、cold S3 卷优先级 1;MAX_DATA_AGE_DAYS=2 表示热卷数据 2 天后搬冷 |
| subnet 10.89.61.0/24 | 自定义网段,避免与宿主已有网络冲突;无特殊需求可整段删除让 Docker 自动分配 |
| 管理口令哈希 | 13a5c2...f2f9 即 sha256("q1w2e3r4")(下文 4.5 验证登录);生产务必换成自己的哈希 |
4.3 启动栈
cd /opt/homer-compose
docker compose up -d
实测 docker compose ps(初始化作业执行完即退出,常态只剩两个常驻服务):
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
homer-11-stack-homer-1 ghcr.io/sipcapture/homer:11.0.369 "/homer" homer 30 minutes ago Up 30 minutes 0.0.0.0:9060->9060/tcp, [::]:9060->9060/tcp, 0.0.0.0:9080->9080/tcp, [::]:9080->9080/tcp, 0.0.0.0:9090->9090/tcp, [::]:9090->9090/tcp, 0.0.0.0:50051->50051/tcp, [::]:50051->50051/tcp, 0.0.0.0:9060->9060/udp, [::]:9060->9060/udp, 0.0.0.0:8131->8080/tcp, [::]:8131->8080/tcp
homer-11-stack-rustfs-1 rustfs/rustfs:latest "/entrypoint.sh rust…" rustfs 30 minutes ago Up 30 minutes (healthy) 9000-9001/tcp
两个初始化作业的实测日志(docker compose logs homer-init rustfs-init-volume):
homer-init-1 | homer data volume ok
rustfs-init-volume-1 | ✓ Bucket 'rustfs/homer-data-cold' created successfully.
rustfs-init-volume-1 | RustFS initialization complete
验证扩展已灌注进数据卷(docker compose exec homer ls /data/homer/.duckdb/extensions/v1.5.6/linux_amd64/):
aws.duckdb_extension
azure.duckdb_extension
ducklake.duckdb_extension
httpfs.duckdb_extension
sqlite_scanner.duckdb_extension
4.4 启动里程碑日志确认
docker compose logs homer 关键里程碑(节选,均为实测原文):
INF homer-core starting in modular mode...
INF version version=11.0.369
INF duckdb version version=v1.5.6
INF enabled modules modules="[ingest storage node coordinator]"
INF DuckLake data directory ensured path=/data/homer/parquet
INF DuckLake table ready (double-buffer, appender) table=homer_lake.hep_proto_1_registration buf_a=mem_hep_proto_1_registration_a buf_b=mem_hep_proto_1_registration_b batch_size=10000
INF Node: Volume attached name=hot lake=homer_lake_hot path=/data/homer/parquet
INF Node: Volume attached name=cold lake=homer_lake_cold path=s3://homer-data-cold
INF Node: DuckDB attached catalogs catalogs="[homer_lake_cold homer_lake_hot]"
INF Node: tiered storage DuckDB wired for merged search (hot+cold)
INF Coordinator: API server started addr=0.0.0.0:8080
INF Prometheus metrics server starting addr=http://0.0.0.0:9090/metrics
确认要点:
enabled modules四模块齐全;Volume attached name=cold ... path=s3://homer-data-cold是冷卷 attach 成功的标志——这行没出现就是扩展/网络问题(见常见问题 Q1);API server started addr=0.0.0.0:8080表示 Web/API 就绪。
TTL 分层服务也随之启动(每小时扫描一次热卷,符合 TTL_MOVE_INTERVAL_SEC=3600):
INF TieringService: TTL partition scan source=hot dest=cold max_data_age_days=2 partition_date_cutoff=2026-10-25 rule="partition date <= cutoff (inclusive); cutoff is calendar today minus max_data_age_days"
INF TieredStorageManager: Volume maintenance completed volume=cold lake=homer_lake_cold
版本复核:
docker compose exec homer /homer version
实测输出:
homer-core 11.0.369
built 2026-10-25 20:29:40, commit da04658, go go1.27.2, linux/amd64
4.5 Web UI 与 API 登录验证
Web UI 浏览器访问 http://<服务器IP>:8131/,命令行验证首页与登录 API:
curl -s -o /dev/null -w 'GET / -> %{http_code}\n' http://127.0.0.1:8131/
curl -s -X POST http://127.0.0.1:8131/api/v4/auth/sessions \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"q1w2e3r4"}'
实测返回(截取,JWT 为有效登录凭据):
GET / -> 200
{"data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWUsImlzcyI6ImhvbWVyLWNvcmUiLCJleHAiOjE3OTMxNjA0NjMsImlhdCI6MTc5MzA3NDA2MywianRpIjoiNDY1OTU0NTc5MjQyYmU0ODlkYTUzOWQ2YWFmNWEzYzgifQ.Hh-ESPTxDGw_HMsIAd6ufBuQqAKE1vQjQ9sza3SCc5s","scope":"admin","user":{"admi
登录后即可在 Web UI 中查看仪表盘与检索页面。注入 SIP 流量并检索验证的完整流程(heplify 采集 → sipsak 发包 → REST/CLI 检索)已在 《Ubuntu 22.04 安装 SIPCAPTURE Homer 11 指南》第五章实测闭环,HEP 投递地址改成本服务器的 9060 端口即可复用。
4.6 指标端点验证
curl -s http://127.0.0.1:9090/metrics | grep '^homer_' | head -3
实测输出(节选):
homer_ducklake_table_flush_duration_seconds_bucket{table="homer_lake.hep_proto_100_default",le="0.001"} 0
homer_ducklake_table_flush_duration_seconds_bucket{table="homer_lake.hep_proto_100_default",le="0.01"} 61
homer_ducklake_table_flush_duration_seconds_bucket{table="homer_lake.hep_proto_100_default",le="0.05"} 61
homer_* 指标正常输出即 Prometheus 端点可用。
五、数据持久化说明
5.1 两个命名数据卷
| 卷 | 服务内挂载点 | 内容 |
|---|---|---|
homer_data | /data/homer | DuckLake 数据湖:parquet/(热数据)、homer_catalog.sqlite(热卷 catalog)、homer_catalog_cold.sqlite(冷卷 catalog)、homer_settings.duckdb(用户/仪表盘等设置库)、.duckdb/extensions/(灌注的扩展)、.homer_jwt_secret 等密钥文件 |
rustfs_data | /data | RustFS 对象存储桶数据(含冷数据桶 homer-data-cold) |
实测 /data/homer 布局(docker compose exec homer ls -la /data/homer/):
drwxr-xr-x 5 homer homer 4096 Oct 27 04:07 .
drwxr-xr-x 3 root root 4096 Oct 25 20:29 ..
drwxr-xr-x 3 homer homer 4096 Oct 27 03:41 .duckdb
drwxr-xr-x 3 homer homer 4096 Oct 27 03:41 .duckdb_spill
-rw------- 1 homer homer 44 Oct 27 03:41 .homer_jwt_secret
-rw------- 1 homer homer 44 Oct 27 03:41 .homer_node_auth_token
-rw-r--r-- 1 homer homer 155648 Oct 27 03:41 homer_catalog.sqlite
-rw-r--r-- 1 homer homer 0 Oct 27 03:41 homer_catalog.sqlite.lock
-rw-r--r-- 1 homer homer 147456 Oct 27 03:41 homer_catalog_cold.sqlite
-rw-r--r-- 1 homer homer 12288 Oct 27 03:41 homer_settings.duckdb
-rw-r--r-- 1 homer homer 48048 Oct 27 03:41 homer_settings.duckdb.wal
drwxr-xr-x 3 homer homer 4096 Oct 27 03:41 parquet
5.2 备份与迁移要点
- 冷数据本体在
rustfs_data卷(即 S3 侧),元数据在homer_data卷的两个 catalog SQLite 文件——两者必须成对备份,只备 catalog 不备桶数据会丢冷数据; homer_settings.duckdb存用户与仪表盘,体量小、价值高,随卷备份即可;down -v会同时删除两个卷(含全部话单数据),生产操作用docker compose down(不带-v);- 需要绑定宿主目录而非命名卷时,把
volumes:段改为 bind mount(如./homer-data:/data/homer),属主仍须是 UID 1000。
六、环境变量表
官方镜像无内置配置文件,以下 HOMER_* 环境变量即该形态的全部配置面(值为本文实测生效值)。
模块开关:
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_INGEST_ENABLE | true | 启用采集模块(HEP 收包) |
HOMER_STORAGE_ENABLE | true | 启用存储模块(DuckLake writer) |
HOMER_NODE_ENABLE | true | 启用查询节点模块(50051/gRPC、/query) |
HOMER_COORDINATOR_ENABLE | true | 启用协调模块(API/Web UI/节点路由) |
采集(ingest):
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_INGEST_WORKER_COUNT | 8 | 收包工作协程数 |
HOMER_INGEST_QUEUE_SIZE | 80000 | 收包队列长度,溢出即丢包(见 metrics 计数) |
HOMER_INGEST_UDP_ENABLE / _HOST / _PORT | true / 0.0.0.0 / 9060 | HEP over UDP 监听 |
HOMER_INGEST_UDP_MULTICORE / HOMER_INGEST_TCP_MULTICORE | true | 多核收包(每核一 socket) |
HOMER_INGEST_TCP_ENABLE / _HOST / _PORT | true / 0.0.0.0 / 9060 | HEP over TCP 监听 |
HOMER_INGEST_TLS_ENABLE | false | HEP over TLS(9061),生产外网采集建议开启 |
HOMER_INGEST_HTTP_ENABLE / _HOST / _PORT | true / 0.0.0.0 / 9080 | HTTP/JSON 批量投递监听 |
HOMER_INGEST_HTTP_READ_TIMEOUT / _WRITE_TIMEOUT | 30 / 30 | HTTP 投递读写超时(秒) |
HOMER_INGEST_HTTP_WEBSOCKET_ENABLE | false | WebSocket 投递开关 |
HOMER_INGEST_HTTPS_ENABLE | false | HTTPS 投递开关 |
HOMER_INGEST_HEP_HEPV3_ENABLE | true | 接受 HEPv3(主流代理均用 v3) |
HOMER_INGEST_HEP_PROTOBUF_ENABLE | true | 接受 Protobuf 变体 |
存储(storage/ducklake):
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_STORAGE_DUCKLAKE_CATALOG_TYPE | sqlite | catalog 类型(SQLite 单文件,免外部数据库) |
HOMER_STORAGE_DUCKLAKE_CATALOG_PATH | /data/homer/homer_catalog.sqlite | 热卷 catalog 路径 |
HOMER_STORAGE_DUCKLAKE_DATA_PATH | /data/homer/parquet | Parquet 数据目录 |
HOMER_STORAGE_DUCKLAKE_LAKE_NAME | homer_lake | 湖仓名 |
HOMER_STORAGE_DUCKLAKE_BATCH_SIZE | 10000 | 内存缓冲行数,凑满即批量落盘 |
HOMER_STORAGE_DUCKLAKE_FLUSH_INTERVAL_SEC | 30 | 落盘周期(秒);小流量验证需等该周期(见 B1 篇排障 7.3) |
HOMER_STORAGE_DUCKLAKE_TUNING_MEMORY_LIMIT | 4GB | writer DuckDB 内存上限 |
HOMER_STORAGE_DUCKLAKE_TUNING_THREADS | 2 | writer DuckDB 线程数 |
HOMER_STORAGE_DUCKLAKE_TUNING_TEMP_DIRECTORY | /data/homer/.duckdb_spill | DuckDB 溢写临时目录 |
分层策略(storage_policy):
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_ENABLE | true | 启用冷热分层 |
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_TTL_MOVE_INTERVAL_SEC | 3600 | 搬迁扫描周期(秒) |
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_MOVE_FACTOR | 0.8 | 触发搬迁的容量因子 |
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_CONCURRENT_MOVES | 2 | 并发搬迁任务数 |
HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_MOVE_ON_STARTUP | true | 启动即执行一轮搬迁检查 |
..._VOLUMES_0_NAME/TYPE/PATH | hot / local / /data/homer/parquet | 热卷定义 |
..._VOLUMES_0_PRIORITY | 0 | 优先级,0 最热 |
..._VOLUMES_0_MAX_DATA_AGE_DAYS | 2 | 热卷数据最大保留天数(超过搬冷) |
..._VOLUMES_0_MAX_SIZE_GB | 100 | 热卷容量上限(GB) |
..._VOLUMES_1_NAME/TYPE/PATH | cold / s3 / s3://homer-data-cold | 冷卷定义(S3) |
..._VOLUMES_1_PRIORITY | 1 | 冷卷优先级 |
..._VOLUMES_1_MAX_DATA_AGE_DAYS | 0 | 0 = 冷卷永久保留 |
..._VOLUMES_1_S3_REGION | us-east-1 | S3 region(RustFS/MinIO 任意值即可) |
..._VOLUMES_1_S3_ACCESS_KEY_ID / _SECRET_ACCESS_KEY | rustfsadmin / rustfsadmin | S3 凭据(演示值,生产更换) |
..._VOLUMES_1_S3_ENDPOINT | http://rustfs:9000 | S3 端点(Compose 网络内服务名) |
..._VOLUMES_1_S3_USE_SSL | false | 是否 HTTPS 访问 S3 |
压实(compaction):
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_STORAGE_DUCKLAKE_COMPACTION_ENABLE | true | 启用后台压实(合并小 Parquet 文件) |
HOMER_STORAGE_DUCKLAKE_COMPACTION_CHECK_INTERVAL_SEC | 1800 | 压实检查周期(秒) |
HOMER_STORAGE_DUCKLAKE_COMPACTION_RETENTION_DAYS | 30 | 数据全局保留天数 |
HOMER_STORAGE_DUCKLAKE_COMPACTION_SNAPSHOT_EXPIRE_INTERVAL_SEC | 3600 | DuckLake 快照过期周期 |
HOMER_STORAGE_DUCKLAKE_COMPACTION_MIN_AGE_SEC | 3600 | 文件最短存活时间(秒),防止压实正在写入的文件 |
HOMER_STORAGE_DUCKLAKE_COMPACTION_MIN_FILE_SIZE_BYTES | 0 | 参与合并的最小文件字节数(0=不设下限) |
HOMER_STORAGE_DUCKLAKE_COMPACTION_MAX_FILE_SIZE_BYTES | 134217728 | 合并目标上限 128MB |
HOMER_STORAGE_DUCKLAKE_COMPACTION_MAX_COMPACTED_FILES | 100 | 单轮合并参与文件数上限 |
查询节点(node):
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_NODE_FLIGHT_SERVER_HOST / _PORT | 0.0.0.0 / 50051 | Airport gRPC 查询服务监听 |
HOMER_NODE_FLIGHT_SERVER_MAX_MESSAGE_SIZE | 16777216 | gRPC 单消息上限 16MB |
HOMER_NODE_DUCKLAKE_LAKE_NAME | homer_lake | 节点侧湖仓名 |
HOMER_NODE_DUCKLAKE_VOLUMES_0_* | hot 本地卷(含 catalog 路径) | 节点侧热卷(coordinator 查询合并用) |
HOMER_NODE_DUCKLAKE_VOLUMES_1_* | cold S3 卷(独立 catalog homer_catalog_cold.sqlite) | 节点侧冷卷 |
HOMER_NODE_DUCKLAKE_TUNING_THREADS | 2 | 节点侧 DuckDB 线程数 |
HOMER_NODE_DUCKLAKE_TUNING_TEMP_DIRECTORY | /data/homer/.duckdb_spill | 节点侧溢写目录 |
协调(coordinator):
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_COORDINATOR_HTTP_SERVER_ENABLE / _HOST / _PORT | true / 0.0.0.0 / 8080 | REST API + Web UI 监听 |
HOMER_COORDINATOR_HTTP_SERVER_STATIC_PATH | /usr/local/homer-core/dist | 内置 Web UI 静态资源路径 |
HOMER_COORDINATOR_NODES_0_NAME/HOST/PORT | local / 127.0.0.1 / 50051 | 查询节点清单(单机即本机回环) |
HOMER_COORDINATOR_NODES_0_FLIGHTSQL_PORT | 0 | FlightSQL 端口(0=关闭) |
HOMER_COORDINATOR_NODES_0_USE_TLS | false | 节点间 TLS |
HOMER_COORDINATOR_NODES_0_PRIORITY | 1 | 节点路由优先级 |
HOMER_COORDINATOR_SETTINGS_DB_PATH | /data/homer/homer_settings.duckdb | 设置库路径(必须指向可写卷,见 FAQ Q2) |
HOMER_COORDINATOR_JWT_EXPIRE_HOURS | 24 | 登录 JWT 有效期(小时) |
HOMER_COORDINATOR_AUTH_ADMIN_USER | admin | 管理员用户名 |
HOMER_COORDINATOR_AUTH_ADMIN_PASSWORD_HASH | 13a5c2…f2f9 | 管理员口令的 SHA-256 十六进制哈希 |
日志与指标:
| 环境变量 | 实测值 | 说明 |
|---|---|---|
HOMER_LOG_LEVEL | info | 日志级别(debug/info/warn/error/trace) |
HOMER_LOG_JSON | false | 结构化 JSON 日志开关 |
HOMER_LOG_OUTPUT_0 | stdout | 日志输出(_0 为输出列表索引) |
HOMER_PROMETHEUS_ENABLE | true | Prometheus 指标开关 |
HOMER_PROMETHEUS_HOST / _PORT / _PATH | 0.0.0.0 / 9090 / /metrics | 指标监听 |
💡 技术拓展:管理员口令存储方案上,Homer 11 采用不可逆的 SHA-256 哈希而非明文/盐值哈希。生成方式:
echo -n '你的口令' | sha256sum。本文演示口令q1w2e3r4的实测结果:13a5c202e320d0bf9bb2c6e2c7cf380a6f7de5d392509fee260b809c893ff2f9 -与环境变量值一致。生产环境务必替换为自定义口令的哈希。
七、配置参数说明
7.1 环境变量与 homer.json 的映射规则
HOMER_* 环境变量与 deb 安装形态的主配置文件 homer.json 是同一棵配置树的两种落地方式,映射规则:
HOMER_前缀后按下划线逐级展开为 JSON 路径,如HOMER_INGEST_UDP_PORT→ingest.udp.port;- 数组元素用
_数字_索引,如HOMER_STORAGE_DUCKLAKE_STORAGE_POLICY_VOLUMES_1_S3_ENDPOINT→storage.ducklake.storage_policy.volumes[1].s3.endpoint、HOMER_COORDINATOR_NODES_0_NAME→coordinator.nodes[0].name; - 日志输出列表同理:
HOMER_LOG_OUTPUT_0→log.output[0]。
官方提供 homer config show 子命令直接打印三来源合并后的生效配置(文件 + 环境变量 + 默认值)。在本文 Compose 栈(纯环境变量形态)上验证:
docker compose exec homer /homer config show --section storage.ducklake.batch_size --compact
实测输出 10000——正是环境变量 HOMER_STORAGE_DUCKLAKE_BATCH_SIZE 注入的值,而非内置默认 25000,证明环境变量已生效:
10000
deb 安装形态(homer.json 文件)上同命令的对照(ingest.udp.port 读自文件):
9060
7.2 两种配置形态的差异结论
| 维度 | Compose/镜像形态(本文) | deb/rpm 安装形态 |
|---|---|---|
| 配置载体 | 纯 HOMER_* 环境变量(镜像内无 homer.json) | /usr/local/homer-core/etc/homer.json |
| 配置生成 | 手写 Compose environment 段 | 复制 homer.json.example 后编辑,或 homer wizard 生成 |
| 生效方式 | docker compose up -d 重建服务 | 修改后 homer system --reload(SIGHUP)或重启服务 |
| 查看生效值 | homer config show(容器内) | homer config show |
同一字段两边等价可用;选型建议:容器化部署随 Compose 走环境变量(版本可控、声明式),二进制部署随 homer.json 走文件(可热重载)。参数语义的逐项详解见本专栏 C1 篇《SIPCAPTURE Homer 11 配置参数详解》。
八、配置文件挂载
8.1 本形态默认无需挂载配置文件
官方镜像把 Web UI 静态资源与二进制都打进镜像,配置经环境变量注入,因此 Compose 文件里没有 homer.json 挂载。需要挂载的只有两类目录/卷:
homer_data数据卷(第五章);./duckdb-extensions:/ext:ro——只读挂载给homer-init灌注扩展(宿主目录只进不退,服务本体不直接读它)。
8.2 如需用 homer.json 文件配置
坚持文件配置时,把编辑好的 homer.json 挂进容器并指定路径:
volumes:
- ./homer.json:/opt/homer/homer.json:ro
# 启动参数无法直接加,改用环境变量指定配置路径:
environment:
HOMER_CONFIG_PATH: /opt/homer/homer.json
⚠️ 注意:镜像形态的主线是环境变量配置;
--config-path参数与HOMER_CONFIG_PATH的组合行为以homer config show的输出为准(配置文件、环境变量、默认值三层合并后打印)。混合使用时建议只用一种来源,避免两层值不一致难以排查。
九、等价 docker run
不用 Compose 时,最小 all-in-one(本地盘、无冷层)等价于:
docker run -d --name homer-11-aio \
-p 8131:8080 -p 9060:9060/udp -p 9060:9060/tcp -p 9080:9080 -p 9090:9090 \
-e HOMER_INGEST_ENABLE=true -e HOMER_STORAGE_ENABLE=true \
-e HOMER_NODE_ENABLE=true -e HOMER_COORDINATOR_ENABLE=true \
-e HOMER_COORDINATOR_AUTH_ADMIN_USER=admin \
-e HOMER_COORDINATOR_AUTH_ADMIN_PASSWORD_HASH=13a5c202e320d0bf9bb2c6e2c7cf380a6f7de5d392509fee260b809c893ff2f9 \
-e HOMER_COORDINATOR_SETTINGS_DB_PATH=/data/homer/homer_settings.duckdb \
-v homer_data:/data/homer \
ghcr.io/sipcapture/homer:11.0.369
⚠️ 注意:docker run 形态没有
homer-init灌注作业,服务器需能直连 extensions.duckdb.org 由 DuckDB 首启自动拉取扩展;离线场景请改用本文 Compose 栈的灌注方案(3.3/4.1),或手工把扩展文件放进数据卷的.duckdb/extensions/v1.5.6/linux_amd64/后再启动。要复刻本文的 S3 冷层,还需另行准备对象存储并把第六章..._VOLUMES_1_*系列变量补全。
十、常用运维命令
# 查看栈状态
docker compose ps
# 跟踪 homer 日志
docker compose logs -f homer
# 改环境变量后重建 homer 服务
docker compose up -d --force-recreate homer
# 停止(保留数据卷)
docker compose down
# 停止并删除数据卷(危险:话单与设置全删)
docker compose down -v
# 进入 homer 执行 CLI(以查看版本为例)
docker compose exec homer /homer version
# 查看 DuckDB 版本(扩展目录 v1.5.6 的依据)
docker compose exec homer /homer system --duckdb-version
# 升级镜像:改 tag 后重建(数据卷保留;注意新版的 DuckDB 版本号可能变化,扩展需重新匹配下载)
# 1) 修改 docker-compose.yml 中 image 的 tag
# 2) 重新下载对应版本扩展并更新 homer-init 里的版本目录名
docker compose up -d
十一、常见问题
Q1:homer 服务启动失败,报 Failed to download extension "ducklake";或冷卷 Volume attached name=cold 迟迟不出现?
这是 DuckDB 扩展获取失败的两种表现。实测报错原文(docker compose logs homer):
Failed to create writer module: failed to create DuckLake manager: failed to create DuckLake sharded writer: failed to create shard 0: failed to load ducklake extension (run homer-core --install-extensions first): IO Error: Failed to download extension "ducklake" at URL "http://extensions.duckdb.org/v1.5.6/linux_amd64/ducklake.duckdb_extension.gz"
Extension "ducklake" is an existing extension.
For more info, visit https://duckdb.org/docs/stable/extensions/troubleshooting?version=v1.5.6&platform=linux_amd64&extension=ducklake (ERROR Failed to read connection)
根因:writer 模块建湖时 DuckDB 要加载 ducklake 扩展,服务器不通外网(或对 extensions.duckdb.org 下载受限)时自动下载失败,进程随即退出;S3 冷卷场景下 aws/httpfs 扩展缺失则表现为冷卷 attach 长时间挂起、Volume attached name=cold 不出现。解法即本文 3.3/4.1 的预灌注方案:把 5 个扩展文件预下载到 duckdb-extensions/,由 homer-init 灌注到数据卷后启动。实测灌注后完整栈(含 S3 冷卷)冷启动一次成功,4.4 节的 Volume attached name=cold 与冷卷维护日志即证据。可联网场景也可用官方自带的 homer system --install-extensions 预装扩展(ducklake、sqlite_scanner、httpfs、aws)。
Q2:报 failed to create settings db directory /var/lib/homer: permission denied?
设置库默认路径在 /var/lib/homer,而服务以 UID 1000 运行,该系统路径不可写。实测报错原文:
Failed to create coordinator module: failed to open settings db: failed to create settings db directory /var/lib/homer: mkdir /var/lib/homer: permission denied
解法:像本文 Compose 一样把 HOMER_COORDINATOR_SETTINGS_DB_PATH 指到可写数据卷(/data/homer/homer_settings.duckdb)。
Q3:扩展灌注了还是挂?
三点逐一核对:扩展版本目录必须与内置 DuckDB 版本一致(/homer system --duckdb-version 查看实测值,本文为 v1.5.6);目录结构必须是 .duckdb/extensions/v1.5.6/linux_amd64/;文件必须是解压后的 .duckdb_extension(.gz 原包不能直接用,见 4.1 的 gunzip 步骤)。
Q4:登录 API 返回 401?
口令哈希不匹配。Compose 形态的口令由 HOMER_COORDINATOR_AUTH_ADMIN_PASSWORD_HASH 决定,改口令 = 换成新口令的 SHA-256 哈希后 docker compose up -d --force-recreate homer。本文演示账号 admin/q1w2e3r4。
Q5:宿主端口被占 / 想改 Web 端口?
改 Compose ports: 冒号左侧宿主端口即可(本文 8131 对应服务内 8080),服务内端口不要动;9060 的 UDP/TCP 两条映射都要保留,否则 HEP 采集断链。
十二、参考链接
- 本专栏上一篇(单机安装路线):《Ubuntu 22.04 安装 SIPCAPTURE Homer 11 指南》
- 本专栏首篇(认知与选型):《SIPCAPTURE Homer 11.0.369 介绍与选型指南》
- 官方镜像:https://github.com/sipcapture/homer/pkgs/container/homer
- Releases 页(版本与镜像 tag 对照):https://github.com/sipcapture/homer/releases
- DuckDB 扩展官方仓库与文档:https://duckdb.org/docs/stable/extensions/official_extensions
- RustFS 项目:https://github.com/rustfs/rustfs