SIP3 2025.2.1 Docker Compose 部署指南
SIP3 2025.2.1 Docker Compose 部署指南:七组件编排、镜像模板渲染机制、JVM 内存调整、salto 模板缺陷排障与 SIP 采集闭环实测。
SIP3 2025.2.1 Docker Compose 部署指南
目标:在一台 Linux 服务器上用 Docker Compose 一键拉起 SIP3 社区版完整监控栈(Captain 抓包 + Salto 聚合 + Twig API + Hoof 界面 + MongoDB/InfluxDB/Grafana 三存储),完成 SIP 信令采集到界面检索的闭环验证。已在 Docker 29.9.2 + Docker Compose v5.6.1、网段 10.89.59.0/24、宿主端口 8134/8135/8136 的环境实测通过(实测日期 2026-10-27)。
一、环境信息
| 项目 | 内容 |
|---|---|
| 服务器 | 主机名 sip3-compose,内网地址 10.89.59.2(SIP 话务侧另有 10.89.59.1、10.89.59.10 作为信令源) |
| 操作系统 | Ubuntu Server 22.04 LTS(x86_64) |
| Docker | 29.9.2(docker --version 实测) |
| Docker Compose | v5.6.1(docker compose version 实测) |
| SIP3 版本 | 官方镜像 2025.2.1(Docker Hub sip3 命名空间最新可用版本,2026-10-26 实测 latest 标签即此版本,2025-07-07 推送) |
| 存储组件镜像 | mongo:7.0、influxdb:1.8、grafana/grafana:10.4.2 |
| 内部网络 | 自定义 bridge 网络 sip3-net,网段 10.89.59.0/24(本环境分配的专用网段槽) |
| 宿主端口规划 | 8134 → Hoof 界面(容器内 80);8135 → Twig API(容器内 8080);8136 → Grafana(容器内 3000) |
| 实测日期 | 2026-10-26 ~ 2026-10-27 |
版本路线必须先说清楚:SIP3 的 apt 软件源(repo.sip3.io)已发布到 2026.2.1,而官方镜像止步于 2025.2.1(2025.3.x 与 2026.x 均无官方镜像,《SIP3 2026.2.1 介绍与选型指南》2.2 节有逐渠道实测对照)。因此本文的镜像线部署版本为 2025.2.1——这是选择镜像路线的固有代价,换来的是不动宿主机系统包、一套 compose 文件整体启停的运维便利。两个版本的组件架构、配置模型、端口约定完全一致,2025.2.1 与 2026.2.1 的差异主要在 JVM 基线、Twig OAuth2/API key 增强与安全修复(见官方 Release Notes),不影响本文部署流程。
💡 技术拓展:SIP3 官方提供三条部署路径,各有取舍——
路径 版本 形态 适用场景 apt 软件源 + systemd 2026.2.1(最新) 每组件一个 systemd 服务,配置落 /etc/sip3-* 生产单机/多机、要最新版本 官方镜像 + Compose(本文) 2025.2.1 一套 compose 编排七组件 快速搭建、升级频繁、宿主不想装系统包 sip3-ansible release/2025.3.2 分支 playbook 按角色批量部署 多台服务器规模化管理 本文采用镜像路线验证整体功能;apt 路线的 2026.2.1 完整实测见《SIP3 2026.2.1 Ubuntu 22.04 安装指南》。
二、镜像选型说明
2.1 官方镜像清单
SIP3 四个 CE 组件在 Docker Hub sip3 命名空间下均有官方镜像,2026-10-26 实测清单如下:
| 镜像 | latest 版本 | 角色对外端口 | 说明 |
|---|---|---|---|
| sip3/sip3-captain-ce:2025.2.1 | 2025.2.1 | 无需对外(UDP 15060/15090 仅栈内) | libpcap 抓包代理,需要 NET_ADMIN/NET_RAW 权限 |
| sip3/sip3-salto-ce:2025.2.1 | 2025.2.1 | UDP 15060/15090 仅栈内 | 事件驱动聚合核心 |
| sip3/sip3-twig-ce:2025.2.1 | 2025.2.1 | HTTP 8080 | REST/OpenAPI 后端 |
| sip3/sip3-hoof-ce:2025.2.1 | 2025.2.1 | HTTP 80(nginx) | Web 界面,反代 /api 与 /grafana |
存储与展示依赖官方直接采用各自项目镜像:mongo:7.0(信令与呼叫数据)、influxdb:1.8(SIP3 写指标用的是 InfluxDB v1 HTTP API,必须 1.x,不能用 2.x/3.x)、grafana/grafana:10.4.2(仪表盘)。如何选型:四组件镜像只能用官方 sip3/ 命名空间(社区无维护分叉);存储镜像版本要与 SIP3 的读写接口匹配——MongoDB 用 5.0+ 均可(本文 7.0),InfluxDB 必须 1.8.x,Grafana 9/10/11 均可(本文 10.4.2)。
2.2 镜像内置的配置渲染机制
四个 SIP3 官方镜像共用同一个入口模式:启动时由 /usr/local/bin/prepare.sh 把 /etc/sip3-<组件>/ 下所有 .j2 Jinja2 模板用当前进程环境变量渲染成同名配置文件,再用渲染结果启动 Java 进程(Hoof 为 nginx,其 conf 同样经 Jinja2 渲染)。prepare.sh 的关键行为实测摘录(来自镜像内脚本原文):
# prepare.sh(镜像内置,摘录):
# env > /tmp/env
# for i in $(ls -1 /etc/$DAEMON/*.j2); do
# result=$(echo $i | rev | cut -c4- | rev)
# jinja2 $i /tmp/env --format=env > $result # 环境变量 -> Jinja2 变量 -> 渲染 .yml
# done
# JAVA_XMS 默认 -Xms512M;JAVA_XMX 默认 -Xmx1024M(可被启动参数覆盖)
# exec su sip3 -c "$JAVA_PATH $JAVA_XMS $JAVA_XMX $JAVA_OPTS ... -jar /opt/$DAEMON/$DAEMON.jar ..."
这意味着:部署阶段的所有配置项都通过环境变量传入(变量名与模板占位符一致,如 saltoServerUri、captainPcapDev),这既是镜像路线的便利,也埋着本文 11.1 那个排障案例的根因——模板缺陷只能靠挂载覆盖模板文件解决。
三、前置条件
3.1 软件与端口检查
确认 Docker 与 Compose 版本,并检查宿主端口 8134/8135/8136 未被占用:
root@sip3-compose:~# docker --version
Docker version 29.9.2, build a82e528
root@sip3-compose:~# docker compose version
Docker Compose version v5.6.1
root@sip3-compose:~# ss -ltn | grep -E ':813[4-6] '
root@sip3-compose:~#
ss 无输出即三个端口空闲。若被占用,在 compose 文件里同步改掉映射左值即可。
3.2 创建内部网络
先建好自定义 bridge 网络并指定网段(compose 文件按 external 网络引用,网络与编排解耦,便于多套栈复用同网段规划):
root@sip3-compose:~# docker network create --driver bridge --subnet 10.89.59.0/24 sip3-net
f012485b1be13965ebf019ca09022514858057dacbd87108da05f351850d14e4
root@sip3-compose:~# docker network ls | grep sip3-net
f012485b1be1 sip3-net bridge local
验证网段:
root@sip3-compose:~# docker network inspect sip3-net --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
10.89.59.0/24
3.3 建立项目目录
所有持久化数据与配置都收敛到 /opt/sip3-compose/(compose 项目目录,即后续 compose 文件所在目录):
root@sip3-compose:~# mkdir -p /opt/sip3-compose/{salto-conf,data/mongo,data/influxdb,data/grafana,grafana/provisioning/datasources,grafana/provisioning/dashboards}
root@sip3-compose:~# ls /opt/sip3-compose/
data grafana salto-conf
⚠️ 注意:Captain 需要
NET_ADMIN、NET_RAW两项能力(libpcap 抓包),compose 文件中必须声明cap_add,否则启动即报 Operation not permitted。
四、部署步骤
4.1 准备 Grafana 预置文件
Grafana 用「预置(provisioning)」方式在首次启动时自动创建 InfluxDB 数据源与 SIP3 仪表盘,无需手工在界面点配。写入数据源预置文件:
root@sip3-compose:~# cat > /opt/sip3-compose/grafana/provisioning/datasources/sip3-datasource.yml <<'EOF'
apiVersion: 1
deleteDatasources:
- name: Sip3
orgId: 1
datasources:
- name: Sip3
type: influxdb
access: proxy
url: http://influxdb:8086
database: sip3
withCredentials: false
isDefault: true
jsonData:
timeInterval: 1s
EOF
逐项说明:type: influxdb 声明数据源类型;url: http://influxdb:8086 用内部网络 DNS 名直连 InfluxDB;database: sip3 对应 InfluxDB 侧 INFLUXDB_DB: sip3 自动创建的库;timeInterval: 1s 匹配 Salto 指标的秒级步长。再写入仪表盘提供者预置文件:
root@sip3-compose:~# cat > /opt/sip3-compose/grafana/provisioning/dashboards/sip3-dashboard.yml <<'EOF'
apiVersion: 1
providers:
- name: 'Technical Dashboard'
orgId: 1
folder: ''
folderUid: ''
type: file
options:
path: /etc/grafana/provisioning/dashboards
EOF
仪表盘 JSON 文件(SIP3 官方 Grafana 仓库提供的 sip3-technical_dashboard.json 与 sip3-sip_metrics.json)放入同目录即可被上面 path 扫描加载。官方文件可从 sip3-documentation / sip3-grafana 仓库获取;若暂不放置 JSON,Grafana 仍会正常启动,只是 Dashboards 菜单为空,不影响呼叫搜索功能。
4.2 准备 Salto 配置模板
2025.2.1 的 Salto 镜像内置模板存在一处缺陷(详见 11.1),需先把内置模板取出、修正缺陷行、再放到挂载目录覆盖回去。先把镜像内模板导出:
root@sip3-compose:~# docker run --rm --entrypoint sh sip3/sip3-salto-ce:2025.2.1 -c 'cat /etc/sip3-salto/application.yml.j2' > /opt/sip3-compose/salto-conf/application.yml.j2
root@sip3-compose:~# wc -l /opt/sip3-compose/salto-conf/application.yml.j2
271 /opt/sip3-compose/salto-conf/application.yml.j2
再把模板中 unknown_raw 集合段的三行点号变量改为扁平环境变量名(其余段落本来就是扁平风格,不用动):
root@sip3-compose:~# sed -i \
-e 's/salto\.mongodb\.collections\.unknown_raw\.indexes\.ascending/saltoMongodbCollectionsUnknownRawIndexesAscending/' \
-e 's/salto\.mongodb\.collections\.unknown_raw\.indexes\.hashed/saltoMongodbCollectionsUnknownRawIndexesHashed/' \
-e 's/salto\.mongodb\.collections\.unknown_raw\.max_collections/saltoMongodbCollectionsUnknownRawMaxCollections/' \
/opt/sip3-compose/salto-conf/application.yml.j2
root@sip3-compose:~# grep -c 'salto\.mongodb\.' /opt/sip3-compose/salto-conf/application.yml.j2
0
grep -c 返回 0 即点号变量已清零,模板可直接进入 4.3 的挂载。
4.3 编写 docker-compose.yml
以下为完整的七组件编排文件(在 /opt/sip3-compose/docker-compose.yml 创建)。Captain 用固定 IP 10.89.59.20,方便话务侧把 SIP 流量发到确定地址:
name: sip3-2025.2.1-stack
services:
mongodb:
image: mongo:7.0
container_name: sip3-2025.2.1-mongodb
restart: unless-stopped
volumes:
- ./data/mongo:/data/db
networks:
sip3-net:
influxdb:
image: influxdb:1.8
container_name: sip3-2025.2.1-influxdb
restart: unless-stopped
environment:
INFLUXDB_DB: sip3
volumes:
- ./data/influxdb:/var/lib/influxdb
networks:
sip3-net:
grafana:
image: grafana/grafana:10.4.2
container_name: sip3-2025.2.1-grafana
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_PASSWORD: q1w2e3r4
volumes:
- ./data/grafana:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
ports:
- "8136:3000"
networks:
sip3-net:
salto:
image: sip3/sip3-salto-ce:2025.2.1
container_name: sip3-2025.2.1-salto
restart: unless-stopped
depends_on:
- mongodb
- influxdb
volumes:
- ./salto-conf/application.yml.j2:/etc/sip3-salto/application.yml.j2:ro
command: ["-Xms256m", "-Xmx512m"]
environment:
saltoName: sip3-salto
saltoServerUri: udp://0.0.0.0:15060
mongodbAddress: mongodb
mongodbPort: "27017"
mongodbDb: sip3
influxdbAddress: influxdb
influxdbPort: "8086"
influxdbDb: sip3
registerFeature: "true"
networks:
sip3-net:
twig:
image: sip3/sip3-twig-ce:2025.2.1
container_name: sip3-2025.2.1-twig
restart: unless-stopped
depends_on:
- mongodb
command: ["-Xms256m", "-Xmx512m"]
environment:
mongodbAddress: mongodb
mongodbPort: "27017"
mongodbDb: sip3
ports:
- "8135:8080"
networks:
sip3-net:
hoof:
image: sip3/sip3-hoof-ce:2025.2.1
container_name: sip3-2025.2.1-hoof
restart: unless-stopped
depends_on:
- twig
- grafana
environment:
twigAddress: twig
grafanaAddress: grafana
ports:
- "8134:80"
networks:
sip3-net:
captain:
image: sip3/sip3-captain-ce:2025.2.1
container_name: sip3-2025.2.1-captain
restart: unless-stopped
depends_on:
- salto
cap_add:
- NET_ADMIN
- NET_RAW
command: ["-Xms256m", "-Xmx512m"]
environment:
captainName: sip3-captain
captainPcapDev: eth0
captainPcapBpfFilter: "udp and port 5060"
captainSenderUri: udp://salto:15060
features: call,register
networks:
sip3-net:
ipv4_address: 10.89.59.20
networks:
sip3-net:
external: true
配置块逐项解说:
- name / container_name:compose 项目名与固定实例名,多套环境并存时一眼可辨。
- restart: unless-stopped:除手工 stop 外都自动拉起,配合 11.1 的故障自愈观察。
- depends_on:声明启动次序(存储先行、Salto 次之、Captain 最后);注意它只管启动顺序,应用层的就绪重连由 SIP3 自身完成(Captain/Salto 有内置重连机制,
captainSenderReconnectionTimeout默认 1000ms)。 - salto 的 volumes 挂载:把 4.2 的模板盖到镜像内置模板位置(只读),绕过 11.1 记录的 2025.2.1 内置模板缺陷。
- command: ["-Xms256m", "-Xmx512m"]:覆盖 prepare.sh 默认的
-Xms512M -Xmx1024M,把堆压到演示环境口径(三 Java 组件统一;生效验证见 7.2)。 - captain 的 cap_add:libpcap 抓包必需;
captainPcapDev: eth0抓内部网卡,BPF 只放行 UDP 5060。 - ipv4_address: 10.89.59.20:Captain 固定地址,话务侧可直接把 SIP 发到这个地址。
- networks.sip3-net.external: true:引用 3.2 预建的专用网络,compose 不再自建。
4.4 启动整套栈
root@sip3-compose:/opt/sip3-compose# docker compose up -d
首次执行会依次拉取七个镜像并按 depends_on 次序启动全部实例。该命令可重复执行(幂等),对已在运行中的栈再次执行时全部显示 Running、不做任何变更——实测回显:
root@sip3-compose:/opt/sip3-compose# docker compose up -d
Container sip3-2025.2.1-mongodb Running
Container sip3-2025.2.1-influxdb Running
Container sip3-2025.2.1-grafana Running
Container sip3-2025.2.1-salto Running
Container sip3-2025.2.1-twig Running
Container sip3-2025.2.1-hoof Running
Container sip3-2025.2.1-captain Running
4.5 状态核验
root@sip3-compose:/opt/sip3-compose# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
sip3-2025.2.1-captain sip3/sip3-captain-ce:2025.2.1 "/usr/local/bin/prep…" captain About an hour ago Up About an hour
sip3-2025.2.1-grafana grafana/grafana:10.4.2 "/run.sh" grafana About an hour ago Up About an hour 0.0.0.0:8136->3000/tcp, [::]:8136->3000/tcp
sip3-2025.2.1-hoof sip3/sip3-hoof-ce:2025.2.1 "/usr/local/bin/prep…" hoof About an hour ago Up About an hour 0.0.0.0:8134->80/tcp, [::]:8134->80/tcp
sip3-2025.2.1-influxdb influxdb:1.8 "/entrypoint.sh infl…" influxdb About an hour ago Up About an hour 8086/tcp
sip3-2025.2.1-mongodb mongo:7.0 "docker-entrypoint.s…" mongodb About an hour ago Up About an hour 27017/tcp
sip3-2025.2.1-salto sip3/sip3-salto-ce:2025.2.1 "/usr/local/bin/prep…" salto 36 minutes ago Up 36 minutes
sip3-2025.2.1-twig sip3/sip3-twig-ce:2025.2.1 "/usr/local/bin/prep…" twig About an hour ago Up About an hour 0.0.0.0:8135->8080/tcp, [::]:8135->8080/tcp
七个实例全部 Up 即部署就绪。Salto 的启动日志能看到渲染后的生效配置(排障时极有用):
root@sip3-compose:/opt/sip3-compose# docker logs sip3-2025.2.1-salto 2>&1 | head -14
==========================
Prepare config
==========================
Run sip3-salto : /opt/java/openjdk/bin/java -Xms256m -Xmx512m -Dlogback.configurationFile=/etc/sip3-salto/logback.xml -jar /opt/sip3-salto/sip3-salto.jar -Dconfig.location=/etc/sip3-salto/application.yml -Dcodecs.location=/etc/sip3-salto/codecs.yml -Dvertx.cacheDirBase=/tmp/sip3-salto
27-10-2026 03:38:01.927 [vert.x-eventloop-thread-1] INFO i.s.commons.vertx.AbstractBootstrap - Configuration:
{
"name" : "sip3-salto",
"version" : "2025.2.1-dbeb4cc",
"vertx" : {
"instances" : 1
},
"server" : {
"uri" : "udp://0.0.0.0:15060",
"buffer_size" : 65535
},
...
(输出节选(实测首尾):中段为完整生效配置 JSON,含 mongo/collections/metrics 全量段落。)
4.6 入口健康验证
三个对外入口逐一探活:
root@sip3-compose:/opt/sip3-compose# curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8134/ # Hoof 界面
200
root@sip3-compose:/opt/sip3-compose# curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8135/api/v3/api-docs # Twig OpenAPI 描述
200
root@sip3-compose:/opt/sip3-compose# curl -s http://localhost:8136/api/health
{
"commit": "701c851be7a930e04fbc6ebb1cd4254da80edd4c",
"database": "ok",
"version": "10.4.2"
}
三个入口 200/healthy 即整体可用。Twig 的 OpenAPI 描述(/api/v3/api-docs)是后续 API 对接的总入口,REST API 的逐端点实测见SIP3 2026.2.1 API 使用详解。
4.7 注入 SIP 信令验证采集闭环
从同网段话务侧主机(本环境为 10.89.59.10,任意装了 python3 的 Linux 主机均可)向 Captain 固定地址 10.89.59.20 的 5060 端口发一条 SIP INVITE:
root@pbx:~# python3 - <<'EOF'
import socket
msg = ("INVITE sip:1002@10.89.59.20 SIP/2.0\r\n"
"Via: SIP/2.0/UDP 10.89.59.10:5060;branch=z9hG4bK-b2test1\r\n"
"From: <sip:1001@10.89.59.10>;tag=abc123\r\n"
"To: <sip:1002@10.89.59.20>\r\n"
"Call-ID: b2-call-001@10.89.59.10\r\n"
"CSeq: 1 INVITE\r\n"
"Contact: <sip:1001@10.89.59.10:5060>\r\n"
"Max-Forwards: 70\r\n"
"Content-Length: 0\r\n\r\n")
socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(msg.encode(), ("10.89.59.20", 5060))
EOF
⚠️ 注意:发包主机必须与 Captain 处于同一路由可达网络,且从另一台主机发送——在本机向本机发包走回环口,
pcap.dev: eth0抓不到(与 apt 路线同源的坑,见 11.3)。
约 10 秒后在 MongoDB 中确认呼叫被聚合入库(按天分片集合,集合名 sip_call_index_<yyyyMMdd>):
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-mongodb mongosh --quiet sip3 --eval 'db.sip_call_index_20261027.find({}, {call_id:1, caller:1, callee:1, state:1, _id:0}).limit(2).forEach(printjson)'
{
call_id: 'b2-call-001@10.89.59.10',
caller: '1001',
callee: '1002',
state: 'unknown'
}
再经 Twig API 从数据面确认(limit 控制返回条数、fields 为附加返回字段):
root@sip3-compose:/opt/sip3-compose# curl -s -X POST -H 'Content-Type: application/json' \
-d '{"created_at":1793000000000,"terminated_at":1799900000000,"query":"sip.method=INVITE","limit":5,"fields":[]}' \
http://localhost:8135/api/search
[{"method":"INVITE","state":"unknown","caller":"1001","callee":"1002","duration":null,"fields":null,"created_at":1793072299769,"terminated_at":1793072304291,"call_id":["b2-call-001@10.89.59.10"],"error_code":null}]
采集闭环打通:抓包 → 聚合 → 入库 → API 可查。打开 Hoof 界面(http://10.89.59.2:8134/)在 Simple Search 输入 1001 应能搜到同一呼叫并查看 Call Flow。
五、数据持久化说明
三份关键数据全部 bind mount 落在项目目录,docker compose down 不删数据,重新 up -d 数据原样恢复:
| 数据 | 宿主目录 | 对应实例内路径 | 内容 |
|---|---|---|---|
| MongoDB | ./data/mongo | /data/db | 呼叫/注册索引与原始报文(sip3 库,按天分片集合) |
| InfluxDB | ./data/influxdb | /var/lib/influxdb | 服务指标时序(sip3 库) |
| Grafana | ./data/grafana | /var/lib/grafana | 仪表盘/数据源/账号状态 |
备份直接落文件即可(先落盘快照更稳妥):
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-mongodb sh -c 'mongodump --db sip3 --archive 2>/tmp/dump.log > /dev/null; head -4 /tmp/dump.log'
2026-10-27T04:20:40.835+0000 writing `sip3.attributes_20261027` to `archive on stdout`
2026-10-27T04:20:40.835+0000 writing `sip3.components` to `archive on stdout`
2026-10-27T04:20:40.835+0000 writing `sip3.sip_call_index_20261027` to `archive on stdout`
2026-10-27T04:20:40.836+0000 writing `sip3.sip_call_raw_20261027` to `archive on stdout`
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-mongodb mongodump --db sip3 --archive > ./sip3-mongo-backup.archive
root@sip3-compose:/opt/sip3-compose# ls -lh sip3-mongo-backup.archive
-rw-r--r-- 1 root root 35K Oct 27 12:20 sip3-mongo-backup.archive
⚠️ 注意:
docker compose down -v的-v只清理命名卷,bind mount 目录不受影响;反过来,rm -rf ./data/*会直接删库,操作前务必确认目录指向。
六、环境变量表
镜像线的配置入口就是环境变量。按实例分列本文用到或需要了解的关键变量:
| 实例 | 变量 | 本文取值 | 说明 |
|---|---|---|---|
| mongodb | (无 SIP3 相关) | — | mongo:7.0 镜像自身变量不涉及 |
| influxdb | INFLUXDB_DB | sip3 | 首次启动自动建库,Salto 写指标依赖它 |
| grafana | GF_SECURITY_ADMIN_PASSWORD | q1w2e3r4 | Grafana 管理员 admin 的密码 |
| salto | saltoName | sip3-salto | 组件自报名 |
| salto | saltoServerUri | udp://0.0.0.0:15060 | 数据接收端口,监听全部网卡 |
| salto | mongodbAddress / mongodbPort / mongodbDb | mongodb / 27017 / sip3 | 呼叫数据落库三件套 |
| salto | influxdbAddress / influxdbPort / influxdbDb | influxdb / 8086 / sip3 | 指标落库三件套 |
| salto | registerFeature | "true" | 渲染 sip_register_* 集合段并放宽 REGISTER 排除 |
| twig | mongodbAddress / mongodbPort / mongodbDb | mongodb / 27017 / sip3 | 查询侧只读连接 |
| hoof | twigAddress | twig | nginx 反代 /api 指向 Twig |
| hoof | grafanaAddress | grafana | nginx 反代 /grafana 指向 Grafana |
| captain | captainName | sip3-captain | 组件自报名 |
| captain | captainPcapDev | eth0 | 抓包网卡 |
| captain | captainPcapBpfFilter | udp and port 5060 | BPF 过滤器 |
| captain | captainSenderUri | udp://salto:15060 | 数据出口,指向 Salto |
| captain | features | call,register | 特性开关清单 |
可用变量远不止上表:Salto 模板暴露约 90 个变量(saltoSipCallAggregationTimeout、saltoMongodbCollectionsSipCallIndexMaxCollections、saltoMediaRtpRAggregationTimeout 等),Captain 约 60 个(captainPcapSnaplen、captainEncoderMtuSize、captainRtpCollectorEnabled 等),Twig 约 26 个(twigSessionDefaultLimit、twigMongodbBatchSize 等),Hoof 另有 hoofPort、hoofServerName、twigServerPort、twigServerServletContextPath 控制反代细节。命名规律为「组件名 + 配置段驼峰拼接」,逐项含义见SIP3 2026.2.1 配置参数详解(配置键与镜像变量一一对应)。
七、配置参数说明
7.1 JVM 堆内存
四个镜像中三个是 Java 进程(Captain/Salto/Twig),prepare.sh 默认堆为 -Xms512M -Xmx1024M。演示环境在 compose 的 command 里压到 -Xms256m -Xmx512m。生效验证(三个实例逐一执行,回显一致):
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-captain ps -ef | grep -o '\-Xms\S* -Xmx\S*'
-Xms256m -Xmx512m
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-salto ps -ef | grep -o '\-Xms\S* -Xmx\S*'
-Xms256m -Xmx512m
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-twig ps -ef | grep -o '\-Xms\S* -Xmx\S*'
-Xms256m -Xmx512m
生产环境按话务量调大 command 中的 -Xmx 即可(如 -Xmx2g),改后 docker compose up -d 重建实例生效,并用同样命令复核。
7.2 渲染产物与排障入口
环境变量渲染出的最终配置在实例内 /etc/sip3-<组件>/application.yml(模板为同名 .j2)。Salto 实例内文件布局实测:
root@sip3-compose:/opt/sip3-compose# docker exec sip3-2025.2.1-salto ls /etc/sip3-salto/
application.yml
application.yml.j2
codecs.yml
logback.xml
vertx-options.json
vertx-options.json.j2
排障时对照「模板 → 渲染产物 → 启动日志 Configuration JSON」三层即可定位任何一个配置项是否生效。
八、配置文件挂载
| 挂载 | 读写 | 用途 |
|---|---|---|
| ./salto-conf/application.yml.j2 → /etc/sip3-salto/application.yml.j2 | :ro | 覆盖镜像内置 Salto 模板(11.1 缺陷规避) |
| ./grafana/provisioning → /etc/grafana/provisioning | :ro | 数据源与仪表盘预置(4.1) |
若需要把某个组件的整套配置改为纯手工维护,同样用只读挂载把渲染产物也盖掉并移除模板渲染依赖——但更推荐维持「环境变量进、模板渲染出」的镜像线原味,只在模板缺陷时做点状覆盖。
九、等价 docker run
compose 文件中的关键服务可用等价 docker run 单独起(以 Captain 为例,便于单实例调试)。栈内常驻 Captain 已占用固定 IP 10.89.59.20,调试实例改用 10.89.59.21:
root@sip3-compose:~# docker run -d \
--name sip3-2025.2.1-captain-run \
--network sip3-net --ip 10.89.59.21 \
--cap-add NET_ADMIN --cap-add NET_RAW \
-e captainName=sip3-captain \
-e captainPcapDev=eth0 \
-e "captainPcapBpfFilter=udp and port 5060" \
-e captainSenderUri=udp://salto:15060 \
-e features=call,register \
sip3/sip3-captain-ce:2025.2.1 \
-Xms256m -Xmx512m
8a9b60231a4c7dd6de3b6e29cd629bcfd8100130350cf0207215b6774c451451
root@sip3-compose:~# docker ps --filter name=sip3-2025.2.1-captain-run --format '{{.Names}} {{.Status}}'
sip3-2025.2.1-captain-run Up 28 seconds
root@sip3-compose:~# docker exec sip3-2025.2.1-captain-run ps -ef | grep -o '\-Xms\S* -Xmx\S*'
-Xms256m -Xmx512m
调试完成后删除该实例:docker rm -f sip3-2025.2.1-captain-run。Salto/Twig/Hoof 的等价命令同理替换镜像名与环境变量。日常编排仍建议统一走 compose,docker run 形态用于临时验证单个组件行为。
十、常用运维命令
root@sip3-compose:/opt/sip3-compose# docker compose ps # 栈内实例与端口总览
root@sip3-compose:/opt/sip3-compose# docker compose logs -f salto # 跟踪 Salto 日志(启动配置 JSON 在最前)
root@sip3-compose:/opt/sip3-compose# docker compose restart captain # 重启单个组件
root@sip3-compose:/opt/sip3-compose# docker compose stop && docker compose start # 整栈停/启(数据保留)
root@sip3-compose:/opt/sip3-compose# docker compose down # 整栈下线(bind mount 数据保留)
root@sip3-compose:/opt/sip3-compose# docker compose pull # 升级前拉新镜像
升级方法:把 compose 文件中的镜像 tag 从 2025.2.1 改为目标 tag(以官方 Docker Hub 实际发布为准,2026-10-26 实测尚无 2025.3.x/2026.x 镜像),docker compose pull && docker compose up -d 滚动重建。回滚把 tag 改回旧值执行同样两步;数据目录不变即自动兼容(集合分片按日期命名,跨版本同构)。
十一、常见问题(FAQ)
11.1 Salto 反复重启(Restarting)
现象:仅用环境变量 + 镜像内置模板时,docker compose ps 中 salto 长期处于 Restarting 状态,启动阶段渲染配置失败退出、被 restart 策略反复拉起。
定位:把镜像内置模板与官方 sip3-ansible 工程 release/2025.3.2 的同名模板对比,发现两个渲染上下文使用的变量风格不同——ansible 模板全文用点号变量(salto.name、salto.server.uri,对应 playbook 变量树),镜像模板全文用扁平环境变量风格(saltoName、saltoServerUri,对应 prepare.sh 的 --format=env 渲染)。而 2025.2.1 镜像内置模板的 unknown_raw 集合段混入了三行点号写法,与镜像的渲染上下文不兼容:
# 镜像内置模板(缺陷行)
- ascending: {{ salto.mongodb.collections.unknown_raw.indexes.ascending | default('[created_at]') }}
- hashed: {{ salto.mongodb.collections.unknown_raw.indexes.hashed | default('[call_id]') }}
- max_collections: {{ salto.mongodb.collections.unknown_raw.max_collections | default('30') }}
# 修正后(与全文扁平风格统一)
+ ascending: {{ saltoMongodbCollectionsUnknownRawIndexesAscending | default('[created_at]') }}
+ hashed: {{ saltoMongodbCollectionsUnknownRawIndexesHashed | default('[call_id]') }}
+ max_collections: {{ saltoMongodbCollectionsUnknownRawMaxCollections | default('30') }}
(上述 diff 为镜像内置模板与修正后模板的实际 diff 输出,全文仅此三行不一致。)
规避:按 4.2 的三步走——导出内置模板、sed 修正三行点号变量、挂载覆盖回 /etc/sip3-salto/application.yml.j2,同时保留 mongodbAddress/saltoServerUri 等环境变量。修正后 Salto 稳定 Up,启动日志正常打印生效配置(见 4.5)。该缺陷属 2025.2.1 镜像打包问题,升级镜像 tag 后应先用 4.2 的 grep -c 'salto\.mongodb\.' 复查新模板,命中为 0 才可移除挂载。
11.2 访问 /api/sessions 报 404/500
Twig 没有 /api/sessions 这个路径(不少资料以讹传讹)。正确的检索端点是 POST /api/search(请求体含 created_at/terminated_at/query/limit/fields),错误路径实测 2025.2.1 镜像线返回 404、2026.2.1 deb 路线返回 500。完整 API 面(含 /api/session/details、/api/session/flow、/api/session/pcap 等 20 个端点)与请求体形态见SIP3 2026.2.1 API 使用详解。
11.3 Captain 起来了但抓不到呼叫
按序检查三点:
- 发包主机:本机发本机走回环口,
captainPcapDev: eth0抓不到,必须从另一台主机发测试流量; - BPF 过滤器:
udp and port 5060只放行 5060 端口,话务环境 SIP 端口不同时要同步改; - 数据出口:
captainSenderUri必须指向 Salto 的 15060(compose 内用 DNS 名salto),可用docker compose logs salto观察是否收到注册与数据。
11.4 端口冲突
宿主端口 8134/8135/8136 被占用时改 compose 中 ports 的左值即可;Salto 的 UDP 15060/15090 仅在内部网络使用,不占宿主端口。
十二、参考链接
- 官网:https://sip3.io
- 官方镜像:https://hub.docker.com/u/sip3
- GitHub 组织:https://github.com/sip3io
- sip3-ansible(模板来源):https://github.com/sip3io/sip3-ansible
- 官方文档:https://sip3.io/documentation/
- 本专栏选型篇:https://www.quzuo.net/document/C5WeLhZIbIpK
- 本专栏 apt 安装篇:https://www.quzuo.net/document/sk2pjogv1eNG
- 本专栏配置篇:https://www.quzuo.net/document/Ws3fH3mFueEd
- 本专栏 API 篇:https://www.quzuo.net/document/0Oxnl7ike1iB