MediaMTX 1.21.3 Docker Compose 部署指南
基于官方 mediamtx 1.21.3 镜像实测:Compose 编排、端口规划、MTX_ 环境变量、认证配置、录制持久化与六协议冒烟验证。
MediaMTX 1.21.3 Docker Compose 部署指南
目标:用 Docker Compose 从零部署一套 MediaMTX v1.21.3 流媒体服务器,覆盖镜像选型、端口规划、配置挂载、认证、持久化与运维命令——全部步骤在 Ubuntu 22.04 x86_64 + Docker 28 环境实测通过(RTSP/RTMP/HLS/WebRTC/SRT 六协议与 REST API 均验证可用)。
一、环境信息
本文所有命令与回显均在以下真实环境实测通过(实测日期 2026-10-29):
- 操作系统:Ubuntu 22.04(x86_64)
- Docker:28.x(含 compose v2 插件,
docker compose子命令可用) - MediaMTX 镜像:
bluenviron/mediamtx:1.21.3(官方镜像,digestsha256:59e43552f3be43695b70c19424dc2a42fcec18075f88d91561a24ac5d70a586c) - 推拉流工具:FFmpeg 6.1.1(宿主机)
- 部署形态:单容器部署,容器内 MediaMTX 以 PID 1 直跑官方静态二进制
- 本次实测宿主端口规划:因实验宿主 8128–8146/8149–8151 已被其他服务占用,按「宿主空闲端口 → 容器标准端口」重映射(8147→8554、8153→1935、8148→8888、8154→8889、8152→9997、8129/udp→8890/udp、8130/udp→8189/udp);读者服务器上若标准端口空闲,把宿主侧端口换成 8554/1935/8888/8889/8890/8189/9997 即可
MediaMTX 本身介绍与选型对比见《MediaMTX 1.21.3 介绍与选型指南》。
二、镜像选型说明
MediaMTX 官方在 Docker Hub 维护 bluenviron/mediamtx 镜像,tag 规则为 latest 与具体版本号(如 1.21.3)。选型要点:
| 事项 | 结论 | 依据 |
|---|---|---|
| 镜像仓库 | bluenviron/mediamtx | 官方仓库 README 指定,非第三方封装 |
| tag 策略 | 生产固定版本号(1.21.3),不要用 latest | 版本升级可能变更默认行为,固定 tag 保证可复现 |
| 镜像内容 | 单静态二进制 /mediamtx,极简 base | 拉取体积小、攻击面小 |
| 配置方式 | 挂载 /mediamtx.yml 或注入 MTX_* 环境变量 | 两种方式本文均实测 |
拉取镜像(实测回显):
docker pull bluenviron/mediamtx:1.21.3
1.21.3: Pulling from bluenviron/mediamtx
Digest: sha256:59e43552f3be43695b70c19424dc2a42fcec18075f88d91561a24ac5d70a586c
Status: Downloaded newer image for bluenviron/mediamtx:1.21.3
docker.io/bluenviron/mediamtx:1.21.3
⚠️ 网络说明:实测宿主 Docker 守护进程可直连 Docker Hub 完成拉取;若你的网络拉取超时,为守护进程配置镜像加速器或代理后重试。官方另提供内置 FFmpeg 的镜像变体(用于 runOn* 钩子直接调 ffmpeg),按需参见官方镜像说明页选用,本文主线使用标准镜像。
三、前置条件
- 服务器已安装 Docker 24+ 与 compose v2 插件(
docker compose version有输出); - 端口规划完成:下表 7 个端口在宿主侧未被占用(
ss -ltn/ss -lun核对); - 建立工作目录(本文以
/opt/mediamtx为例,与后续挂载路径一致):
mkdir -p /opt/mediamtx && cd /opt/mediamtx
ss -ltn | grep -E ':(8554|1935|8888|8889|9997)\b' ; ss -lun | grep -E ':(8890|8189)\b'
实测回显(两个端口段均空闲,无输出即代表可占用;本实验宿主因已被其他服务占用而选择重映射,见第一章):
(无输出 = 端口空闲可用)
端口规划速查(MediaMTX v1.21.3 全部默认监听):
| 端口 | 协议/用途 | 传输层 |
|---|---|---|
| 8554 | RTSP | TCP |
| 8000/8001 | RTSP RTP/RTCP(UDP 模式收发) | UDP |
| 1935 | RTMP | TCP |
| 8888 | HLS | TCP |
| 8889 | WebRTC(WHEP/WHIP 信令 HTTP) | TCP |
| 8189 | WebRTC ICE 媒体 | UDP |
| 8890 | SRT | UDP |
| 8892/8893 | MoQ(Media over QUIC,v1.21 新增) | TCP/UDP |
| 9997 | REST 控制 API | TCP |
| 9998 | Prometheus metrics | TCP |
| 9996 | 回放服务 | TCP |
如何取用:核心六协议至少映射 8554/1935/8888/8889(+8189/udp)/8890(udp);9997 管理强烈建议开启。端口冲突时按「宿主空闲端口:容器端口」改宿主侧即可,容器内端口不要改。
四、部署步骤
4.1 编写 docker-compose.yml
在 /opt/mediamtx/docker-compose.yml 写入(以下即本次实测配置,宿主侧端口为实测重映射值):
name: mediamtx-1.21.3-stack
services:
app:
image: bluenviron/mediamtx:1.21.3
container_name: mediamtx-1.21.3-app
restart: "no"
ports:
- "8147:8554" # RTSP
- "8153:1935" # RTMP
- "8148:8888" # HLS
- "8154:8889" # WebRTC (WHEP/WHIP 信令)
- "8129:8890/udp" # SRT
- "8130:8189/udp" # WebRTC ICE 媒体
- "8152:9997" # REST API
volumes:
- ./mediamtx.yml:/mediamtx.yml:ro
networks:
stack-net:
ipv4_address: 10.89.61.10
networks:
stack-net:
name: mediamtx-1.21.3-stack-net
driver: bridge
ipam:
config:
- subnet: 10.89.61.0/24
逐项说明:
name:compose 项目名,docker compose系列命令按它分组管理;restart: "no":实验环境便于排障观察;生产建议unless-stopped;ports:左侧是宿主端口、右侧是容器内 MediaMTX 固定监听端口;UDP 映射必须带/udp后缀,漏写会导致 SRT/WebRTC ICE 不通;volumes:把配置文件只读挂载进容器固定路径/mediamtx.yml(官方镜像的默认读取路径);networks:显式指定子网,避免与服务器上其他 bridge 网段冲突。
配置文件 mediamtx.yml 先给最小可用版(开启 REST API 与内置认证,路径允许所有):
api: yes
apiAddress: :9997
authInternalUsers:
- user: admin
pass: q1w2e3r4
ips: []
permissions:
- action: publish
- action: read
- action: playback
- action: api
- action: metrics
- action: pprof
- user: any
pass: ''
ips: ['192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12']
permissions:
- action: publish
- action: read
paths:
all_others:
逐项说明:admin 为全权限管理账号(API/metrics/录制回放全开,任何来源 IP 可用);any 用户对三个内网段放行匿名推流/拉流,便于局域网设备直接接入;paths.all_others 表示未显式定义的路径全部允许推拉(v1.21 语义见第七章常见问题 2)。
4.2 启动并确认
docker compose up -d && docker compose ps
实测回显:
Container mediamtx-1.21.3-app Created
Container mediamtx-1.21.3-app Starting
Container mediamtx-1.21.3-app Started
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
mediamtx-1.21.3-app bluenviron/mediamtx:1.21.3 "/mediamtx" app 3 seconds ago Up 2 seconds 0.0.0.0:8153->1935/tcp, 0.0.0.0:8130->8189/udp, 0.0.0.0:8147->8554/tcp, 0.0.0.0:8148->8888/tcp, 0.0.0.0:8154->8889/tcp, 0.0.0.0:8129->8890/udp, 0.0.0.0:8152->9997/tcp
看启动日志确认各协议服务就绪:
docker logs mediamtx-1.21.3-app 2>&1 | grep -E 'INF|WAR' | head -12
实测回显:
2026/10/29 12:46:35 WAR parameter 'apiAllowOrigin' is deprecated and has been replaced with 'apiAllowOrigins'
2026/10/29 12:46:35 INF MediaMTX v1.21.3, linux, amd64
2026/10/29 12:46:35 INF configuration loaded from /mediamtx.yml
2026/10/29 12:46:35 INF [RTSP] started with listeners on :8554 (TCP/RTSP), :8000 (UDP/RTP), :8001 (UDP/RTCP)
2026/10/29 12:46:35 INF [RTMP] started with listener on :1935 (TCP/RTMP)
2026/10/29 12:46:35 INF [HLS] started with listener on :8888 (TCP/HTTP)
2026/10/29 12:46:35 INF [WebRTC] started with listeners on :8889 (TCP/HTTP), :8189 (UDP/ICE)
2026/10/29 12:46:35 INF [SRT] started with listener on :8890 (UDP/SRT)
2026/10/29 12:46:35 WAR [MoQ] certificate auto.key not found, generating it from scratch
2026/10/29 12:46:35 INF [MoQ] started with listeners on :8892 (TCP/HTTP2), :8892 (UDP/HTTP3), :8893 (UDP/QUIC)
2026/10/29 12:46:35 INF [API] started with listener on :9997 (TCP/HTTP)
⚠️ 排障实录:首测配置里写了旧参数名
apiAllowOrigin,v1.21.3 启动直接给出弃用警告parameter 'apiAllowOrigin' is deprecated and has been replaced with 'apiAllowOrigins'——v1.21 已改为复数形式apiAllowOrigins(值为来源白名单数组)。改名后警告消失。 另注意[MoQ] certificate auto.key not found警告:MoQ 需要 TLS 证书,未提供时自动生成临时证书,仅影响 MoQ 协议,不影响本文主线六协议。
宿主侧端口监听验证:
ss -ltn | grep -E ':(8147|8148|8152|8153|8154)\b'
实测回显:
LISTEN 0 4096 0.0.0.0:8147 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:8148 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:8152 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:8153 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:8154 0.0.0.0:*
4.3 推流、拉流、API 三项冒烟验证
① RTSP 推流(宿主机 FFmpeg,推到映射后的 8147,带 admin 认证):
ffmpeg -re -f lavfi -i testsrc=size=640x480:rate=25 -f lavfi -i sine=frequency=1000:sample_rate=44100 \
-c:v libx264 -preset veryfast -tune zerolatency -pix_fmt yuv420p -g 50 -c:a aac -b:a 64k \
-f rtsp -rtsp_transport tcp rtsp://admin:q1w2e3r4@127.0.0.1:8147/cam
服务端日志(实测回显,docker logs mediamtx-1.21.3-app | grep -i publish):
2026/10/29 12:48:24 INF [RTSP] [session 247560ac] is publishing to path 'cam'
2026/10/29 12:48:24 INF [path cam] stream is available and online, 2 tracks (H264, MPEG-4 Audio)
② HLS 拉流(先取主清单,实测返回 302 cookie 检查后 200):
curl -si http://127.0.0.1:8148/cam/index.m3u8 | head -3
curl -sL http://127.0.0.1:8148/cam/index.m3u8 | head -8
实测回显:
HTTP/1.1 302 Found
Location: /cam/index.m3u8?cookieCheck=1
Server: mediamtx
#EXTM3U
#EXT-X-VERSION:10
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="audio2",AUTOSELECT=YES,DEFAULT=YES,URI="audio2_stream.m3u8?session=edd996fb-dda1-4708-87ee-5b6fafd72fd5"
#EXT-X-STREAM-INF:BANDWIDTH=173256,AVERAGE-BANDWIDTH=173256,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x480,FRAME-RATE=25.000,AUDIO="audio"
video1_stream.m3u8?session=edd996fb-dda1-4708-87ee-5b6fafd72fd5
③ REST API(带 Basic 认证查路径状态):
curl -s -u admin:q1w2e3r4 http://127.0.0.1:8152/v3/paths/list
实测回显(输出节选(实测首尾),JSON 经格式化):
{"itemCount":1,"pageCount":1,"items":[{"name":"cam","confName":"cam","ready":true,
"tracks":["H264","MPEG-4 Audio"],"readers":[],"bytesReceived":4811342}]}
三项全绿即部署完成。API 全部端点玩法见《MediaMTX 1.21.3 API 使用详解》。
五、数据持久化说明
MediaMTX 的状态分两类,持久化处理方式不同:
- 配置:容器无状态,一切配置来自挂载的
mediamtx.yml与MTX_*环境变量,重建容器不丢; - 录制文件:开启
record: yes后按recordPath(默认./recordings/%path/%Y-%m-%d_%H-%M-%S-%f_%z,即容器内工作目录下)落盘。要持久化必须额外挂载目录,在 compose 的volumes:增加:
volumes:
- ./mediamtx.yml:/mediamtx.yml:ro
- ./recordings:/recordings
并同步把配置中 recordPath 指到挂载路径(如 /recordings/%path/%Y-%m-%d_%H-%M-%S-%f_%z)。实测验证:开启录制推流后,宿主侧 ls ./recordings/cam/ 能看到 *.mp4 分段文件落盘。
- 运行时流状态:直播流本身不落盘即不持久(断流即失),属于流服务器常态,无需处理。
六、环境变量表
官方镜像支持用 MTX_ 前缀环境变量覆盖配置文件中的同名参数,规则为「配置键转大写 + MTX_ 前缀」。实测验证(注入 MTX_LOGLEVEL=debug 后日志出现 DEB 级别行):
docker run --rm -e MTX_LOGLEVEL=debug bluenviron/mediamtx:1.21.3
实测回显:
2026/10/29 12:53:25 INF MediaMTX v1.21.3, linux, amd64
2026/10/29 12:53:25 INF configuration loaded from /mediamtx.yml
2026/10/29 12:53:25 DEB path manager created
2026/10/29 12:53:25 INF [RTSP] started with listeners on :8554 (TCP/RTSP), :8000 (UDP/RTP), :8001 (UDP/RTCP)
常用环境变量对照(MTX_LOGLEVEL/MTX_API 实测生效,其余为同名规则推导):
| 环境变量 | 对应配置键 | 默认值 | 说明 |
|---|---|---|---|
MTX_LOGLEVEL | logLevel | info | 日志级别:error/warn/info/debug |
MTX_API | api | no | 开 REST API |
MTX_APIADDRESS | apiAddress | :9997 | API 监听地址 |
MTX_METRICS | metrics | no | 开 Prometheus 指标 |
MTX_RTSPADDRESS | rtspAddress | :8554 | RTSP 监听地址 |
MTX_RTMPADDRESS | rtmpAddress | :1935 | RTMP 监听地址 |
MTX_HLSADDRESS | hlsAddress | :8888 | HLS 监听地址 |
MTX_WEBRTCADDRESS | webrtcAddress | :8889 | WebRTC 信令监听地址 |
MTX_SRTADDRESS | srtAddress | :8890 | SRT 监听地址 |
MTX_PATHDEFAULTS_SOURCE | pathDefaults.source | publisher | 默认流来源 |
MTX_PATHS_CAM_SOURCE | paths.cam.source | — | 指定路径 cam 的流来源(路径级注入) |
⚠️ 注意:环境变量优先级高于配置文件;敏感值(密码等)用环境变量注入比写进 yml 更安全(yml 建议只读挂载且不进版本库)。全部 121 个全局参数与覆盖规则见《MediaMTX 1.21.3 配置参数详解》。
七、配置参数说明与配置文件挂载
7.1 挂载方式
- 挂载点固定为容器内
/mediamtx.yml(官方镜像读取路径); - 推荐只读挂载(
:ro),配置变更走「改宿主文件 →docker compose restart app」,重启 1 秒内完成(实测); - 也可以完全不挂载配置文件,仅用
MTX_*环境变量——不挂载时容器按内置默认值启动(与零配置行为一致,paths为空则拒绝一切推拉,见 7.3)。
7.2 最小配置 vs 全量配置
- 最小配置(4.1 所示):只写你关心的键,其余全走默认,可读性最好;
- 全量配置:官方镜像/发布包内自带一份带全部 121 个全局参数注释的
mediamtx.yml(约 3.9 万字符),可先docker cp mediamtx-1.21.3-app:/mediamtx.yml ./取出(官方发布包 tar 里也有同名文件),再按注释逐项改; - 参数含义逐项解读见《MediaMTX 1.21.3 配置参数详解》。
7.3 paths 语义(最容易踩的坑)
实测确认 v1.21 的路径开关逻辑:
- 配置里定义了具体路径(如
cam:)→ 未列出的路径全部拒绝,日志报closed: path 'cam_rtmp' is not configured(实测实录:RTMP 推到未定义路径被拒); - 想放行其余路径 → 显式加
all_others:; - 完全不写
paths段(或零配置启动)→ 同样拒绝一切推拉。首次部署推流报400 Bad Request/is not configured,先检查这一节。
八、等价 docker run
不使用 compose 的等价命令(与 4.1 compose 逐项对应):
docker run -d --name mediamtx-1.21.3-app \
-p 8147:8554 -p 8153:1935 -p 8148:8888 -p 8154:8889 \
-p 8129:8890/udp -p 8130:8189/udp -p 8152:9997 \
-v /opt/mediamtx/mediamtx.yml:/mediamtx.yml:ro \
bluenviron/mediamtx:1.21.3
启动后同样用 4.3 三步冒烟验证。compose 与 docker run 二选一,不要同时跑(端口会冲突)。
九、常用运维命令
docker compose ps # 状态
docker logs -f mediamtx-1.21.3-app # 跟踪日志
docker compose restart app # 改配置后重启(实测约 1~2 秒恢复)
docker stats --no-stream mediamtx-1.21.3-app # 资源占用
docker compose down # 停止并移除容器与网络
资源占用实测回显(单路 H264+AAC 推流、多协议拉流中):
NAME CPU % MEM USAGE / LIMIT NET I/O
mediamtx-1.21.3-app 0.00% 26.09MiB / 15.57GiB 42.9MB / 1.66MB
26 MiB 量级的常驻内存是 MediaMTX 作为边缘节点的核心优势之一(同场景选型对比见介绍篇第七章)。
热配置补充:挂载 :ro 时改参数需重启;若希望运行中直接热改(不重启),在 compose 挂载上去掉 :ro 并开启 API,用 PATCH /v3/config/global/patch 即时生效(实测:把 logLevel 从 info 改 debug 立即生效,详见 API 篇)。
十、常见问题
Q1:curl http://127.0.0.1:9997/v3/paths/list 返回 {"status":"error","error":"authentication error"}?
原因:v1.21 REST API 默认启用内置认证,内置用户默认只对 localhost 放行;经端口映射访问时容器看到的源 IP 是 bridge 网关地址(如 10.89.61.1),不是 127.0.0.1,认证不通过。实测排障路径:在 authInternalUsers 中增加具全权限的用户(本文 4.1 的 admin/q1w2e3r4 即为该目的),或把网关网段加入 any 用户的 ips。之后用 curl -u admin:q1w2e3r4 http://127.0.0.1:8152/v3/paths/list 即可。
Q2:推流报 closed: path 'cam_rtmp' is not configured?
见 7.3:v1.21 中定义过 paths: 后,未列出的路径默认拒绝(实测日志原样报 closed: path 'cam_rtmp' is not configured)。加 all_others: 或用 API 动态建路径(POST /v3/config/paths/add/cam_rtmp,实测返回 {"status":"ok"} 后立即可推)。
Q3:启动日志出现 parameter 'apiAllowOrigin' is deprecated and has been replaced with 'apiAllowOrigins'?
v1.21 参数改名:apiAllowOrigin → apiAllowOrigins(复数,值为数组,如 ['*'])。实测改名后警告消失。
Q4:HLS 地址 curl 返回 302 而不是 m3u8?
正常行为:HLS 首跳 302 到 ?cookieCheck=1 做播放器 cookie 检查(防死循环)。curl -L 跟随重定向即得到 m3u8(实测见 4.3②);播放器会自动跟随。
Q5:SRT/WebRTC 映射了 TCP 端口还是不通?
两者核心媒体走 UDP:SRT 8890 是 UDP、WebRTC ICE 8189 是 UDP,映射必须带 /udp 后缀("8129:8890/udp"),且宿主防火墙放行对应 UDP 端口。
Q6:跨机访问 WebRTC 页面黑屏?
ICE 候选地址与实际可达 IP 不一致导致。检查三点:8189/udp 已映射并放行、服务器有公网/可达 IP 时配置 webrtcAdditionalHosts(或 webrtcICEHostNAT1To1IPs)声明对外 IP、浏览器端协议用 http(s) 与信令端口一致。参数细节见配置详解篇。
十一、参考链接
- 官方仓库:https://github.com/bluenviron/mediamtx (v1.21.3,查询日期 2026-10-29)
- 官方镜像:https://hub.docker.com/r/bluenviron/mediamtx
- 官方 wiki(部署与认证文档):https://github.com/bluenviron/mediamtx/tree/main/wiki
- 本系列:《MediaMTX 1.21.3 介绍与选型指南》、《MediaMTX 1.21.3 配置参数详解》、《MediaMTX 1.21.3 API 使用详解》