Docker 部署 SRS:轻松搭建实时音视频流媒体平台
我最早接触 SRS 是在做一个小型直播项目的时候,当时甲方要求在三天内上线一个支持低延迟直播的内测环境,还要能跟现有的服务做鉴权对接。说实话,用传统方式编译 SRS 再配 Nginx 转封装,时间根本不够。后来直接用 Docker 拉镜像跑起来,一小时不到就把推拉流全链路打通了。几年用下来,Docker 部署 SRS 已经成为我搭建实时音视频流媒体平台的首选方案,不管是自己做实验还是交付给客户,都省掉了大量踩坑时间。
这篇文章就把我实际部署和调优 SRS 的经验完整记录下来。你如果是刚接触流媒体服务、想用 Docker 快速跑起一套能用的 RTMP/HLS/WebRTC 服务,或者已经用 Nginx-RTMP 但觉得扩展性不够,想试试 SRS 又不想从源码编译,这篇内容都能直接帮到你。我会从最基础的概念讲起,到 Docker 部署、配置解析、推拉流测试、鉴权接入,最后是生产环境常见问题排查,一步一步带你走通全链路。
1. 为什么选 SRS 而不是 Nginx-RTMP 或其他方案
1.1 先说清楚 SRS 到底解决了什么问题
SRS(Simple Realtime Server)是一个开源的实时视频服务器,用 C++ 写的,专注于直播和实时音视频分发场景。它支持 RTMP、HLS、HTTP-FLV、WebRTC、SRT 等多种协议,既能做直播流的接入和转发,也能做简单的录制、转码、鉴权、集群分发。简单说,你的手机、电脑、摄像头把流推上来,SRS 负责让其他人通过网页、播放器、小程序等不同方式看到这份直播画面,并且尽量保持低延迟、高并发、稳定不卡顿。
我知道很多人第一反应是 Nginx-RTMP 模块也够用,为什么非要换 SRS。我的真实体会是:Nginx-RTMP 更像是“顺手做直播”,它的核心毕竟是 Web 服务器,RTMP 模块只是插件能力。当你需要 WebRTC 低延迟推拉流、需要 GB28181 接入摄像头、需要灵活的 HTTP 回调做鉴权和统计这些场景时,Nginx-RTMP 会非常吃力,甚至实现不了。SRS 从出生就聚焦在流媒体这个垂直领域,对协议的支持、对并发性能的优化、对运维接口的完善程度,都明显高一个段位。
另外 SRS 的社区活跃度和文档质量在国产开源项目里属于第一梯队,遇到问题搜一搜大部分都有答案。它的代码结构也清晰,二次开发和定制非常方便。我见过不少团队从 Nginx-RTMP 迁移到 SRS,基本上去一次就回不去了。
1.2 Docker 在这里扮演什么角色
SRS 虽然很强大,但也有它的脾气。如果从源码编译,需要拉取依赖、配置编译选项、处理系统兼容性,整套流程对新手不太友好,对时间紧迫的项目来说更是一种奢侈。更麻烦的是,不同版本之间配置项有差异,编译参数也影响功能开关,换一台机器部署就要重新来一遍。
Docker 把这些问题挡在了门外。SRS 官方提供了维护完善的 Docker 镜像,镜像里已经编译好了所有常用模块,拉下来就能跑。用 Docker 部署 SRS 意味着你的宿主机不需要装任何编译工具链和运行时依赖,一个 Docker 引擎就搞定全部。另外镜像版本和宿主机操作系统是隔离的,你在 Ubuntu 上测试好的一套配置,到了 CentOS 或者 Windows Server 上一样能跑,不会出现“换台机器就起不来”这种诡异问题。
用 Docker 还有一个隐形优势:版本回滚极其方便。我在生产环境吃过一次亏,升级 SRS 版本后某个鉴权配置写法变了,服务起不来,急得一头汗。后来只要用到 Docker,我都会先做好镜像 tag 绑定,升级前保存当前容器,出问题一条命令退回旧版本,时间成本几乎为零。这种“后悔药”在交付现场真的能救命。
1.3 一个类比:装修房子和自己烧砖的区别
说得直白点,从源码编译安装 SRS 就像自己烧砖盖房子,过程漫长而且要求你有一定的“施工资质”。而 Docker 部署 SRS 像买精装房,钥匙拿到手,热水器、马桶、地板都装好了,你只需要把家具搬进去(改配置),马上就能入住。这两种方式的差距,在赶工期的时候格外明显。
2. 部署前的准备工作:环境、镜像与网络规划
2.1 Docker 环境安装的常见坑
既然要用 Docker 部署 SRS,第一步自然是先把 Docker 装好。Windows 用户通常会装 Docker Desktop,这个工具集成度高,图形界面方便,但有两个非常典型的坑。
第一个坑是虚拟化未开启。很多人在 Windows 上安装 Docker Desktop 后启动失败,提示 virtualization support not detected 或者类似信息。这通常是因为 BIOS/UEFI 里的虚拟化技术(Intel VT-x / AMD-V)没有打开,或者 Windows 的 Hyper-V / WSL2 功能没有启用。解决办法是重启进 BIOS,找到虚拟化相关的开关打开,然后在 Windows 功能里勾选“适用于 Linux 的 Windows 子系统”和“虚拟机平台”,再执行一次wsl --update更新 WSL 内核,最后重启 Docker Desktop。
第二个坑是 WSL2 网络模式带来的端口绑定问题。Docker Desktop 在 Windows 上通过 WSL2 作为后端,容器端口映射有时候会不稳定,表现为映射成功后宿主机无法访问。我遇到这种情况,通常会检查 Windows 防火墙是否拦截了对应端口,或者直接把 WSL2 的镜像模式打开:在.wslconfig文件中设置networkingMode=mirrored,让 Windows 共享 WSL2 的网络栈。这个操作能省掉很多端口访问的烦恼。
Linux 服务器上装 Docker 相对简单,用发行版官方源安装就行。要注意的是别图省事用旧版本,旧版 Docker 对容器网络的兼容性和资源隔离都有差距。安装完成后输入sudo docker run hello-world验证一下是否能正常拉取镜像并运行,这比看任何教程都靠谱。
2.2 选对 SRS 镜像版本:不只是 latest 那么简单
SRS 官方镜像在 Docker Hub 上有多个 tag,很多人图省事直接拉latest,这在我眼里是大忌。流媒体服务器是持续运行的服务,稳定性优先,latest 版本可能携带尚未充分验证的新特性,配置格式也可能跟旧版本不兼容。线上环境一定要用具体版本号,比如4.0.168,或者至少固定大版本如4.0。
SRS 当前主流大版本是 v4,相比 v3 在 WebRTC 支持和配置结构上有明显变化。如果你需要 WebRTC 低延迟直播,直接选择 v4 或更新版本。v3 也不是不能用,但它对 WebRTC 的支持比较原始,配置起来更费劲。我在测试环境会保留一个 SRS v5 的容器,用来体验新特性,但生产环境固定在 v4 的某个稳定版本上,这个习惯帮我减少了很多不必要的麻烦。
还有一个容易忽略的坑:SRS 镜像分oss和full(或者对应版本里的不同 tag),前者是简化版不包含转码、DVR 等高级模块,体积小但功能少。如果你要使用 FFmpeg 转码、录制文件、HLS 切片等功能,务必选择功能完整的镜像。我一开始图镜像小,用了精简版,结果开启 HLS 配置后服务直接报错,排查了半天才发现是镜像模块不完整。
2.3 端口规划和防火墙策略
SRS 用到的端口挺多的,规划不好后面会乱。我通常建议预留以下端口:
1935:RTMP 推流和拉流端口,直播推流最核心的入口,绝大多数推流软件都要用。8080:HTTP 服务端口,提供 API 接口、Web 控制台、HTTP-FLV 播放、HLS 文件访问。1985:HTTP API 端口,SRS 的鉴权、统计、回调接口都走这个端口。8000:WebRTC over UDP 的媒体端口,用于 WebRTC 推流和播放。8003/8081:UDP 端口段,WebRTC 音视频媒体传输使用。
在云服务器上,用 Docker 的-p参数映射端口时,需要在安全组和宿主机防火墙里同时放行这些端口。我有一次部署完了本地推流正常,客户端换到外网就黑屏,折腾了半天,最后发现是云服务商安全组没放行 UDP 的 8000 端口,WebRTC 握手能通但媒体数据传输被拦截。这里特别提醒:TCP 和 UDP 都要检查,不要只放行 TCP。
3. 核心概念梳理:RTMP、HLS、HTTP-FLV 与 WebRTC 怎么选
3.1 四种协议各自的脾气
部署 SRS 之前,先把协议这一课补上,否则配置写了也不知道在配什么。
RTMP 是直播界的老大哥,基于 TCP,Adobe 搞出来的协议,推流端兼容性极好,几乎所有直播软件(OBS、手机推流 App)都支持 RTMP 推流。但是 RTMP 拉流在浏览器里没法直接播放,因为浏览器不支持这种格式,需要借助 Flash 插件或者做协议转换,这也是它逐渐被 HTTP-FLV 和 WebRTC 替代的原因。
HLS 是苹果主导的协议,原理是把视频切成一个个小 ts 文件,通过 m3u8 索引文件让播放器顺序拉取。它的优势是能直接跑在普通 HTTP 服务器上,兼容性极佳,iOS 和 Android 浏览器原生支持。缺点是延迟非常高,切片大小加上播放器缓冲,真实延迟通常在 5 到 30 秒之间。所以 HLS 适合对实时性要求不高、但要求稳定可回放的应用,比如活动录像回放、教育课程点播。
HTTP-FLV 是国内的“土生土长”方案,核心思想是把 FLV 数据包封装在 HTTP 响应里,播放器通过流式读取的方式实现低延迟播放。延迟能做到 1 到 3 秒,而且兼容 H5 播放器,很多直播平台在 PC 端就是用它来拉流。缺点是移动端 iOS 原生不支持 FLV,需要依赖 flv.js 这类库,而且对服务器并发有一定压力。
WebRTC 是这两年最火的方案,基于 UDP,延迟能做到 500 毫秒以内,浏览器原生支持。SRS v4 开始对 WebRTC 支持得特别好,适合视频连麦、在线课堂、低延迟监看这些场景。缺点是 UDP 在网络穿透上比较复杂,服务器和客户端之间可能需要处理 NAT 穿透问题,虽然在公网部署 SRS 并且开启相关配置后,大部分情况都能直接用。
3.2 选择策略:不同场景配不同协议
实际项目里,我会遵循一条简单的选择原则:推流端一律采用 RTMP 或 WebRTC,拉流端根据用户终端决定。PC 网页用户优先用 HTTP-FLV,移动端浏览器优先用 HLS 或者 WebRTC,需要超低延迟互动场景直接上 WebRTC。
SRS 的厉害之处在于这个配置不用你额外做复杂的转换逻辑。它接受 RTMP 推流进来,然后同时输出 HLS、HTTP-FLV、WebRTC 等多种格式,客户端各取所需,这个过程在 SRS 内部自动完成。我们只需要在配置文件中打开对应模块,端口不冲突,就能一鱼多吃。
3.3 关键参数解释:这些配置项到底在干什么
看 SRS 配置文件时,最影响理解的是几个核心参数。
listen设置 RTMP 的监听端口,默认 1935,一般不用改。http_api里的enabled开启 HTTP API 服务,listen对应 1985 端口,这里是 SRS 对外暴露控制接口的地方。http_server里的enabled开启 HTTP 文件服务,监听 8080 端口,HLS 切片文件就是从这里往外发的。
rtc_server块负责 WebRTC 相关配置,enabled打开 WebRTC 后,listen是 UDP 端口,candidate和api需要填服务器公网 IP 或域名。这一块是 WebRTC 部署最容易踩坑的地方,后面我会专门讲。
vhost可以理解为虚拟主机配置块,类似 Nginx 的 server 块。你可以针对不同的应用配置不同的转发、鉴权和转码策略。vhost __defaultVhost__表示默认虚拟主机,在http_remux块里开启 HTTP-FLV 转发,在hls块里开启 HLS 切片,在rtc块里开启 WebRTC 支持。
4. 实操:用 Docker 部署 SRS 并完成首次推拉流
4.1 完整部署步骤:一条命令启动服务
直接进入正题。我以 Docker 方式在 Linux 服务器上部署 SRS v4 为例,整个流程如下。
确立工作目录和配置目录,方便管理:
mkdir -p /opt/srs/config mkdir -p /opt/srs/objs创建一个基本的配置文件/opt/srs/config/srs.conf。这个配置兼容推流和各类拉流:
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__ { http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } hls { enabled on; hls_path ./objs/nginx/html; hls_fragment 2; hls_window 6; } rtc { enabled on; rtc_port 8000; } }启动容器。这里我解释一下关键参数:
docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ -v /opt/srs/config/srs.conf:/usr/local/srs/conf/srs.conf \ -v /opt/srs/objs:/usr/local/srs/objs \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4.0.168参数说明:-d表示后台运行,--name srs给容器命名,-p映射端口,-v挂载配置文件和日志目录。这里的-v /opt/srs/config/srs.conf保证你改宿主机上的配置就相当于改容器里的配置,不用进容器编辑;挂载objs目录则方便你在宿主机直接查看 HLS 切片文件。
启动后检查容器状态:
docker ps | grep srs docker logs srs --tail 50如果看到类似rtmp server started或http server started的输出,说明服务已经正常运行。此时访问http://服务器IP:8080/能看到 SRS 的控制台页面,访问http://服务器IP:1985/api/v1/versions能拿到 JSON 格式的版本信息。
4.2 推流测试:用 FFmpeg 模拟一整个直播源
首次验证一般不用真实摄像头,用 FFmpeg 推送一个测试视频文件是最快的方式。这里我给大家一个可以直接套用的命令:
ffmpeg -re -i /path/to/test.mp4 \ -c:v libx264 -preset veryfast -tune zerolatency \ -c:a aac \ -f flv rtmp://服务器IP:1935/live/test解释一下各参数:-re按视频原始帧率读取,模拟直播推流的速度;-c:v libx264用 H.264 编码视频;-preset veryfast -tune zerolatency追求编码速度和低延迟,适合直播;-c:a aac音频编码为 AAC;-f flv指定输出格式。如果没有现成的测试视频,可以用 SRS 官方提供的测试素材,或者用另一条命令生成测试画面:
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \ -f lavfi -i sine=frequency=440:sample_rate=44100 \ -c:v libx264 -preset veryfast -tune zerolatency \ -c:a aac \ -f flv rtmp://服务器IP:1935/live/test推流成功后,在 SRS 控制台http://服务器IP:8080/players/页面,输入对应的拉流地址就能直接预览。也可以用 VLC 播放器打开rtmp://服务器IP:1935/live/test验证 RTMP 拉流是否正常。
4.3 拉流验证的多种方式
RTMP 拉流测试用 VLC 最直观,输入地址能播放就说明链路通了。HTTP-FLV 地址则是http://服务器IP:8080/live/test.flv,这个地址可以直接在浏览器上用 flv.js 播放,也可以用 VLC 打开。HLS 地址是http://服务器IP:8080/live/test.m3u8,这个地址在 iOS 手机上直接用 Safari 打开就能播放。WebRTC 拉流地址通常是在控制台提供的,形如webrtc://服务器IP/live/test,需要通过支持 WebRTC 的播放器页面测试。
4.4 为什么用 Docker 跑 SRS 比直接装效率高这么多
我这么说可能有点主观,但实测下来确实如此。Docker 容器将 SRS 及其运行环境打包在一起,宿主机只要装了 Docker 就能跑,不管底层操作系统是 CentOS 7、Ubuntu 22.04 还是 Debian,结果完全一致。相比之下,直接装 SRS 意味着你要先处理编译依赖:装 GCC、Make、Python、Perl,运气不好还要解决 Perl 模块缺失的问题。这一套下来,快的话半小时,慢的话一上午就没了。
而且 Docker 天然支持多实例。你可以同时跑一个 SRS v3 和一个 SRS v4,端口冲突就用不同的映射,做新旧版本对比。这种能力在验证配置是否兼容时极其好用,直接装的话几乎不可能实现。
5. 高级配置:鉴权、分发与实时转码
5.1 推流鉴权:让陌生人无法往你的服务器塞流
没有鉴权的流媒体服务器等于裸奔。任何人知道你的服务器 IP 和端口,都可以推流上来,占用你的带宽和资源。我见过不少项目上线很久才发现服务器在被盗刷流量,就是鉴权这层没做。
SRS 支持在 HTTP 回调里做鉴权,叫 on_publish 事件。当客户端尝试推流时,SRS 会向配置的回调地址发送一个 HTTP 请求,把推流参数(比如 token、sign)带过去,你的后端服务校验通过就返回 0,拒绝就返回非 0。配置只有在 vhost 里加:
vhost __defaultVhost__ { http_hooks { enabled on; on_publish http://你的回调服务地址:端口/api/srs/on_publish; on_play http://你的回调服务地址:端口/api/srs/on_play; on_stop http://你的回调服务地址:端口/api/srs/on_stop; } }配合推流端,OBS 可以设置推流串流密钥,之后 RTMP 地址变成rtmp://IP:1935/live/test?token=你的密钥。SRS 收到推流后会在回调请求里带上token参数,后端校验这个 token 是否有效。这种方式和 CDN 的鉴权思路完全一致,上线前我强烈建议务必配好。
5.2 多节点分发:一台不够时怎么横向扩展
随着并发用户增加,单台 SRS 可能会成为瓶颈。SRS 支持 Origin 和 Edge 两种角色,Origin 负责接收推流和存储流,Edge 负责转发给拉流用户。这种架构下,推流只需要到 Origin 一台服务器,拉流的用户分散到多个 Edge 服务器上,自动减轻了单台机器的下行压力。
Docker 部署 Edge 节点时,配置会简单很多。Edge 不接收推流,只做转发,类似 CDN 的边缘节点:
vhost __defaultVhost__ { mode remote; origin http://Origin服务器IP:1985; }这种架构做横向扩展非常容易:再跑一个 Docker 容器,配置里的 origin 指向同一个 Origin 服务器即可。负载均衡层放一个 Nginx 做多 Edge 之间的流量分发,整套体系就能扛住比较大的并发。
5.3 实时转码:FFmpeg 与 SRS 的协同
SRS 本身不做转码,但可以通过 FFmpeg 来实现。常见的需求是接收 RTMP 推流后,给流做转码输出多个清晰度(比如 1080P 和 720P 同时输出),或者把某些非标准编码转成 H.264 + AAC 的标准直播流。SRS 的配置里可以设置转码规则,指定 FFmpeg 转出新的流,继续在同一个 SRS 里分发。
在 Docker 场景下,为了让 SRS 能够调用 FFmpeg,需要在镜像里包含 FFmpeg 可执行文件。选择full或ffmpeg版本的镜像即可。转码配置比较简单:
vhost __defaultVhost__ { transcode { enabled on; ffmpeg ./objs/ffmpeg/bin/ffmpeg; engine ffmpeg { vcodec libx264; vbitrate 2500; acodec aac; abitrate 128; output rtmp://127.0.0.1:[port]/live/[stream]_trans; } } }转码会显著消耗 CPU,Docker 部署时建议给容器设置 CPU 限制,避免转码任务吃满宿主机资源。我一般会在docker run时加--cpus=2之类的参数,防止某个转码任务把整台服务器拖垮。
5.4 Docker 网络模式对性能的影响
Docker 的默认网络模式是 bridge,容器通过 NAT 访问外网。这种模式对大多数场景完全够用,但在高性能流媒体服务中,NAT 转发会带来一点点额外开销。如果你非常在意性能,可以用--network=host模式让容器直接使用宿主机网络,SRS 直接绑定宿主机的 IP 和端口,性能最接近原生部署。
使用 host 模式的代价是端口隔离会消失,容器监听哪个端口就直接占宿主机的端口。但如果你的宿主机就是专门跑流媒体服务的,我建议直接上 host 模式,性能和稳定性都有提升。配置起来更简单,端口不用映射,SRS 配置里的监听端口就是宿主机的端口。
6. 常见问题排查与优化实录
6.1 推流失败:connection refused 和握手失败
推流失败最经典的报错是connection refused,这种情况分两步排查。第一步确认容器是否在运行:docker ps看 srs 容器状态,如果容器没起来,看docker logs srs的日志找原因。第二步确认端口映射是否正常:netstat -tlnp | grep 1935,如果宿主机上没监听 1935,说明映射有问题,重新跑容器即可。
如果是握手失败或者推流超时,优先怀疑防火墙或者安全组。我做 WebRTC 时踩过一个印象深刻的坑:推流地址用的 1935 端口能推上去,但网页播放 WebRTC 始终黑屏,排查了编码、分辨率、候选地址各种原因,最后发现是安全组没放行 UDP 8000 端口。TCP 的握手能通过,但真正的媒体数据走 UDP,被防火墙拦截后播放端什么都收不到。所以检查安全组时,TCP 和 UDP 一定要分开看,不能只盯着 TCP。
6.2 WebRTC 黑屏、卡顿的排查思路
WebRTC 黑屏的排查有三板斧。第一板斧看 SRS 日志,日志里会明确提示 candidate 相关错误,或者 ICE 协商失败。第二板斧确认配置文件里的candidate是不是服务器正确的公网 IP,这个是 WebRTC 能不能打通的命门。如果服务器 IP 是内网 IP,SRS 通过容器映射到公网,需要在配置里指定公网 IP:
rtc_server { enabled on; listen 8000; candidate 你的公网IP; }第三板斧是检查浏览器的控制台日志。Chrome 的chrome://webrtc-internals页面能看到完整的 ICE 候选、SDP 协商过程,配合 SRS 服务端日志基本能定位问题。实测下来,80% 的 WebRTC 问题出在 candidate 配置和防火墙拦截上,把这两项检查完才能继续看编码和网络质量问题。
6.3 HLS 播放卡顿、延迟高怎么办
HLS 延迟高是协议特性决定的,但卡顿往往和切片参数有关。hls_fragment是每个切片文件时长,hls_window是保留的切片数量。如果hls_fragment设成 10 秒,播放器加载一个切片可能要等 10 秒,再加上缓冲,延迟自然很大。我把hls_fragment调到 2 秒、hls_window调到 6 秒,延迟能从十几秒压缩到 5 到 8 秒左右。当然想继续压低,就要考虑 HTTP-FLV 或者 WebRTC。
HLS 切片写入速度和磁盘 IO 关系也很大。如果宿主机磁盘 IO 性能差,切片写入慢,播放器拉取 m3u8 索引时会看到文件尚未生成完毕的问题。Docker 部署时,挂载的目录尽量用 SSD,不要用机械盘,尤其在高并发场景下这个因素会被放大。
6.4 Docker 容器 OOM 和 CPU 占用过高
SRS 默认配置下内存占用不高,但并发上来后线程和缓冲会增长。我在docker run时加上了-m 4g --memory-swap 4g之类内存限制,防止极端情况下容器占满全机内存。如果内存确实不足,优先优化 SRS 的max_connections和队列缓冲,而不是盲目升配服务器。
CPU 占用过高,先看是不是开了转码,FFmpeg 转码是 CPU 杀手。转码规格从veryfast改成ultrafast能显著降低 CPU 负载,画质损失在直播场景其实感知不强。再检查是不是有人恶意刷流,SRS 控制台的统计页面能看到每个流的实时连接数,如果某个流异常高,直接抓包查来源。
6.5 配置了 HTTP 回调但收不到请求
HTTP 回调收不到请求是鉴权场景的经典问题。我自己也踩过这个坑,最后发现原因很简单:配置里的回调地址用了127.0.0.1。容器内的127.0.0.1指向容器自身,而不是宿主机。正确的写法应该是用 Docker 的网关 IP,或者直接用宿主机在局域网中的 IP。如果你用 Docker Compose 编排,服务名可以直接作为主机名使用,比如回调地址填http://my-backend:8080/api/srs/on_publish。
回调整体调通后,可以在回调服务里先记录所有请求参数,确认 SRS 发了什么,再写业务逻辑。这是调试时的通用做法,避免你对着空日志瞎猜。
7. 从单机到生产:SRS 和 Docker 的进一步玩法
7.1 Docker Compose 编排全套流媒体服务
单容器部署 SRS 只是第一步。真实项目中,SRS 往往和鉴权服务、转码任务、监控告警系统并存。Docker Compose 能把这些服务编排在一起,一条命令启动整套平台。
一个典型的docker-compose.yml大概长这样:
version: "3" services: srs: image: registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4.0.168 container_name: srs restart: always network_mode: host volumes: - ./config/srs.conf:/usr/local/srs/conf/srs.conf - ./objs:/usr/local/srs/objs api: build: ./backend container_name: srs-api restart: always ports: - "9000:9000" monitor: image: grafana/grafana:latest container_name: srs-monitor restart: always ports: - "3000:3000"使用 Compose 的好处是环境一致性拉满。我交付给客户的方案经常是一整个docker-compose.yml外加几个配置文件,客户只需要装好 Docker 和 Compose,然后docker compose up -d就能完成部署。这种交付效率比写二十页部署文档高太多了。
7.2 容器日志、监控与可视化
SRS 本身提供 HTTP API,我们可以通过1985端口的 API 获取服务器状态、流列表、连接数等数据。生产环境中我用 Prometheus 采集这些指标,Grafana 做可视化面板,能一眼看到当前活跃流数、总带宽和错误率。Docker 容器的 CPU、内存数据用 cAdvisor 采集,配置好了之后,整个平台运行状态尽在掌握。
日志方面,SRS 在 Docker 里的标准输出可以通过docker logs查看。生产环境建议加一个json-file驱动的日志轮转,避免长时间运行后日志文件膨胀占满磁盘。启动容器时加参数:
--log-driver json-file --log-opt max-size=100m --log-opt max-file=3这样单日志文件最大 100MB,保留 3 个轮转文件,磁盘占用可控。
7.3 数据持久化与备份策略
Docker 容器的文件系统是临时的,容器删除后数据就没了。SRS 的 DVR 录制文件、HLS 切片文件都在objs目录,一定要通过-v挂载到宿主机,否则容器一重启历史数据全部消失。这点提醒过很多人,还是有人会踩。
备份策略上,我会用脚本定期把objs目录里的重要录制文件同步到远端存储,比如对象存储或者 NAS。HLS 切片属于临时文件,有hls_window控制生命周期,不需要全量备份。录制文件则按业务重要性决定保留周期,一般是 30 天到 90 天。
7.4 实战案例:一个小型互动直播系统的完整配置
最后分享一个我前几天交付的小型互动直播系统的配置,这套方案同时满足低延迟直播(WebRTC 播放)、标准直播(HTTP-FLV/HLS 播放)、录制回放(DVR 录制)三种需求。
配置文件关键部分:
listen 1935; max_connections 2000; daemon off; srs_log_tank console; http_api { enabled on; listen 1985; } http_server { enabled on; listen 8080; dir ./objs/nginx/html; } vhost __defaultVhost__ { http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } hls { enabled on; hls_path ./objs/nginx/html; hls_fragment 2; hls_window 6; } rtc { enabled on; rtc_port 8000; candidate 公网IP; } dvr { enabled on; dvr_path /usr/local/srs/objs/rec/[app]/[stream]/[2006]/[01]/[02]/[15]/[04]/[05].flv; dvr_plan session; } http_hooks { enabled on; on_publish http://api平台地址:9000/api/srs/auth; on_play http://api平台地址:9000/api/srs/auth; on_stop http://api平台地址:9000/api/srs/report; } }这套配置跑在小型云服务器上(2 核 4G),实测支持同时 50 路 RTMP 推流,200 路并发观看,录制和低延迟播放同时开启,CPU 峰值约 70%,稳定运行两周没有重启。Docker 部署、host 网络模式、SSD 数据盘,就是全部的架构要点。
8. 写在最后的个人心得
Docker 部署 SRS 这件事,本质上就是现代运维思维在流媒体领域的一次落地。你不再需要关心 SRS 是怎么编译出来的,只需要知道这个工具能做什么、配置该怎么写、数据往哪里放。这种“依赖隔离”带来的安心感,是直接安装二进制包很难体验到的。
如果让我给你一个行动建议:第一步先把 Docker 环境装好,第二步拉一个 SRS 镜像用默认配置跑起来,第三步拿 FFmpeg 推一条测试流,第四步打开控制台看看画面。整个流程熟练之后,你会发现流媒体服务器不再只是“听起来高大上”的技术,而是一个像装 Nginx 一样稀松平常的基础设施。
如果后面遇到奇怪的 WebRTC 连不上、内存被打满、回调收不到请求这类问题,回头翻翻这篇里的排查思路,大概率能帮你省下几小时的折腾时间。流媒体这条路,踩的坑不少,但每次把问题解决掉,把整套服务稳定跑起来,还是挺有成就感的。