MistServer 3.12 Docker Compose 部署指南
基于 ddvtech/mistserver:3.12 官方发行版实测:compose 编排与 shm_size 硬前置、4242 首启向导建号、RTMP/RTSP 推流与 HLS/DASH/VoD 拉流全链路验证及排障。
MistServer 3.12 Docker Compose 部署指南
目标:在一台 Linux 服务器上用官方发行版 ddvtech/mistserver:3.12 完成多协议流媒体服务从零到一的部署:编排文件逐行说明、首次启动向导(建号 + 协议连接器)、RTMP/RTSP 推流与 HLS/DASH 拉流全链路验证,以及部署期最常见的共享内存与端口路由问题排障。本文所有命令与回显均在 2026-10-30 的实测中逐条执行验证。
本文是 MistServer 系列的第二篇。第一篇《MistServer 3.12 介绍与选型指南》讲清了"它是什么、协议矩阵有多宽、适不适合你",本篇解决"怎么把它跑起来"。流媒体源站的搭建与转推场景如果需要一套轻量参考,可以对照阅读 《MediaMTX 1.21.3 Docker Compose 部署指南》,两篇的验证方法(推流、拉流、冒烟三件套)保持了同一套范式,方便横向比较。
一、环境信息
| 项目 | 值 |
|---|---|
| 组件版本 | MistServer 3.12(2026-10-05 发布,官方 GitHub Releases,2026-10-30 实查) |
| 发行形态 | 官方 Docker 发行版 ddvtech/mistserver:3.12(Docker Hub,2026-10-30 实查) |
| 服务器系统 | Linux x86_64(内核 6.x) |
| 管理界面 | 4242 端口(Web UI 与 Management API 同口) |
| 协议端口 | 1935 RTMP、5554 RTSP、8080 HTTP(HLS/DASH/WebRTC 元数据)、8889/udp 与 18203/udp |
| 实测日期 | 2026-10-30 |
3.12 的管理口在首次启动时只有一个 4242 在监听——RTMP、HTTP 等协议监听口都要在管理界面(或 API)里显式启用后才会拉起,这是 3.x 的明确设计。所以本篇的部署步骤里"首启向导"不是可跳过的形式,而是协议服务真正对外服务的开关。
二、部署形态与资源预算
2.1 官方发行版的两种形态
官方在下载页与 Docker Hub 提供两类镜像形态(mistserver.org/download,2026-10-29 查询):
- 含操作系统的完整形态:内置 Ubuntu 基座,可以用脚本、可以进服务排障,官方 Docker 文档的示例命令默认指向这类;
- 纯二进制精简形态:只打包 MistServer 全套可执行文件,体积更小,但里面没有 shell 工具链,无法在运行环境内补装分析工具。
两种形态的入口一致:进程以 MistController 为核心,配置持久化在 /config.json 单文件。本篇采用完整形态 ddvtech/mistserver:3.12,实测排障时需要在运行环境里看进程列表、查日志,完整形态更合适。
2.2 共享内存:必须显式配置的硬前置
MistServer 的进程模型依赖 POSIX 共享内存交换数据:每条流的每个轨道默认申请 40MB 共享内存环形缓冲。而默认共享内存只有 64MB——这是本系列实测踩到的第一个故障,首启日志里 MistController 会直接警告:
[2026-10-30 04:30:18] WARN: You have very little shared memory available (63 MiB). Mist heavily relies on shared memory: please ensure your shared memory is set to a high value, preferably ~95% of your total available RAM.
[2026-10-30 04:30:18] WARN: Tip: If you are using docker, e.g. add the `--shm-size=15143m` parameter to your `docker run` command to fix this.
(日志节选自实测首启输出。)
共享内存预算公式(实测数据推导):
/dev/shm ≥ 并发流数 × 平均轨道数 × 40MB + 元数据余量
10 路音视频双轨直播流 = 10 × 2 × 40MB = 800MB。实验与中小规模生产建议直接 shm_size: "1gb";更大规模按公式放大。官方文档也强调默认 64MB "barely enough to do anything"(mistserver.org 文档 Docker 章节,2026-10-29 查询)。
2.3 端口规划
本篇实测端口矩阵(宿主侧统一用 81xx 高位段,规避与既有服务冲突):
| 宿主端口 | 服务端口 | 协议用途 |
|---|---|---|
| 8132 | 4242/tcp | Web 管理界面 + Management API |
| 8133 | 8080/tcp | HTTP 输出:HLS(/hls/)、CMAF/DASH(/cmaf/)、WebRTC 播放页与元数据 |
| 8135 | 1935/tcp | RTMP 收流/推流 |
| 8139 | 5554/tcp | RTSP 收流/推流 |
| 8140 | 8889/udp | SRT(TSSRT 连接器,默认 UDP 8889) |
| 8141 | 18203/udp | WebRTC(SRTP UDP socket,默认 UDP 18203) |
规划原则:4242 是管理面,不要暴露公网;8080 是 HTTP 家族的总入口(3.x 用路径前缀区分 HLS/DASH/WebRTC,见 4.4 节实测);UDP 端口(8889、18203)发布时必须带 /udp 后缀,漏写后缀会被按 TCP 解析导致对应协议拉流失败——这是编排文件最容易抄错的一行。两个 UDP 口的默认值来自连接器能力清单(capabilities)的实测读回:TSSRT 连接器默认 port: 8889、WebRTC 连接器默认 port: 18203。
三、前置条件
- 服务器已安装 Docker 与 Docker Compose v2(
docker compose version可执行); - 宿主 8132/8133/8135/8139/8140/8141 六个端口空闲:
ss -ltnp | grep -E '8132|8133|8135|8139'确认无占用(UDP 口用ss -lunp查); - 准备持久化目录:管理配置单文件与 VoD 媒体目录,本篇统一放工作数据目录(示例为
/opt/mistserver,读者可按自己的目录规范替换):
mkdir -p /opt/mistserver/data /opt/mistserver/vod
touch /opt/mistserver/data/config.json
- (可选)准备一个测试用 MP4 文件放入
vod/,本篇用testvod.mp4(640×360、25fps、含 AAC 音轨,时长约 10 秒)演示 VoD 点播流。
四、部署步骤
4.1 编写 docker-compose.yml
在 /opt/mistserver/ 下编写编排文件。项目名显式声明为 mistserver-3.12-stack——多套流媒体服务并行部署时,统一规范的项目名能避免操作互相误伤:
name: mistserver-3.12-stack
services:
mistserver:
image: ddvtech/mistserver:3.12
container_name: mistserver-3.12-app
restart: unless-stopped
shm_size: "1gb"
ports:
- "8132:4242" # Web 管理界面 / Management API
- "8133:8080" # HTTP:HLS / CMAF(DASH) / WebRTC 播放页
- "8135:1935" # RTMP 收流/推流
- "8139:5554" # RTSP 收流/推流
- "8140:8889/udp" # SRT(TSSRT 连接器默认 UDP 8889)
- "8141:18203/udp" # WebRTC(SRTP UDP socket 默认 18203)
volumes:
- /opt/mistserver/data/config.json:/config.json
- /opt/mistserver/vod:/vod
networks:
- mistserver-net
networks:
mistserver-net:
name: mistserver-3.12-net
driver: bridge
逐行说明:
name: mistserver-3.12-stack:Compose 项目名,所有资源(网络、服务)以它为前缀,docker compose down只影响本项目;shm_size: "1gb":共享内存上限,2.2 节的硬前置。漏掉它,流会拉不起来且日志只有一句模糊提示;ports六行:TCP 四个 + UDP 两个。8140、8141两行若漏写/udp,启动时映射类型错误;volumes两行:/config.json是 MistServer 唯一的持久化状态(账号、协议连接器、流配置全在里面,实测确认它由服务进程自动写回);/vod挂载点播素材,容器内路径与流配置的 source 一一对应(4.4 节 VoD 流的 source 就是/vod/testvod.mp4);networks:显式命名网络,避免 Compose 用项目名哈希生成随机网络名。
💡 技术拓展:同样是"官方 Docker 发行版",流媒体服务器的端口暴露策略与普通 Web 服务不同。普通服务暴露一个 HTTP 口即可;流媒体服务器是"多协议多端口"形态——RTMP(1935)、RTSP(5554)、HTTP 家族(8080)、WebRTC(8889/udp)各自独立监听。另一种极端做法是宿主网络模式(官方文档对 Linux 推荐
--network=host):省去端口映射、UDP 类协议(WebRTC/SRT)配置更简单,代价是没有端口隔离层、端口冲突要自己兜底。本篇选端口映射模式:端口收敛可控,且便于和反向代理配合;如果后续要上 WebRTC 大规模并发或 SRT 广电流,再评估切宿主网络模式。
4.2 启动与首启确认
cd /opt/mistserver
docker compose up -d
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE STATUS
mistserver-3.12-app ddvtech/mistserver:3.12 "/usr/local/bin/Mist…" mistserver Up 4 seconds
启动后先看首启日志,确认服务自身状态与共享内存告警是否出现:
docker compose logs mistserver | head -20
实测回显(节选):
mistserver-3.12-app | [2026-10-30 04:30:18] CONF: No login configured. No protocols enabled. No streams configured. This can be configured through the web interface on port 0 or through the API
mistserver-3.12-app | [2026-10-30 04:30:18] CONF: Controller started
Controller started 即管理面就绪。此时用 ss -ltn 看宿主端口,会确认 2.1 节的判断:只有 8132(映射的 4242)在监听,其余协议口要等 4.3 节首启向导里启用连接器后才出现。
4.3 首启向导:建号与启用协议连接器
首启有两种完成方式:浏览器打开 http://<服务器IP>:8132 走 Web 向导,或直接调 Management API。两种方式写入的是同一份 /config.json,效果等价。演示环境是命令行友好场景,这里把两条路都走一遍。
方式一:Web 界面(推荐)
浏览器打开 http://<服务器IP>:8132,首启流程三步:
- 创建管理员账号:界面提示 "There is currently no username or password set"(当前未设置任何账号),填写用户名与密码后提交。本系列演示统一使用账号
root、密码q1w2e3r4(演示账号,生产环境务必换强密码); - 确认协议连接器:向导给出默认协议集(RTMP、RTSP、HTTP、HLS、CMAF 等),首次部署建议直接采用默认值——实测默认集已覆盖本篇全部验证场景;
- 进入主界面:左侧导航包含 Streams(流管理)、Protocols(协议连接器)、Accounts(账号)、Limits、Triggers、Logs 等配置域,具体逐项说明见本系列配置篇。
方式二:API 建号
无账号状态(NOACC)下允许通过 API 创建初始账号。先请求任意接口拿到认证挑战,再用挑战值完成创建。实测全程(curl 与回显):
# 1. 无账号探测:返回 NOACC
curl -s 'http://127.0.0.1:8132/api2?command=%7B%7D'
{"authorize":{"status":"NOACC"}}
# 2. 创建初始账号(明文,仅限首次建号且仅限内网使用)
curl -s 'http://127.0.0.1:8132/api2' -H 'Content-Type: application/json' \
-d '{"authorize":{"new_username":"root","new_password":"q1w2e3r4"}}'
{"authorize":{"status":"ACC_MADE"}}
ACC_MADE 表示账号已建立。官方文档明确提醒这种方式"不安全",只该出现在首次部署的内网环节。
建号后服务端日志有对应记录(实测):
CONF: Created account root through API
4.4 创建流:三种典型 source
流是 MistServer 的核心配置对象。管理界面 Streams → Add stream 或 API 均可创建。三种典型 source 本篇全部实测:
| source 写法 | 类型 | 行为 |
|---|---|---|
push:// | 实时推流 | 等待编码器向 RTMP/RTSP 端口推流,流名匹配即接入 |
/vod/testvod.mp4 | 文件点播 | 立即就绪,循环/按需供拉流 |
push://streamname | 限定流名推流 | 只接受推到指定流名的推流会话 |
API 方式创建(addstream 命令,请求体必须是 JSON——实测中发现 form 表单方式提交写操作不生效,详见 D 篇排障):
curl -s 'http://127.0.0.1:8132/api' -H 'Content-Type: application/json' \
-d '{"addstream":{"live":{"name":"live","source":"push://"}}}'
{"authorize":{"status":"OK"},...}
Web 界面操作等价:Streams 页 → Add stream → 流名 live、source 选 Stream(即 push://)→ Save。创建后流列表出现 live,状态为离线(等待推流)。
再创建一条 VoD 流验证点播链路(source 填 /vod/testvod.mp4,即 4.1 节挂载目录内的文件)。创建成功后流列表里 vod 显示可用状态——实测其状态值为 online: 2,表示"文件流就绪":
{"vod": {"error": "Available", "name": "vod", "online": 2, "source": "/vod/testvod.mp4"}}
4.5 协议连接器确认
Protocols 页(或 API 的 config.protocols)应显示默认五项全部在线。实测读回:
[{"connector": "RTMP", "online": 1, "port": "1935"},
{"connector": "RTSP", "online": 1, "port": "5554"},
{"connector": "HTTP", "online": 1, "port": "8080"},
{"connector": "HLS", "online": 1},
{"connector": "CMAF", "online": 1}]
online: 1 表示连接器已拉起。HLS 与 CMAF 没有独立端口——它们寄生于 HTTP 连接器的 8080 端口,靠 URL 前缀路由(下一节实测)。此时宿主侧再看端口,8133/8135/8139 已全部进入监听。
4.6 推拉流全链路验证
RTMP 推流到 live(用 ffmpeg 从测试源推流,生产环境此角色是编码器或导播台):
ffmpeg -re -f lavfi -i testsrc=size=640x360:rate=25 \
-f lavfi -i sine=frequency=1000 \
-c:v libx264 -preset veryfast -pix_fmt yuv420p -g 50 \
-c:a aac -f flv rtmp://<服务器IP>:8135/live/live
推流地址是两段式:/live/live 前一段是应用名、后一段是流名,两段缺一不可——只推一段会被服务端日志拒绝(实测回显:Push rejected - stream not configured or unavailable,空流名)。
推流成功后,管理界面 Streams 页 live 状态变绿,API 读回(实测):
{"live": {"name": "live", "online": 1, "source": "push://"}}
RTSP 推流到 cam(模拟摄像头接入,source 同样是 push://):
ffmpeg -re -f lavfi -i testsrc2=size=640x360:rate=25 \
-f lavfi -i sine=frequency=500 \
-c:v libx264 -preset veryfast -pix_fmt yuv420p -g 50 \
-c:a aac -f rtsp rtsp://<服务器IP>:8139/cam
HLS 拉流验证(HTTP 8080 家族,宿主映射 8133):
curl -s 'http://127.0.0.1:8133/hls/live/index.m3u8'
实测回显:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=131392,RESOLUTION=640x360,FRAME-RATE=25,CODECS="avc1.64001e,mp4a.40.2"
1_2/index.m3u8?tkn=207935232
子播放列表与分片同样可拉(实测):
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PROGRAM-DATE-TIME:2026-10-30T04:06:35.794Z
#EXTINF:2.000000,
2000_4000.ts?tkn=2981602234
分片请求实测 http=200 bytes=57716,HLS 链路完整。浏览器播放地址即 http://<服务器IP>:8133/hls/live/index.m3u8(Chrome 原生播 HLS 仍不稳,前端建议配 hls.js)。
DASH 拉流验证(CMAF 连接器,前缀 /cmaf/):
curl -s 'http://127.0.0.1:8133/cmaf/vod/index.mpd' | head -8
实测回显(VoD 流,静态 MPD):
<?xml version="1.0" encoding="UTF-8"?>
<MPD type="static" mediaPresentationDuration="PT9.960S" minBufferTime="PT1.5S" ... >
<ProgramInformation><Title>vod</Title></ProgramInformation>
<Period >
<AdaptationSet group="1" mimeType="video/mp4" width="640" height="360" frameRate="25" ... >
RTSP 拉流验证(从 cam 拉流解码 1 秒,实测回显末帧):
frame= 26 fps= 12 q=-0.0 Lsize=N/A time=00:00:01.03 bitrate=N/A speed=0.493x
VoD 直链验证:http://<服务器IP>:8133/hls/vod/index.m3u8 返回主播放列表(实测回显含 BANDWIDTH=131680,RESOLUTION=640x360 变体行),证明挂载目录 + 文件 source 的点播链路可用。
流元数据 JSON:HTTP 口对每条活跃流提供元数据接口,3.12 实测可用路径是 http://<服务器IP>:8133/<流名>.json(实测回显含编码参数、分辨率、帧率):
[{"data":{"audiocodecid":10,"audiodatarate":67.38281249999999,"audiosamplerate":44100,...,"framerate":25,"height":360,...,"width":640},"time":0,"track":0}]
注意:文档旧版本里写的 json_<流名>.json 路径在 3.12 实测不可用(服务端把 json_live 整体当流名查找,日志报 Could not get stream 'json_live' config!),这个行为变化在配置篇与 API 篇都有展开。
五、数据持久化说明
| 数据 | 位置 | 说明 |
|---|---|---|
| 管理配置(账号/连接器/流) | 宿主 /opt/mistserver/data/config.json → 服务内 /config.json | 单文件全量状态,服务进程变更后自动写回(实测:API 建号、建流、改连接器后文件即时更新) |
| VoD 媒体 | 宿主 /opt/mistserver/vod/ → 服务内 /vod/ | 点播素材;文件流首次被拉起时会在同目录生成 <文件名>.dtsh 索引(实测确认) |
| 共享内存 | 服务内 /dev/shm | 非持久化,重启即释放;预算见 2.2 节 |
config.json 一旦建立了管理员账号,文件里就是密码的 MD5 摘要(实测格式 {"account":{"root":{"password":"<md5>"}}}),备份该文件等于备份整套管理面——请把宿主侧该目录纳入常规备份计划,并控制读取权限。
六、首启后的最小安全收敛
- 管理口收敛:4242 不应对公网。只在内网/堡垒机后暴露 8132,其余协议口按需开放;
- 强密码:演示账号
root/q1w2e3r4仅限实验;生产部署在首启向导里直接设置强密码; - API 免认证边界:本机(localhost)访问管理口不需要认证(官方文档明示),服务器上本机的其他进程都能直接控制管理面——共享宿主的场景要意识到这条边界;
- 带宽例外网段:配置里默认把内网网段(10/8、172.16/12、192.168/16、127/8)列入带宽统计例外,首启日志有
Adding default bandwidth exception ranges (local networks)记录,公网暴露时按需复核。
七、常用运维命令
# 状态与日志
docker compose ps
docker compose logs -f mistserver
# 重启单个服务(配置改动后一般不需要,MistServer 配置即改即生效)
docker compose restart mistserver
# 停止与彻底清理(含网络)
docker compose down
升级版本:替换 compose 文件中的发行版标签(如 3.12 → 后续稳定版)后 docker compose up -d,/config.json 持久化的配置与流会原样保留——升级前请先备份该文件并核对新版本的 Release Notes 是否有协议路由变化(3.x 系列的路径前缀规则见 4.6 节)。
八、常见问题(实测排障)
Q1:流创建了但一直离线,日志只有"无法启动缓冲"类提示。
共享内存不足。首启日志的 WARN(63 MiB 警告)就是它。按 2.2 节公式给足 shm_size,1 音 1 视的流至少 80MB 余量起步。
Q2:推流被拒,日志 Push rejected - stream not configured or unavailable。
两种原因(实测都遇到过):一是流名未创建——MistServer 不会为未知流名自动建流;二是推流地址少了应用名段,rtmp://host:8135/live 只有一段,正确是 rtmp://host:8135/live/live。
Q3:/live/index.m3u8 返回 "Unsupported Media type / library failed to launch the required connector"。
3.x 的 HTTP 家族靠路径前缀路由:HLS 是 /hls/<流名>/index.m3u8、DASH 是 /cmaf/<流名>/index.mpd、WebRTC 播放页在 /webrtc/<流名>.html。裸流名路径是 2.x 的习惯,3.x 已不适用。
Q4:UDP 端口启动报错或 WebRTC 拉不通。
检查 ports 里 UDP 映射是否带了 /udp 后缀(2.3 节);宿主侧用 ss -lunp 确认 UDP 口在监听。
Q5:VoD 流报 "Stream open failed"。
依次核对:服务内路径与挂载点是否对应(compose 挂载 /vod,流 source 也要写 /vod/...);文件编码是否被支持(MP4/MKV/TS 等主流封装均在列,可用管理界面 Files 域确认);<文件名>.dtsh 索引是否生成(首次拉流时自动创建,目录只读会失败)。
九、参考链接
- 系列总览与选型:《MistServer 3.12 介绍与选型指南》(含协议矩阵、版本要点与 nginx-rtmp/SRS/MediaMTX 横向对比);
- 配置体系逐项拆解见本系列配置篇,Management API 的认证与命令集见本系列 API 篇;
- 轻量同域对照:《MediaMTX 1.21.3 Docker Compose 部署指南》;
- 官方文档:https://mistserver.org/documentation(First time set-up / Docker installation 章节,2026-10-29 查询);
- 官方 Docker Hub:https://hub.docker.com/r/ddvtech/mistserver(2026-10-29 查询);
- 本文全部命令与回显来自 2026-10-30 在 Linux 服务器上的实测。