Apache Unomi 3.0.1 Docker Compose 部署指南
使用 Docker Compose 一键部署 Apache Unomi 3.0.1 与 Elasticsearch 9.5.3:提供自建镜像的 Dockerfile 与入口脚本、编排文件、数据持久化、环境变量表与常用运维命令,全程实测。
Apache Unomi 3.0.1 Docker Compose 部署指南
本文介绍以 Docker Compose 编排部署 Apache Unomi 3.0.1 与 Elasticsearch 9.5.3 的完整方案,包含自建镜像、编排文件、持久化与运维命令。全部文件与命令均在真实环境实测通过。
一、环境信息
| 项目 | 说明 |
|---|---|
| Apache Unomi | 3.0.1(自建镜像 unomi-local:3.0.1,实测 961MB) |
| Elasticsearch | 9.5.3(官方镜像 docker.elastic.co/elasticsearch/elasticsearch:9.5.3,实测 2.56GB) |
| 基础镜像 | eclipse-temurin:17-jre(Unomi 运行时) |
| Docker / Compose | 引擎 20.10+,Compose v2(实测版本 docker 29.8.0) |
| 部署目录 | /opt/unomi-compose |
| 端口映射 | 8181(cxs HTTP)、9443(cxs HTTPS)、9200(ES HTTP)、8102(Karaf 控制台,可选) |
| 管理账号 | karaf / q1w2e3r4 |
二、镜像选型说明
- Elasticsearch 直接使用官方镜像 docker.elastic.co/elasticsearch/elasticsearch:9.5.3。
- Apache Unomi 官方 Docker 仓库(apache/unomi)当前最新版本为 2.6.1,尚未提供 3.0.1 镜像;而 Unomi 3.0.1 要求 Elasticsearch 版本窗口 9.0.3-10.0.0 与 JDK 17。因此本文采用自建镜像方案:以 eclipse-temurin:17-jre 为基础,叠加官方发行包与启动入口脚本,构建 unomi-local:3.0.1。
- 自建镜像内置的入口脚本完成两件事:等待 Elasticsearch 健康后以前台模式启动 Karaf;循环执行
unomi:start完成首次初始化。这与裸机部署的关键差异在于:初始化无需人工介入。
三、前置条件
- 宿主机已安装 Docker 引擎与 Compose v2 插件(
docker compose version可正常输出)。 - 宿主机内核参数满足 ES 要求,执行并持久化:
sysctl -w vm.max_map_count=262144
echo "vm.max_map_count = 262144" > /etc/sysctl.d/99-elasticsearch.conf
- 磁盘可用空间不低于 4GB(两份镜像合计约 3.5GB,另需索引数据空间)。
- 已下载官方发行包 unomi-3.0.1-bin.tar.gz(https://dlcdn.apache.org/unomi/3.0.1/unomi-3.0.1-bin.tar.gz),SHA512 校验值:
99e1d9f729eb4adfe9288fdfd9d1ec6a35489dfa8c17e7658c1a08ceb550b1bca31646355c043cf59a926cca7f2a00d692d7ce59d95b318e1baaf11c311f1cc9
- 宿主机 8181、9443、9200 端口未被占用。
四、部署步骤
4.1 准备构建目录
mkdir -p /opt/unomi-compose
将 unomi-3.0.1-bin.tar.gz 放入 /opt/unomi-compose,并校验:
cd /opt/unomi-compose
sha512sum unomi-3.0.1-bin.tar.gz
回显应与第三节校验值一致。
4.2 编写 Dockerfile
在 /opt/unomi-compose 创建 Dockerfile:
FROM eclipse-temurin:17-jre
ADD unomi-3.0.1-bin.tar.gz /opt/
RUN mv /opt/unomi-3.0.1 /opt/unomi
COPY entrypoint.sh /opt/unomi/bin/entrypoint.sh
RUN chmod 755 /opt/unomi/bin/entrypoint.sh
WORKDIR /opt/unomi
EXPOSE 8181 9443 8102
ENTRYPOINT ["/opt/unomi/bin/entrypoint.sh"]
4.3 编写入口脚本 entrypoint.sh
在 /opt/unomi-compose 创建 entrypoint.sh:等待 ES 健康后前台启动 Karaf,并循环尝试执行 unomi:start 直至成功(首次初始化约需数分钟):
#!/bin/bash
schema='http'
if [ "$UNOMI_ELASTICSEARCH_SSL_ENABLE" = 'true' ]; then schema='https'; fi
health_url="$schema://${UNOMI_ELASTICSEARCH_ADDRESSES:-localhost:9200}/_cat/health?h=status"
health_check="$(curl -fsSL "$health_url" 2>/dev/null)"
until [ "$health_check" = 'yellow' ] || [ "$health_check" = 'green' ]; do
health_check="$(curl -fsSL "$health_url" 2>/dev/null)"
>&2 echo "Elasticsearch is not yet available - waiting (health check=$health_check)..."
sleep 2
done
/opt/unomi/bin/karaf server &
KARAF_PID=$!
i=0
until echo "unomi:start" | timeout 30 /opt/unomi/bin/client -u karaf -p "${UNOMI_ROOT_PASSWORD:-karaf}" >/dev/null 2>&1; do
i=$((i + 1))
if [ "$i" -ge 120 ]; then >&2 echo "unomi:start failed"; kill "$KARAF_PID"; exit 1; fi
sleep 5
done
>&2 echo "Apache Unomi services started"
wait "$KARAF_PID"
注意 client 调用必须携带 -u karaf -p 凭据(默认密码 karaf,与 UNOMI_ROOT_PASSWORD 保持一致)。
4.4 构建镜像
docker build -t unomi-local:3.0.1 /opt/unomi-compose
构建完成后确认:
docker images unomi-local
实测回显:
REPOSITORY TAG IMAGE ID CREATED SIZE
unomi-local 3.0.1 ab3318894cc1 2 hours ago 961MB
4.5 编写 docker-compose.yml
在 /opt/unomi-compose 创建 docker-compose.yml:
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:9.5.3
container_name: unomi-elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- cluster.name=contextElasticSearch
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:9200/_cluster/health || exit 1"]
interval: 15s
timeout: 10s
retries: 10
unomi:
image: unomi-local:3.0.1
container_name: unomi-server
environment:
- UNOMI_ROOT_PASSWORD=q1w2e3r4
- UNOMI_ELASTICSEARCH_ADDRESSES=elasticsearch:9200
- EXTRA_JAVA_OPTS=-Xms256M -Xmx512M -Dorg.apache.unomi.elasticsearch.sslEnable=false
ports:
- "8181:8181"
- "9443:9443"
- "8102:8102"
depends_on:
elasticsearch:
condition: service_healthy
volumes:
es-data:
要点说明:ES 集群名必须为 contextElasticSearch(Unomi 默认连接值);xpack.security.enabled=false 与 Unomi 默认无认证连接匹配;EXTRA_JAVA_OPTS 同时限定 Unomi 堆内存 256-512MB 并通过系统属性关闭 ES SSL 连接(发行包 cfg 默认 sslEnable=true,实测必须覆盖);unomi 服务以 condition: service_healthy 等待 ES 就绪后再启动。
4.6 启动编排
cd /opt/unomi-compose
docker compose up -d
查看状态(ES 需先通过 healthcheck):
docker compose ps
实测回显:
NAME IMAGE SERVICE STATUS
unomi-elasticsearch docker.elastic.co/elasticsearch/elasticsearch:9.5.3 elasticsearch Up (healthy)
unomi-server unomi-local:3.0.1 unomi Up
4.7 确认初始化完成
docker compose logs unomi | tail -3
实测回显关键行:
Apache Unomi services started
首次启动含 unomi:start 初始化,从 up 到该日志出现通常需要 3-8 分钟,期间 unomi-server 日志会反复输出 Elasticsearch 等待信息属正常现象。
4.8 验证部署
在 unomi-server 内调用 cxs REST 接口(请求体必须携带 sessionId):
docker exec unomi-server curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:8181/cxs/context.json -H 'Content-Type: application/json' -d '{"source":{"itemId":"home","itemType":"page","scope":"mysite"},"sessionId":"compose-session-001"}'
实测回显:
200
验证 HTTPS 集群接口(自签证书加 -k,Basic 认证使用 karaf / q1w2e3r4):
docker exec unomi-server curl -sk -u karaf:q1w2e3r4 -o /dev/null -w '%{http_code}\n' https://localhost:9443/cxs/cluster
实测回显:
200
宿主机与外部客户端直接访问 http://<服务器IP>:8181/cxs/context.json 同样可用(端口已映射)。
五、数据持久化说明
- Elasticsearch 数据(画像、事件、会话等全部业务数据)保存在命名卷 es-data(挂载于 /usr/share/elasticsearch/data),执行
docker compose down不会删除,docker compose down -v会连卷删除——生产环境慎用。 - unomi-server 内 /opt/unomi/data 仅包含 Karaf 运行缓存(felix cache)与日志,不存业务数据;重建 unomi 容器不丢失用户数据,入口脚本会在每次启动时自动重新完成 unomi:start 初始化(实测幂等)。
- 数据卷由 Compose 按项目命名管理(卷名带项目前缀),执行
docker volume ls查看;备份时挂载该卷打包即可,例如启动一个临时工具镜像挂载卷后执行 tar。
六、常用环境变量表
Unomi 镜像通过 custom.system.properties 内置的 ${env:UNOMI_XXX:-默认值} 映射支持环境变量注入(实测清单节选):
| 环境变量 | 说明 | 默认值 |
|---|---|---|
| UNOMI_ROOT_PASSWORD | Karaf 管理账号 karaf 的密码 | karaf |
| UNOMI_HTTP_PORT | cxs HTTP 端口 | 8181 |
| UNOMI_SECURE_HTTP_PORT | cxs HTTPS 端口 | 9443 |
| UNOMI_ELASTICSEARCH_ADDRESSES | ES 地址(Compose 中为服务名 elasticsearch:9200) | localhost:9200 |
| UNOMI_ELASTICSEARCH_CLUSTERNAME | ES 集群名 | contextElasticSearch |
| UNOMI_ELASTICSEARCH_USERNAME / UNOMI_ELASTICSEARCH_PASSWORD | ES 认证账号 | 空 |
| UNOMI_ELASTICSEARCH_SSL_ENABLE | 连接 ES 是否走 HTTPS(入口脚本据此选择健康检查协议) | — |
| UNOMI_ELASTICSEARCH_INDEXPREFIX | 索引名前缀 | context |
| UNOMI_CLUSTER_PUBLIC_ADDRESS | 对外公布地址 | http://localhost:8181 |
| UNOMI_CLUSTER_INTERNAL_ADDRESS | 节点间通信地址 | https://localhost:9443 |
| UNOMI_CLUSTER_NODEID | 节点 ID,多实例部署每份编排必须唯一 | unomi-node-1 |
| ES_JAVA_OPTS | ES 官方镜像 JVM 参数(本文设 512m 堆) | — |
| EXTRA_JAVA_OPTS | Unomi JVM 附加参数(本文设堆 256-512MB 并关闭 ES SSL 属性) | — |
七、常用配置参数说明
- 配置注入链路:环境变量 UNOMI_XXX → custom.system.properties 的
${env:UNOMI_XXX:-默认值}→ Karaf 系统属性 → etc/*.cfg 的属性替换。修改环境变量后执行docker compose up -d --force-recreate unomi重建生效。 - EXTRA_JAVA_OPTS 中的
-Dorg.apache.unomi.elasticsearch.sslEnable=false作用:发行包 cfg 中 sslEnable 的属性替换默认值为 true,系统属性优先级高于 cfg 默认值,实测以此方式关闭对 ES 的 HTTPS 连接。若自建镜像时已将 cfg 改为字面值 false,则该 -D 参数可省略。 - ES 侧参数通过 environment 直接注入官方镜像:discovery.type、xpack.security.enabled、cluster.name、ES_JAVA_OPTS,均实测有效。
八、配置文件持久化
如需深度定制,可仅挂载具体 cfg 文件到 unomi 容器(fileinstall 会监控加载),例如覆盖 ES 连接配置:
unomi:
volumes:
- ./org.apache.unomi.persistence.elasticsearch.cfg:/opt/unomi/etc/org.apache.unomi.persistence.elasticsearch.cfg:ro
也可以同样方式挂载 users.properties 注入账号密码。
重要警告(实测踩坑):不要挂载覆盖 /opt/unomi/etc/custom.system.properties——该文件包含端口定义(8181/9443)与全部 UNOMI_* 环境变量映射,覆盖后 HTTP 端口回落为 8080 且环境变量全部失效,8181 将无法访问。定制该文件时应先 docker cp unomi-server:/opt/unomi/etc/custom.system.properties . 取出原文件、修改后再整体挂载回去。
ES 侧如需固定 elasticsearch.yml,可从官方镜像取出 /usr/share/elasticsearch/config/elasticsearch.yml 修改后挂载。
九、等价 docker run 运行方式
不使用 Compose 时,以下命令与上述编排完全等价(实测组网逻辑一致):
docker network create unomi-net
docker run -d --name unomi-elasticsearch --network unomi-net -p 9200:9200 -e discovery.type=single-node -e xpack.security.enabled=false -e cluster.name=contextElasticSearch -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -v unomi-es-data:/usr/share/elasticsearch/data docker.elastic.co/elasticsearch/elasticsearch:9.5.3
docker run -d --name unomi-server --network unomi-net -p 8181:8181 -p 9443:9443 -p 8102:8102 -e UNOMI_ROOT_PASSWORD=q1w2e3r4 -e UNOMI_ELASTICSEARCH_ADDRESSES=elasticsearch:9200 -e EXTRA_JAVA_OPTS="-Xms256M -Xmx512M -Dorg.apache.unomi.elasticsearch.sslEnable=false" unomi-local:3.0.1
十、常用运维命令
docker compose ps
docker compose logs -f unomi
docker compose logs -f elasticsearch
docker compose restart unomi
docker compose stop
docker compose up -d
docker compose images
进入 Unomi 排障:
docker exec -it unomi-server /opt/unomi/bin/client -u karaf -p q1w2e3r4
进入后可执行 system:version、bundle:list、log:display 等 Karaf 命令,Ctrl+D 退出。完全下线并删除数据卷(危险,业务数据会丢失)使用 docker compose down -v。
十一、常见问题
**Q1:**unomi-server 一直输出 Elasticsearch is not yet available - waiting?
入口脚本在等 ES 健康。检查 elasticsearch 容器状态与日志:常见原因是宿主机 vm.max_map_count 低于 262144 导致 ES 启动失败,或 cluster.name 与 Unomi 侧不一致。宿主机执行 sysctl -w vm.max_map_count=262144 后 docker compose restart elasticsearch。
**Q2:**宿主机访问 8181 无响应,但容器内 8080 有服务? 挂载覆盖了 /opt/unomi/etc/custom.system.properties,端口定义与环境变量映射丢失所致。按第八节警告处理:恢复该文件或改为仅挂载具体 cfg 文件。
**Q3:**POST /cxs/context.json 返回 internalServerError?
Unomi 3.x 要求请求体携带 sessionId、profileId 或 personaId 之一,补齐 "sessionId":"demo-session-001" 后返回 200 并回显 profileId。
**Q4:**ES 启动失败,日志报 max virtual memory areas vm.max_map_count [65530] is too low? 在宿主机(而非容器内)执行内核参数调整并重启 ES 服务,见第三节与 Q1。
**Q5:**bin/client 连接报 Closed 或认证失败? 系统未完全启动时连接会被拒绝,等待初始化完成(日志出现 Apache Unomi services started);认证失败检查 UNOMI_ROOT_PASSWORD 与 -p 参数是否一致。
**Q6:**能否直接使用官方 apache/unomi:2.6.1 镜像? 可以,但那是 2.x 功能集:要求 JDK 11、ES 7.x/8.x,配置项与本篇 3.0.1 方案存在差异,需按 2.x 官方手册核对;需要 3.0.1 能力时仍应采用本文自建镜像方案。
**Q7:**如何调整 Unomi 堆内存?
修改 compose 中 EXTRA_JAVA_OPTS 的 -Xms/-Xmx(建议保持 256-512MB 区间)后执行 docker compose up -d --force-recreate unomi,并在容器内以 ps -ef | grep karaf.main.Main 验证回显中的堆参数。
十二、参考链接
- Apache Unomi 官方手册:https://unomi.apache.org/manual/latest/
- Apache Unomi 下载页:https://unomi.apache.org/download.html
- Elasticsearch 官方 Docker 文档:https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-with-docker
- Docker Compose 文档:https://docs.docker.com/compose/
- eclipse-temurin 镜像:https://hub.docker.com/_/eclipse-temurin