MediaMTX 1.21.3 Docker Compose 部署指南

基于官方 mediamtx 1.21.3 镜像实测:Compose 编排、端口规划、MTX_ 环境变量、认证配置、录制持久化与六协议冒烟验证。

MediaMTXMediaMTX自托管流媒体RTSP2026/10/29

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(官方镜像,digest sha256: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),按需参见官方镜像说明页选用,本文主线使用标准镜像。

三、前置条件

  1. 服务器已安装 Docker 24+ 与 compose v2 插件(docker compose version 有输出);
  2. 端口规划完成:下表 7 个端口在宿主侧未被占用(ss -ltn / ss -lun 核对);
  3. 建立工作目录(本文以 /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 全部默认监听):

端口协议/用途传输层
8554RTSPTCP
8000/8001RTSP RTP/RTCP(UDP 模式收发)UDP
1935RTMPTCP
8888HLSTCP
8889WebRTC(WHEP/WHIP 信令 HTTP)TCP
8189WebRTC ICE 媒体UDP
8890SRTUDP
8892/8893MoQ(Media over QUIC,v1.21 新增)TCP/UDP
9997REST 控制 APITCP
9998Prometheus metricsTCP
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 的状态分两类,持久化处理方式不同:

  1. 配置:容器无状态,一切配置来自挂载的 mediamtx.yml 与 MTX_* 环境变量,重建容器不丢;
  2. 录制文件:开启 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 分段文件落盘。

  1. 运行时流状态:直播流本身不落盘即不持久(断流即失),属于流服务器常态,无需处理。

六、环境变量表

官方镜像支持用 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_LOGLEVELlogLevelinfo日志级别:error/warn/info/debug
MTX_APIapino开 REST API
MTX_APIADDRESSapiAddress:9997API 监听地址
MTX_METRICSmetricsno开 Prometheus 指标
MTX_RTSPADDRESSrtspAddress:8554RTSP 监听地址
MTX_RTMPADDRESSrtmpAddress:1935RTMP 监听地址
MTX_HLSADDRESShlsAddress:8888HLS 监听地址
MTX_WEBRTCADDRESSwebrtcAddress:8889WebRTC 信令监听地址
MTX_SRTADDRESSsrtAddress:8890SRT 监听地址
MTX_PATHDEFAULTS_SOURCEpathDefaults.sourcepublisher默认流来源
MTX_PATHS_CAM_SOURCEpaths.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) 与信令端口一致。参数细节见配置详解篇。

十一、参考链接