SIP3 2025.2.1 Docker Compose 部署指南

SIP3 2025.2.1 Docker Compose 部署指南:七组件编排、镜像模板渲染机制、JVM 内存调整、salto 模板缺陷排障与 SIP 采集闭环实测。

SIP3SIPVoIPSIP32026/10/27

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)
Docker29.9.2(docker --version 实测)
Docker Composev5.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 软件源 + systemd2026.2.1(最新)每组件一个 systemd 服务,配置落 /etc/sip3-*生产单机/多机、要最新版本
官方镜像 + Compose(本文)2025.2.1一套 compose 编排七组件快速搭建、升级频繁、宿主不想装系统包
sip3-ansiblerelease/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.12025.2.1无需对外(UDP 15060/15090 仅栈内)libpcap 抓包代理,需要 NET_ADMIN/NET_RAW 权限
sip3/sip3-salto-ce:2025.2.12025.2.1UDP 15060/15090 仅栈内事件驱动聚合核心
sip3/sip3-twig-ce:2025.2.12025.2.1HTTP 8080REST/OpenAPI 后端
sip3/sip3-hoof-ce:2025.2.12025.2.1HTTP 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 镜像自身变量不涉及
influxdbINFLUXDB_DBsip3首次启动自动建库,Salto 写指标依赖它
grafanaGF_SECURITY_ADMIN_PASSWORDq1w2e3r4Grafana 管理员 admin 的密码
saltosaltoNamesip3-salto组件自报名
saltosaltoServerUriudp://0.0.0.0:15060数据接收端口,监听全部网卡
saltomongodbAddress / mongodbPort / mongodbDbmongodb / 27017 / sip3呼叫数据落库三件套
saltoinfluxdbAddress / influxdbPort / influxdbDbinfluxdb / 8086 / sip3指标落库三件套
saltoregisterFeature"true"渲染 sip_register_* 集合段并放宽 REGISTER 排除
twigmongodbAddress / mongodbPort / mongodbDbmongodb / 27017 / sip3查询侧只读连接
hooftwigAddresstwignginx 反代 /api 指向 Twig
hoofgrafanaAddressgrafananginx 反代 /grafana 指向 Grafana
captaincaptainNamesip3-captain组件自报名
captaincaptainPcapDeveth0抓包网卡
captaincaptainPcapBpfFilterudp and port 5060BPF 过滤器
captaincaptainSenderUriudp://salto:15060数据出口,指向 Salto
captainfeaturescall,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 起来了但抓不到呼叫

按序检查三点:

  1. 发包主机:本机发本机走回环口,captainPcapDev: eth0 抓不到,必须从另一台主机发测试流量;
  2. BPF 过滤器:udp and port 5060 只放行 5060 端口,话务环境 SIP 端口不同时要同步改;
  3. 数据出口:captainSenderUri 必须指向 Salto 的 15060(compose 内用 DNS 名 salto),可用 docker compose logs salto 观察是否收到注册与数据。

11.4 端口冲突

宿主端口 8134/8135/8136 被占用时改 compose 中 ports 的左值即可;Salto 的 UDP 15060/15090 仅在内部网络使用,不占宿主端口。

十二、参考链接