用Docker部署SRS流媒体服务器:从RTMP到WebRTC的完整实战指南
想自己搭一个实时音视频流媒体服务,又不想被编译源码、装依赖这些事劝退?用Docker部署SRS是我这些年用下来最省心的一条路。SRS是一个开源的流媒体服务器,全称是Simple Realtime Server,专注于解决直播、RTC、监控等各种实时音视频场景,支持RTMP、HLS、WebRTC、SRT、HTTP-FLV、GB28181这些主流协议,部署起来一条命令就能拉起整套服务。这篇东西我会从选型思路、Docker环境准备、实际部署、推流拉流实操,到最后的排坑心得全部摊开讲,你有基础也好、完全新手也好,照着做基本都能跑起来。
我见过太多人卡在第一步:跑SRS直接去源码编译,结果依赖装到一半崩溃,或者编译完发现版本和文档不一致。其实Docker镜像里早就把这些乱七八糟的依赖处理好了,你要做的只是把端口和配置挂出来,让它替你跑底层那些事。下面我把踩过的坑和真正好用的姿势挨个说清楚。
1. 先搞懂SRS是什么,再决定要不要用Docker
1.1 SRS到底解决了什么问题
市面上能干的流媒体服务器不少,但SRS的定位很明确: 开箱即用、协议覆盖广、性能不错 。它是用C++写的高性能实时服务器,最擅长的场景包括:
- 直播推流:主播端RTMP推上来,观众端能通过RTMP、HTTP-FLV、HLS多协议观看。
- WebRTC通话/会议:不需要额外部署MCU或SFU的时候,SRS 5.0及以上本身就支持WebRTC的推拉流。
- 摄像头/监控接入:通过RTSP拉流,或者GB28181接入,再转成前端能播的格式。
- 低延迟直播:SRT协议在高丢包网络下表现稳定,适合弱网传输。
如果你只是想Nginx加个RTMP模块随便玩玩,SRS的定位其实是高出一截的——它把HLS切片、HTTP-FLV流、WebRTC信令、集群转发这些能力都集成好了,不用你再去东拼西凑。
1.2 为什么推荐Docker而不是裸机编译
先说裸机方案的痛点。SRS官方提供源码,也提供release包,但裸机部署很容易遇到几个问题:
- 编译依赖繁琐:需要C++编译器、OpenSSL、FFmpeg依赖库、python工具链等,缺一个就报错。
- 升级麻烦:每次升级要重新编译,或者替换二进制文件,还可能要迁移配置和数据。
- 环境隔离差:同一台服务器上如果还跑着Nginx、MySQL、Redis,依赖版本冲突是常有的事。
Docker方案的好处在这些地方体现得特别明显:
-
秒级启动:
docker compose up -d直接拉起,不需要手动装依赖。 - 版本可切换:想用SRS 5还是SRS 6,换个镜像tag就行。
- 不影响主机环境:SRS跑在容器里,所有依赖都封装在镜像中,删除容器不会残留垃圾。
- 回滚方便:升级后出问题,直接切回上一个镜像就能还原。
有人担心Docker性能损耗,这其实是误解。流媒体服务器主要瓶颈在网络和CPU的编码/转发,Docker本身只是进程级隔离,网络走的是内核NAT或host网络模式,正常配置下性能损耗几乎可以忽略。个人项目、中小团队场景完全没问题,我在生产环境也这么跑过。
2. 环境准备:Docker安装与镜像加速的坑
2.1 Docker和Compose的安装姿势
不管你是Ubuntu、CentOS还是Windows,第一步先把Docker装好。Linux环境下最推荐用官方脚本安装,省事且版本较新:
curl -fsSL https://get.docker.com | bash -s docker
装完顺手把当前用户加入docker组,免得每条命令都要sudo:
sudo usermod -aG docker $USER
newgrp docker
Windows用户建议直接装Docker Desktop,勾选WSL2后端,体验比较完整。不过Windows下跑SRS做生产级服务会涉及端口、防火墙和文件挂载权限问题,个人测试可以,长时间跑还是建议用Linux服务器。
验证是否安装成功:
docker --version
docker compose version
这里有一个经验:老教程里会说“安装docker-compose”,那是独立的Python工具,需要另装。现在的Docker Desktop和新版Docker Engine都集成了
docker compose
插件,命令是
docker compose
而不是
docker-compose
。你如果照着旧教程遇到
docker-compose: command not found
,多半就是版本或安装方式不对。
2.2 镜像加速配置,解决拉取慢
国内拉取Docker官方镜像慢是常态,尤其是比较大的镜像。SRS镜像虽然不大,但如果你还要拉FFmpeg、Ubuntu底包、Nginx等,就要提前配置镜像加速。
配置方法很简单,修改Docker配置
/etc/docker/daemon.json
:
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1ms.run"
]
}
然后重启Docker服务:
sudo systemctl daemon-reload
sudo systemctl restart docker
关于加速器,我更推荐用国内云厂商的容器镜像服务,注册后会给一个专属加速地址,速度和稳定性比公共加速器好得多。你在阿里云或腾讯云控制台搜“容器镜像服务”,找到“镜像加速器”,复制那个地址填进去就行。有些公共加速器过一阵就失效了,填进去白折腾,云厂商的能用很久。
注意:镜像加速只对
docker pull生效,不影响容器内业务流量。改完daemon.json记得重启Docker,否则不生效。
3. 实战:Docker Compose部署SRS
3.1 目录结构与docker-compose.yml
我建议直接用一个独立目录管理SRS,方便以后升级和迁移:
mkdir -p /opt/srs/conf
cd /opt/srs
然后创建
docker-compose.yml
,内容如下:
services:
srs:
image: ossrs/srs:6
container_name: srs
restart: unless-stopped
ports:
- "1935:1935" # RTMP/RTSP推拉流
- "1985:1985" # HTTP API
- "8080:8080" # HTTP Server (HLS/HTTP-FLV/WebRTC)
- "8000:8000/udp" # WebRTC UDP媒体端口
- "8001:8001/udp" # WebRTC UDP媒体端口
volumes:
- ./srs.conf:/usr/local/srs/conf/srs.conf
- ./objs:/usr/local/srs/objs
environment:
- TZ=Asia/Shanghai
这里几个关键点解释一下:
-
image选择
:我用的
ossrs/srs:6,对应SRS 6.x,WebRTC和SRT支持比5.0更完善。如果你要稳定保守,ossrs/srs:5也可以,区别在于RTC相关的配置项有所变化。 - 端口映射 :1935是RTMP入口,外网推流都走这里;8080是HTTP服务,HLS切片和HTTP-FLV都在这个端口输出;1985是HTTP API,用于管理、统计、鉴权回调;8000/8001是WebRTC的UDP媒体传输端口,很多新手漏配这两个,结果WebRTC死活拉不了流。
-
数据卷挂载
:把
./srs.conf挂进去方便自行修改配置;objs目录是SRS运行产生的日志和HLS临时切片,挂载到宿主机方便排查问题。 -
restart策略
:
unless-stopped表示容器因异常退出会自动重启,但手动stop后不会硬拉起来,比较符合运维直觉。
3.2 配置文件srs.conf怎么填
SRS镜像自带一份默认配置,直接启动就能跑通基础推拉流。不过既然挂载了配置,我建议你自己写一份可控的,最简配置如下:
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_api {
enabled on;
listen 1985;
}
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
hls {
enabled on;
hls_fragment 2;
hls_window 6;
}
http_remux {
enabled on;
}
rtc {
enabled on;
}
}
说明几个容易迷惑的配置项:
-
daemon off:容器里必须用off,因为前台运行才能被Docker的日志和进程管理捕获。 -
srs_log_tank console:日志输出到标准输出,这样我们直接用docker logs就能看到。 -
hls_fragment 2:切片长度设成2秒,延迟更低。默认是5秒,追求低延迟时可调小,但会增加服务器切片次数和海量小文件,生产环境要根据观看规模权衡。 -
http_remux:HTTP-FLV拉流靠这个模块,不开启的话xxx.flv地址无法访问。 -
rtc enabled on:开启WebRTC支持。注意SRS 6的配置已经和5.x有差异,这个写法是6.x的格式。
写完配置后,启动服务:
docker compose up -d
看下容器状态和日志:
docker ps
docker logs -f srs
日志中出现类似“SRS is running”的字样,说明启动正常。这时候可以访问
http://你的IP:8080/
,能看到SRS的默认目录页面;访问
http://你的IP:1985/api/v1/versions
,能返回JSON版本信息,说明HTTP API也通了。
3.3 自定义配置后怎么生效
改
srs.conf
之后不用重新创建容器,只需要:
docker compose restart srs
这个操作的逻辑是:配置通过volume挂载进容器,重启容器后SRS重新加载,所以改动就能生效。如果改坏了起不来,用
docker logs srs
看报错,通常能定位到是配置语法还是端口冲突。
4. 推流拉流实战:把视频送进去再取出来
4.1 推流:FFmpeg循环推一个文件
SRS部署起来只是把路修好了,真正要看到画面,还得有“车”开上去。最常用的推流工具就是FFmpeg。本地没有视频文件的话,可以下一段MP4,然后执行:
ffmpeg -re -stream_loop -1 -i /data/test.mp4 -c copy -f flv rtmp://127.0.0.1:1935/live/stream
命令拆开看:
-
-re:按原视频帧率读取,避免以最快速度推完,这是推流的关键参数。不加这个,FFmpeg会拼了命地读文件,几秒钟就把整个视频推完。 -
-stream_loop -1:无限循环播放这个文件,直播流就不会中断。 -
-c copy:直接复制编码流,不重新编码,CPU占用极低。前提是视频编码是H.264、音频是AAC,这是浏览器和播放器最通用的组合。如果视频是H.265或其他编码,前端播放会黑屏,得用-c:v libx264转码。 -
-f flv:指定输出封装格式为FLV,RTMP协议只支持FLV封装。
推流几分钟后,可以在SRS日志里看到连接建立和断开的记录。如果不想敲命令,也可以用OBS Studio推流,服务器地址填
rtmp://你的IP:1935/live
,串流密钥填
stream
,效果是一样的。
4.2 拉流测试:RTMP、HTTP-FLV、HLS
验证流有没有推上去,最简单的方法是拿播放器拉流。我常用的几种方式:
-
RTMP地址:
rtmp://ip:1935/live/stream,用VLC或者ffplay可以直接播。 -
HTTP-FLV地址:
http://ip:8080/live/stream.flv,浏览器里也可以用VLC插件或flv.js播放,移动端兼容性也不错。 -
HLS地址:
http://ip:8080/live/stream.m3u8,这个最通用,iOS的Safari、网页<video>标签都能直接放。
用ffplay测试最省事:
ffplay rtmp://127.0.0.1:1935/live/stream
ffplay http://127.0.0.1:8080/live/stream.flv
ffplay http://127.0.0.1:8080/live/stream.m3u8
三个地址都能出画面,说明RTMP模块、HTTP-FLV模块、HLS模块都正常。我从实践经验说,HTTP-FLV是现在Web端最稳妥的协议,延迟在可接受范围,实现成本低;HLS适合点播和对延迟不敏感的场景;WebRTC延迟最低,但部署复杂度也最高,下一节单独说。
4.3 摄像头RTSP流接入:从“找流地址”到真正用起来
很多人部署SRS不是为了自己推流,而是想把家里的摄像头、公司监控或者网上找来的公开直播源接入自己的平台。这类需求本质上都涉及一个动作: 拉取RTSP/RTMP源,再转成前端能播的格式 。
摄像头通常暴露RTSP地址,格式类似
rtsp://用户名:密码@IP:554/stream1
。把摄像头流接入SRS,用FFmpeg转推:
ffmpeg -rtsp_transport tcp -stimeout 5000000 -i "rtsp://admin:password@192.168.1.100:554/stream1" -c copy -f flv rtmp://127.0.0.1:1935/live/camera1
这个命令比前面的文件推流多了几个关键参数:
-
-rtsp_transport tcp:强制走TCP拉RTSP流。默认可能是UDP,监控网络丢包严重时画面会花屏、卡顿,TCP模式稳定很多。代价是稍微增加带宽占用,但对局域网场景完全不是问题。 -
-stimeout 5000000:设置网络超时,单位是微秒,也就是5秒。摄像头流断线或者网络抖动时,FFmpeg进程能在5秒后主动退出,配合守护进程脚本就能实现自动重连。不加这个参数,FFmpeg可能一直卡在阻塞状态,怎么等都等不到它退出。
摄像头源断线重连是监控场景最大的坑,我建议用一个循环脚本来跑转推命令:
#!/bin/bash
while true; do
ffmpeg -rtsp_transport tcp -stimeout 5000000 -i "rtsp://admin:password@192.168.1.100:554/stream1" -c copy -f flv rtmp://127.0.0.1:1935/live/camera1
echo "FFmpeg exited, restarting in 3s..."
sleep 3
done
把脚本挂到systemd服务或者用supervisor管理,基本能做到断线自动恢复。很多朋友拿着一堆“直播源地址”想接进自己的播放器,思路也是类似的:先用FFmpeg把这些RTMP/HTTP-FLV源拉到本地SRS,再统一输出成HLS或WebRTC给前端,中间还能做转码、录制、截图,这就是一套最原始的“流媒体中台”了。
4.4 WebRTC拉流:低延迟但注意这些细节
SRS 6对WebRTC的支持已经很成熟,地址格式是:
webrtc://ip:8080/live/stream
但这里有一个大坑:
WebRTC在非localhost环境下强制要求HTTPS
,否则浏览器直接拒绝访问摄像头和播放流。如果你只是在本机测试,用
webrtc://localhost:8080/live/stream
可以通;但如果要在局域网或公网给其他设备播放,必须有HTTPS证书。
最简单的做法是用Caddy或者Nginx做反向代理,把
https://你的域名:443
转发到SRS的8080端口,并在代理层处理好WebRTC需要的UDP端口转发。SRS官方文档有Nginx反代WebRTC的完整配置,这里我建议新手先用HTTP-FLV把业务跑起来,等有时间再折腾WebRTC,因为WebRTC涉及证书、UDP端口、ICE候选等多个环节,任何一个没配好都白屏,排查起来比较费时间。
SRS的WebRTC底层其实帮你处理了TURN/STUN的大部分逻辑,但UDP端口不映射到宿主机、防火墙不开UDP,媒体数据就传不过去。所以再次提醒: 配置里8000/8001的UDP映射不能少 。
5. 常见问题与排查技巧实录
5.1 镜像拉取慢或超时
这几乎是新手必踩的坑。处理方法就是前面说的配置
registry-mirrors
。如果配置了加速器还是慢,可以考虑直接拉阿里云等云平台上的镜像副本,或者干脆用代理环境把镜像导出再导入到目标服务器。另外建议查看当前镜像信息:
docker inspect ossrs/srs:6 --format '{{.RepoDigests}}'
确认镜像完整度,有时候半途中断的pull会留下残缺层,重新
docker pull
一次即可。
5.2 推流报错或连接被拒绝
FFmpeg推流提示
Connection refused
,优先排查三件事:
-
容器是不是真的起来了:
docker ps看有没有退出。 -
1935端口有没有映射:
ss -lntp | grep 1935。 - 防火墙有没有放行TCP 1935。
如果是腾讯云、阿里云这类服务器,还要去控制台安全组里放行端口,这是最容易忽略的,很多人在服务器本地测试没问题,外部一访问就失败,锅就在安全组。另外SRS默认最大连接数是1000,如果连接数打满了,会拒绝新连接,适当调大
max_connections
。
5.3 画面卡顿、延迟高
HLS切片默认可能是5秒甚至更长,总延迟自然高。想降低延迟,把配置里的
hls_fragment
调到2,再打开HTTP-FLV通道。播放器选择也很重要,VLC播HTTP-FLV延迟不高,但网页里播放要注意用flv.js的
live
模式,不要去走进度条。
如果推流端CPU拉满,多半是ffmpeg在转码而不是copy,检查是不是解码格式问题导致
-c copy
失效。用
ffprobe
看下源文件编码,如果是H.265但没有H.265解码能力的播放器,前端会黑屏,这种场景就必须转码。
5.4 WebRTC能推不能拉,或者拉流黑屏
这个问题我在5.0时代被折磨过很久。排查顺序:
- 确认浏览器是通过HTTPS访问的页面(localhost除外)。
- 确认容器映射了UDP 8000/8001,并且服务器防火墙同时放行了UDP端口。
- 确认SRS版本和配置项匹配。WebRTC相关配置在5.x和6.x之间有过调整,照着旧教程配新版本容易踩坑。
-
看SRS日志里有没有报
ICE、DTLS错误,这些通常指向UDP端口不通。
如果以上都检查完还不行,用官方自带的WebRTC测试页面
http://ip:8080/players/rtc_player.html
测试。这个页面能直接播放rtc流,还能给出详细的错误提示,比你自己写的播放器更容易定位问题。我自己排查的时候,经常先用这个页面确认SRS本身没问题,再去改前端。
5.5 容器日志太多、磁盘被撑满
SRS开启HLS后会产生大量切片文件,默认配置下临时文件都在
objs
目录。解决办法是定期清理,或者把HLS切片放到内存盘/tmpfs,再或者调大
hls_window
让旧切片尽快被删除。挂载的
./objs
目录在宿主机上长期运行,建议写个cron定时清理:
find /opt/srs/objs/nginx/html -name "*.ts" -mmin +10 -delete
还有
docker logs
本身也会持续增长,SRS在调试模式下日志量很大,容器跑久了
/var/lib/docker/containers
会占不少空间。建议在
daemon.json
里加上日志轮转:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "20m",
"max-file": "5"
}
}
改完重启Docker,新容器的日志才会被限制大小。
6. 部署之外的几点扩展思路
SRS容器跑起来只是第一步,真正要投入使用时,有几个方向值得继续深入:
-
鉴权与安全
:默认配置下,SRS的HTTP API没有任何鉴权,任何能访问1985端口的人都能查到你的服务器信息甚至调接口。如果服务暴露在公网,建议用Nginx反代加一层Token校验,或者配置SRS的
http_api的鉴权回调,回源服务器验证推拉流地址的合法性。 - 录制与回放 :SRS支持DVR录制,推上来的流可以直接落盘成FLV或MP4文件。结合HLS切片,可以很容易做点播回放。
- 集群扩展 :一台SRS扛不住高并发时,用SRS的Origin/Edge集群架构,Edge节点做分流和缓冲,Origin节点处理源流和转码,在Docker里可以通过多个Compose服务编排起来。
-
监控指标
:SRS的HTTP API能输出
/api/v1/streams列表和/api/v1/clients在线状态,写个脚本定时抓取,推给Prometheus或者钉钉告警,就能实现简单的流健康监控。
我在实际使用中最大的体会是,Docker化的SRS把部署的复杂度降到了一个很低的水位,让人能把精力放在真正重要的事情上——比如流怎么组织、延迟怎么优化、播放端体验怎么提升。如果你只是自己折腾,照着这篇文章跑到WebRTC能拉流就已经很完整了;如果你是想拿它支撑业务,建议把官方文档的“配置”和“API”章节通读一遍,尤其是
vhost
、
token
和
http_hooks
这几块,那才是SRS真正值钱的地方。
更多推荐

所有评论(0)