Docker部署SRS流媒体服务器:从RTMP到WebRTC的完整实践指南 📅 发布时间:2026/9/16 2:23:44 👁 浏览次数: 做直播、低延迟连麦、监控大屏这类音视频项目时SRS 是我第一时间会想到的开源流媒体服务器。它协议支持全、社区活跃配合 Docker 部署更是能把环境编译、依赖冲突这些麻烦事直接挡在门外。这篇文章不聊虚的直接讲清楚怎么用 Docker 把 SRS 跑起来打通 RTMP、WebRTC、HLS、HTTP-FLV 这几条关键链路并把我在实际部署中踩过的坑和排查思路一并分享出来。无论你是刚接触流媒体方向的新手还是已经在做音视频落地的工程师照着这篇文章操作基本能把“推流-分发-播放”这条主链路完整跑通。我自己的建议是先别看那么多协议文档先把服务跑起来看到画面再回头对照配置理解原理这样效率最高。1. 为什么用 Docker 部署 SRS需求、选型与准备1.1 SRS 在音视频项目里到底解决什么问题SRS 全称 Simple Realtime Server是一个开源的高性能流媒体服务器作者是开源社区里的知名团队 OSSRS。它最大的特点是“协议全家桶”既能接收 RTMP 推流也能转出 HLS、HTTP-FLV、WebRTC、SRT、GB28181 等多种格式几乎覆盖了直播、会议、监控、在线课堂这些主流场景。在项目里SRS 解决的核心问题就是“把一路画面变成多路可播放的地址”。比如你有一台摄像头或者一个主播端原始画面不可能直接让成千上万人拉取SRS 在中间做协议转换和分发客户端只需要拿到一个 HTTP 或者 RTMP 地址就能在浏览器、手机、VLC 播放器里看到内容。适合使用 SRS 的典型场景我列几个企业内部直播培训、在线教育一对一/小班课、安防监控流接入、用 OBS 推流做个人直播、甚至是一些物联网设备推流上云的场景。相比云厂商的直播服务SRS 自建方案没有按流量计费的问题数据完全在自己服务器上对于重视隐私或者预算有限的团队非常友好。1.2 对比裸机源码编译Docker 方案为什么更香我最早接触 SRS 的时候是在一台 CentOS 服务器上源码编译部署当时被依赖问题折腾得够呛。SRS 编译需要匹配的 gcc、cmake、openssl、ffmpeg 库稍有不慎就报错一个上午就耗进去了。后来切到 Docker 部署之后整个体验完全是两个级别。Docker 方案最核心的优势是“开箱即用”。官方镜像 ossrs/srs 已经把各种协议特性默认编译好了一条 docker run 就能启动完整的流媒体服务不需要关心底层操作系统、库版本也不需要在宿主机上装任何 SRS 的编译依赖。镜像的 tag 体系也很好用想升级就换 tag想回滚就改回旧版本没有任何残留文件的问题。如果你是在 Windows 或者 macOS 上做开发调试Docker 更是绕不过去的方案。SRS 官方调研也提到 Windows 原生支持并不好但在 Docker Desktop 里跑 Linux 容器就完全没有障碍。生产环境同样推荐容器化因为交付物、运行配置、运维命令都是同一套团队协作成本低。当然Docker 也不是万能的。如果你追求极端性能比如单机支撑上万并发并且需要针对内核参数做深度调优那用裸机编译部署可能更适合。但常规的百级到千级并发场景Docker 的开销完全可以忽略我认为没必要为了几毫秒的性能差异付出大量运维成本。1.3 前置准备Docker 环境与镜像加速部署之前先把 Docker 环境准备好。不同系统的安装方式差异比较大我按常见情况简单说一下。Linux 服务器Ubuntu/Debian 系通常这样装sudo apt update sudo apt install -y docker.io docker-compose-v2 sudo systemctl enable --now dockerCentOS/RHEL 系则推荐使用官方源安装 docker-ce一条脚本也能完成curl -fsSL https://get.docker.com | bash sudo systemctl enable --now dockerWindows 和 macOS 用户一般是安装 Docker Desktop。如果启动时提示 “virtualization support not detected” 或者 “Docker Desktop failed to start because virtualisation support wasnt detected”多半是 BIOS 里的虚拟化开关没打开需要重启进 BIOS 开启 Intel VT-x 或 AMD-V然后在 Windows 功能里确认打开了 Hyper-V 或 WSL2。这类问题在论坛里刷屏最多但九成都是这个原因。装完 Docker 之后建议顺手配置一个镜像加速。国内网络直接从 Docker Hub 拉镜像有时候会比较慢可以在 Docker 的 daemon.json 里配置国内公共镜像加速地址例如阿里云容器镜像服务提供的个人加速地址{ registry-mirrors: [https://your-id.mirror.aliyuncs.com] }配置后重启 Docker 服务生效。验证环境是否正常执行 docker version 和 docker run hello-world看到正常提示就说明 Docker 服务没问题可以进行下一步了。注意如果你不想手动配置 daemon.json也可以使用 docker desktop 的设置界面添加 registry-mirrors效果一样。2. 核心细节解析协议、配置与端口规划2.1 RTMP / WebRTC / HLS / HTTP-FLV 怎么选很多新手第一次用 SRS 时最大的困惑不是怎么安装而是“我到底该用哪个协议地址去播放”。这里我花点篇幅把协议之间的关系讲清楚后面配置时就心里有数了。RTMP 是最老牌的直播推拉流协议基于 TCP 的 1935 端口Adobe 公司提出大多数直播软件比如 OBS默认推流都支持。它的优点是稳定、兼容性好缺点是不被浏览器原生支持需要 Flash 或插件所以现在主流做法是用 RTMP 做“推流入口”播放则交给下面的协议。HTTP-FLV 是当前国内直播场景使用最广泛的分发协议。简单理解就是把 RTMP 流封装成 FLV 格式通过 HTTP 传输给浏览器。浏览器端用 flv.js 这个库就可以播放延迟通常控制在 1 到 3 秒适合直播、监控等场景。SRS 默认在 HTTP 服务端口下提供 .flv 后缀的播放地址非常方便。HLS 是苹果主导的协议原理是把直播流切成一个个小 ts 文件再通过 m3u8 索引文件播放。它的优势是浏览器和移动端原生支持不需要插件缺点是切片导致延迟偏高通常有 5 到 15 秒甚至更高。适合点播、对延迟要求不高的电视直播场景。WebRTC 则是实时互动的王牌协议基于 UDP 传输端到端延迟能压到 500 毫秒以内适合视频会议、连麦、低延迟监控这些场景。SRS 对 WebRTC 的支持做得非常好可以直接把 RTMP 流转成 WebRTC 流给浏览器播放延迟体验远好于 HTTP-FLV。一句话总结选型逻辑推流用 RTMP跨端分发优先 HTTP-FLV追求极低延迟用 WebRTC移动端苹果生态或者不着急的场景用 HLS。SRS 的好处是这些协议可以同时开启一份流进来多个协议地址同时输出不需要你做二选一。2.2 srs.conf 关键配置逐项拆解SRS 的配置集中在 srs.conf 文件里默认路径是 /usr/local/srs/conf/srs.confDocker 镜像启动时也会读取这个文件。下面我把最关键的几项配置拆开讲。listen 1935; max_connections 1000; daemon off; srs_log_tank console;listen 指定 RTMP 监听端口默认 1935一般不用改。max_connections 是最大并发连接数根据服务器资源调整个人测试 1000 足够。daemon off 是 Docker 部署里的关键项意思是让 SRS 在前台运行如果没有这一项SRS 默认会后台守护进程方式运行容器因为找不到前台进程就会直接退出很多人第一次跑容器“秒退”就是这个问题。srs_log_tank console 表示日志输出到控制台这样我们才能用 docker logs 看到运行日志。再看 HTTP 相关配置http_api { enabled on; listen 1985; } http_server { enabled on; listen 8080; dir ./objs/nginx/html; }http_api 是 SRS 的 HTTP API 服务可以查询当前流列表、连接数等统计信息比如访问 http://服务器IP:1985/api/v1/streams 就能看到正在直播的流列表。http_server 是内嵌的 HTTP 静态文件服务主要用来做 HLS 文件分发以及提供 SRS 自带的播放器测试页面默认目录就是 SRS 安装目录下的 objs/nginx/html。WebRTC 相关的配置是rtc_server { enabled on; listen 8000; candidate 127.0.0.1; }rtc_server 开启 WebRTC 功能listen 指定 UDP 端口 8000。candidate 是踩坑重灾区它的作用是告诉浏览器“你的媒体数据应该发到哪个 IP”。如果是本地调试填 127.0.0.1 没问题但如果部署在云服务器上这里必须填服务器的公网 IP 或者 EIP否则客户端拿到的 SDP 里是一个内网地址WebRTC 的 UDP 连接根本打不通。vhost 配置块负责多域名、多应用的逻辑隔离默认的defaultVhost就是默认虚拟主机。里面的 tcp_nodelay 和 min_latency 和延迟优化相关play 区域里的 gop_cache 表示是否开启关键帧缓存开启后新进用户能快速起播但会增加延迟实时互动场景建议关闭直播场景建议开启。2.3 端口映射到底怎么规划Docker 部署最需要提前想清楚的就是端口规划。SRS 涉及多种协议每种协议都有对应端口一旦容器启动了再改端口映射就麻烦不少。我通常采用下面的端口规划协议默认端口传输类型用途RTMP1935TCP推流/拉流HTTP API1985TCP查询流状态、控制接口HTTP 服务8080TCPHLS、HTTP-FLV、测试播放页WebRTC8000UDP低延迟音视频传输HTTPS可选8443TCP配合 WebRTC 的 HTTPS 访问在 docker run 命令里端口映射的写法是“宿主机端口:容器端口”。如果宿主机端口被占用可以修改左边的数字比如 19360:1935但需要注意播放地址里的端口也要跟着改成 19360。这里特别提醒一下WebRTC 的 8000 端口必须映射为 UDP 格式命令里要写 8000:8000/udp。很多人在云服务器上配好了一切结果 WebRTC 就是连不上一查才发现安全组只放行了 TCP 的 8000UDP 没放行。云服务器安全组和系统防火墙firewalld/ufw都需要同时支持 UDP 8000 端口。如果后续要支持 SRT 协议额外映射 9000/udp需要 GB28181 监控接入默认也是 9000 端口可以改。我的原则是先按最小集把核心协议跑通再根据业务需要逐步加端口不要一开始就把所有端口全开增加安全风险。3. 实操过程从拉镜像到完成推流播放3.1 第一跑docker run 最小化启动一切准备就绪后先拉取 SRS 官方镜像。推荐使用 SRS 5.0 版本镜像 tag 是 ossrs/srs:5这个版本对 WebRTC 的支持已经非常稳定。如果你的网络拉取缓慢可以换成阿里云镜像仓库的地址 ossrs/srs:5 或者 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5。docker pull ossrs/srs:5拉取完成后执行下面这条命令启动一个最简实例docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ ossrs/srs:5-d 表示后台运行--name srs 给容器命名。启动后立即执行 docker ps 查看状态正常情况下 STATUS 应该是 Up。然后打开浏览器访问 http://服务器IP:8080/如果可以看到 SRS 的欢迎页面说明基础服务已经起来了。日志排查这一步很重要养成习惯docker logs -f --tail100 srs你会看到类似下面的输出SRS is up, version: 5.0.0 live/stream: play, client: 127.0.0.1:51892这说明 SRS 正在正常运行已经用默认配置跑起来了。注意这种启动方式没有挂载自定义配置使用的完全是镜像内部的默认 srs.conf适合快速验证环境真正要落地使用还是要进入下一步的 compose 配置。3.2 进阶docker compose 挂载自定义配置实际项目中我通常不会用 docker run 直接跑生产服务而是用 docker compose 管理。这样配置一目了然团队协作也方便。先建立一个项目目录mkdir -p /opt/srs/conf cd /opt/srs在 /opt/srs/conf 下创建 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; } rtc_server { enabled on; listen 8000; candidate 127.0.0.1; } vhost __defaultVhost__ { tcp_nodelay on; min_latency on; play { gop_cache on; queue_length 10; } }然后在 /opt/srs 下创建 docker-compose.ymlversion: 3 services: srs: image: ossrs/srs:5 container_name: srs restart: unless-stopped ports: - 1935:1935 - 1985:1985 - 8080:8080 - 8000:8000/udp volumes: - ./conf/srs.conf:/usr/local/srs/conf/srs.conf启动命令docker compose up -d重点解释两个配置的意义。restart: unless-stopped 表示 Docker 会自动拉起意外退出或重启后恢复的容器生产环境必须加。volumes 把宿主机的 srs.conf 挂载到容器内部对应路径覆盖默认配置。这样改配置后只需要执行 docker compose restart srs 就能生效不用重新构建镜像。3.3 推流与拉流实战服务跑起来后最激动人心的环节就是推流和拉流。我用 ffmpeg 推流是最常见的做法先准备一个测试的视频文件 test.mp4然后执行ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost/live/stream-re 的作用是让 ffmpeg 按视频原始帧率读取文件模拟实时推流。如果没有本地文件也可以用摄像头实时推流ffmpeg -f dshow -i videoUSB Camera -c:v libx264 -preset ultrafast -f flv rtmp://localhost/live/streamWindows 的 dshow 设备名可以通过 ffmpeg -list_devices true -f dshow -i dummy 查看macOS 用 avfoundation。推流过程中SRS 日志会有 publish 记录。推流成功后我们有四种播放地址可以验证RTMP: rtmp://localhost/live/stream HTTP-FLV: http://localhost:8080/live/stream.flv HLS: http://localhost:8080/live/stream.m3u8 WebRTC: webrtc://localhost:8080/live/streamPC 端最简单的播放方式是打开 VLC 播放器选择“媒体 → 打开网络串流”粘贴 RTMP 地址或者 HTTP-FLV 地址。如果 VLC 能看到画面说明整个链路已经通了。浏览器端验证更方便SRS 自带了播放器测试页面直接访问http://localhost:8080/players/flv_player.html http://localhost:8080/players/rtc_player.html在页面里填上对应的流地址点击播放即可。HLS 的 m3u8 地址也可以直接丢给浏览器原生 video 标签比如video srchttp://localhost:8080/live/stream.m3u8 controls autoplay/video同时通过 HTTP API 可以确认当前流的状态curl http://localhost:1985/api/v1/streams返回 JSON 里会包含 streams 数组里面有 stream 名称、推流客户端的 IP、创建时间等信息。这是我平时排查问题最常用的接口。3.4 WebRTC 低延迟播放与 HTTPS 配置如果你只想公网播放 HTTP-FLV其实不需要 HTTPS。但 WebRTC 的很多高级能力比如调用摄像头、麦克风浏览器强制要求页面必须是 HTTPS 环境。本地 localhost 是例外公网 IP 访问时必须走 HTTPS。一种方案是直接用 SRS 内置的 HTTPS 支持在 srs.conf 的 http_server 区域增加 https 段落http_server { enabled on; listen 8080; dir ./objs/nginx/html; https { enabled on; listen 8443; key ./conf/server.key; cert ./conf/server.crt; } }key 和 cert 指向 SSL 证书和私钥文件可以用 openssl 生成本地自签名证书测试生产环境建议使用域名并配置 Lets Encrypt 自动签发证书。另一种更灵活的生产方案是用 Nginx 或 Caddy 做 HTTPS 反向代理统一管理证书和域名转发。相对而言Caddy 配置更简单只需要在 Caddyfile 里写一行srs.example.com { reverse_proxy 127.0.0.1:8080 }Caddy 会自动申请和续期 HTTPS 证书省去手工运维证书的麻烦。无论用哪种 HTTPS 方案WebRTC 播放时还需要注意 candidate 的配置必须改成服务器的公网 IP否则即使 HTTPS 正常WebRTC 也无法完成媒体传输。我在云服务器上排过一个多小时就是卡在这个问题上日志里看不到明显报错实际上是 candidate 一直是内网地址。4. 生产环境注意点与常见问题排查4.1 常见问题速查表把我在使用中最常遇到的问题整理成一张表建议收藏。每个问题都对应有明确的排查方向现象常见原因解决办法容器启动后立刻退出配置里没有 daemon off在 srs.conf 中确认 daemon off;访问 8080 打不开端口未映射/防火墙未放行docker ps 查看端口映射确认安全组放行 8080推流时报 Connection refusedRTMP 地址/端口不对检查 1935 端口映射和防火墙FFmpeg 推流成功但播放黑屏播放器不支持指定协议换 VLC 或 SRS 自带的 player 页面WebRTC 播放连接失败candidate 为内网 IP、UDP 端口未放行修改 candidate 为公网 IP放行 8000/udpHTTPS 请求证书报错证书路径挂载不正确确认 key/cert 文件已挂载进容器镜像拉取速度很慢Docker Hub 网络问题配置镜像加速或使用阿里云镜像仓库Docker Desktop 启动失败BIOS 虚拟化未开启开启 VT-x/AMD-V启用 WSL2/Hyper-V修改配置后浏览器还是旧行为容器未重启、浏览器缓存docker compose restart srs换无痕窗口HTTP API 返回 404http_api 未开启或端口不对确认 1985 端口映射和 http_api on这张表的排查顺序基本也是我日常排障的顺序先看到容器状态再看端口映射再看安全组最后看应用日志。4.2 排查思路与实操技巧流媒体服务排障我建议遵循“由外到内由网络到应用”的原则。不要一上来就怀疑 SRS 配置先确认端口是不是通的。检查端口是否正常监听ss -tlnp | grep -E 1935|1985|8080如果是外部客户端可以用 telnet 或者 nc 测试 TCP 端口nc -vz 服务器IP 1935UDP 端口比较特殊可以用脚本或者直接在服务器上跑 SRS同时用客户端发起 WebRTC 连接通过 SRS 日志里是否出现 WebRTC 穿透日志来判断。进入容器内部检查配置是否正确docker exec -it srs bash cd /usr/local/srs ./objs/srs -t-t 参数是测试配置文件的模式如果有语法错误会直接提示。这是最方便、最安全的配置校验方式改完配置先测试再重启避免把自己锁在外面。查看容器的实时日志是另一个核心手段docker logs -f --tail50 srsSRS 的日志里每个连接都会记录 client 的 IP 和播放的流名通过日志能定位很多问题。比如播放流时日志显示 “not found”基本就是流名打错了或者推流端没有成功推到同一个应用名和流名上。还有一个小技巧是直接查看容器的端口映射是否符合预期docker port srs输出会列出容器内的端口到宿主机端口的映射关系排查映射错误时非常直观。4.3 性能和稳定性经验谈SRS 单机性能其实相当不错官方数据在普通机器上可以支撑数千路并发播放。但在实际项目中性能瓶颈往往不在 SRS 本身而在操作系统限制和磁盘 IO 上。第一文件描述符限制要拉高。Linux 默认的 ulimit -n 可能只有 1024高并发场景远远不够。在 docker run 或 compose 里要给容器设置更高的 ulimits 限制也可以在宿主机层面修改 /etc/security/limits.conf。我一般先把宿主机和容器的 nofile 都改成 65535。第二日志要做轮转和限制。容器日志默认会无限增长长时间运行可能把磁盘写满。最方便的做法是在 daemon.json 里配置 log-driver 的 max-size 和 max-file 参数{ log-driver: json-file, log-opts: { max-size: 20m, max-file: 5 } }这样单个日志文件超过 20MB 就自动轮转保留最近 5 个文件避免磁盘被日志拖垮。第三HLS 切片写入会产生大量小文件对磁盘性能要求相对较高。如果直播频次高、切片时间长建议使用 SSD 或者给 /usr/local/srs 挂载高性能数据盘。同时可以在配置里调整 hls 的切片时长和列表长度在兼容性和存储成本之间找平衡。第四如果做大规模分发单台 SRS 终有上限。常见架构是“推流域名到 SRS播放前加一层 CDN 或负载均衡”把 SRS 的 HTTP-FLV/HLS 分发能力交给 CDN 边缘节点SRS 只负责拉流和转协议。这种架构下 SRS 的稳定性会高很多即使源站重启边缘节点还能继续服务一段时间。另外建议给 SRS 容器配置健康检查。在 docker-compose.yml 里可以加上healthcheck: test: [CMD, curl, -f, http://localhost:1985/api/v1/] interval: 30s timeout: 5s retries: 3健康检查加上之后监控系统可以自动感知服务的存活状态出问题要第一时间发现并处理。最后再说一个我从实践中得出的体会SRS Docker 这套组合最大的价值不是省了一次编译时间而是让流媒体服务的交付变得标准化。本地调试、预发验证、生产部署用的是同一套镜像和配置文件出问题的概率大大降低。我自己现在不管项目大小都会先把 docker-compose 配置沉淀下来后面再要开新环境十分钟就能复制一套省下的时间可以拿来做真正的业务逻辑。如果你刚上手我建议先按文章里的步骤把 RTMP 推流和 HTTP-FLV 播放这条链路跑通再加上 WebRTC最后再考虑 HTTPS 和调优。一次只引入一个新变量出了问题也容易定位。等主链路稳定了再慢慢尝试 SRT、GB28181 这些扩展能力这套基础架构能支持的场景远比你想的要多。