ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CentOS下用Docker快速部署ZLMediaKit流媒体服务器

CentOS下用Docker快速部署ZLMediaKit流媒体服务器 说来也巧我最早接触ZLMediaKit是在做监控平台对接的时候当时项目方要求支持GB28181国标接入还要能同时输出RTSP、HTTP-FLV、HLS多种拉流协议。看了下源码C写的功能确实强但编译依赖拉了一长串从CMake到openssl再到FFmpeg在CentOS 7上一套编译下来少说半小时起步中途还容易因为依赖版本对不上翻车。后来换成了Docker部署一次镜像拉取加配置挂载十分钟内就能把服务跑起来而且换机器迁移也省心。这篇文章就把我在CentOS环境下用Docker部署ZLMediaKit的完整过程、参数选择和排坑经验写出来给正准备入手的运维和音视频开发省点时间。1. 为什么选择Docker部署而不是源码编译先聊点实在的。ZLMediaKit是一个高性能的轻量级流媒体服务器核心支持RTSP、RTMP、HLS、HTTP-FLV、WebRTC、GB28181这些主流协议。它在安防监控、直播推流、低延迟视频传输这些场景里用得非常广。但它的原生编译安装对系统环境的要求不低尤其当你需要把FFmpeg、SRT、OpenSSL这些扩展能力都编译进去的时候依赖链会变得很复杂。1.1 源码编译的典型痛点我第一次在CentOS 7.9上编译ZLMediaKit时光环境依赖就折腾了大半天。你至少需要装gcc、g、cmake、openssl-devel、libsrt-devel、ffmpeg相关库还有zlib。CentOS 7自带的gcc版本是4.8.5对C14/17标准的支持比较差而ZLMediaKit新版本对编译器有要求你往往得先升级devtoolset或者手动装更高版本的gcc。即使编译器这关过了FFmpeg相关库的版本兼容、cmake的查找路径问题都会冒出来。等你终于编出可执行文件还有配置文件、可执行文件、www静态页面目录的关系要梳理清楚。整个过程对刚接触流媒体服务器的人极不友好而且后面每次想升级版本都得重复一遍编译流程。1.2 Docker部署解决了什么Docker的核心价值就是“把环境问题和业务剥离”。镜像里已经打包好了ZLMediaKit运行所需的所有动态库、可执行文件、默认配置和静态页面目录你在宿主机上只需要关心三件事容器跑起来没有、端口映射对不对、数据挂载在哪里。一句话总结Docker部署的收益有三点部署时间从小时级降到分钟级升级和回滚变得非常轻量不同机器之间的环境差异不再影响服务运行当然也不是所有场景都适合Docker。如果你要做内核级性能调优、需要自定义网卡队列、或者做某些需要直接操作宿主设备的高并发场景那还是源码部署更自由。但对大多数中低并发场景和开发测试环境来说Docker方案在效率和稳定性上都完胜。注意别把Docker当成万能药它适合的是“标准化部署”这件事。如果你想深挖ZLMediaKit内部的编译参数、内存池调优还是要回到源码层面去研究。2. CentOS主机环境准备版本差异与Docker安装细节部署之前先把宿主机的底子打好。CentOS现在常见的有三个大版本7.9、8 Stream、9 Stream。不同版本在Docker安装方式上有一些细微差别特别是CentOS 7它的yum源和内核特性需要额外留意。2.1 CentOS 7.9环境要点CentOS 7.9是很多服务器还在跑的经典版本但它的默认内核是3.10.x对Docker新特性支持有限。好在跑ZLMediaKit这种应用型服务没什么问题关键是别盲装最新版Docker要用CentOS 7能兼容的稳定版本。安装步骤我之前整理过直接在root权限下执行# 安装必要依赖 yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加docker-ce源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 安装指定版本这里的版本号按需调整 yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io # 启动并设置开机自启 systemctl start docker systemctl enable docker这里有个坑要注意CentOS 7下如果直接用yum install docker-ce不指定版本有可能会拉到新版Docker而新版Docker对iptables和nftables的兼容处理在CentOS 7上偶尔会出现NAT规则异常。我自己遇到过docker0网桥的流量出不去最后固定到20.10.x才稳定。2.2 CentOS 8/9 Stream环境要点CentOS 8 Stream和9 Stream的内核都升级到了5.xDocker的安装兼容性好很多直接按官方源装最新版即可。dnf install -y dnf-utils dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo dnf install -y docker-ce docker-ce-cli containerd.io systemctl start docker systemctl enable dockerCentOS 9 Stream有时候会碰到iptables和nftables后端的提示通常不影响使用如果容器网络异常可以检查一下/etc/sysctl.conf里的net.ipv4.ip_forward是不是1。sysctl -w net.ipv4.ip_forward1 echo net.ipv4.ip_forward1 /etc/sysctl.conf2.3 Docker网络模式和SELinux的取舍装完Docker后先别急着拉镜像把网络模式想清楚。ZLMediaKit这类流媒体服务我强烈建议直接使用host网络模式原因在后面章节展开。再说SELinux。CentOS默认开启SELinux时Docker挂载目录会报Permission denied。解决方案有两种一是给挂载目录设置正确的SELinux上下文chcon -Rt svirt_sandbox_file_t /data/zlmediakit二是直接临时关闭SELinux测试环境可用生产环境还是建议用前者setenforce 0我当时图省事直接关了后来做安全审计被提了整改意见所以这里推荐大家环境允许的话还是用chcon处理挂载目录。3. 拉取镜像与首次启动版本选择与关键参数说明环境准备好之后就到了核心环节拉镜像、跑容器。3.1 镜像版本怎么选ZLMediaKit官方在Docker Hub上有镜像仓库名是zlmediakit/zlmediakit。标签主要有master、dev和带构建日期的release版本。我的建议是测试或学习直接用master最新版生产环境锁定一个release版本的标签不要经常浮动更新docker pull zlmediakit/zlmediakit:master拉镜像这一步基本没什么坑国内网络拉取速度也还行。如果拉取超时可以给Docker配置一下镜像加速器。3.2 创建目录结构和挂载点容器启动前先规划宿主机目录。ZLMediaKit容器里和我本地的目录映射主要有这几个可执行文件目录/opt/media二进制和启动脚本配置文件目录/opt/media/bin/config.iniWeb管理页面静态文件/opt/media/www我在宿主机创建了对应的持久化目录mkdir -p /data/zlmediakit/www mkdir -p /data/zlmediakit/bin mkdir -p /data/zlmediakit/logwww目录用于存放HLS切片和静态管理页面log目录用于收集运行日志以后方便统一清理。3.3 用host网络模式启动容器这是整个部署中我认为最重要的一个决定--network host。ZLMediaKit涉及大量音视频端口如果走Docker的bridge模式你得手动映射一堆端口而且RTP动态端口范围在bridge模式下映射起来特别痛苦。用host模式容器直接共享宿主机网络栈端口天然全通。docker run -d \ --name zlmediakit \ --restart always \ --network host \ -v /data/zlmediakit/www:/opt/media/www \ -v /data/zlmediakit/bin:/opt/media/bin \ -v /data/zlmediakit/log:/opt/media/log \ zlmediakit/zlmediakit:master注意-v挂载暂时没有挂配置文件因为第一次运行会让容器生成默认的config.ini我们后面再手动改。启动后等两三秒看下容器日志确认服务正常docker logs zlmediakit正常日志里能看到ZLMediaKit的版本号、启动耗时以及各个协议监听的端口号比如HTTP 80、RTSP 554、RTMP 1935。看到这些基本就说明服务起来了。提示host模式下不要再用-p映射端口会报参数冲突或无效。host模式最干净的做法就是完全不用-p。3.4 确认默认端口ZLMediaKit默认监听端口如下部署后可以先用ss -lntup确认协议/用途默认端口HTTP/HTTP-FLV/HLS80RTSP554RTMP1935HTTP APIRESTful8080RTP 收流GB28181/SRT10000-10010WebRTC8000/udp如果你要用端口判断服务是否存活重点看80、554、1935、8080这四个。4. 容器内部配置调整config.ini里最值得改的几个参数第一次启动后容器会在/opt/media/bin下生成一个默认config.ini。但因为我们已经把bin目录挂载到了宿主机所以配置文件实际落在了/data/zlmediakit/bin/config.ini里直接用宿主机编辑器改就行。4.1 先搞懂配置文件的加载机制ZLMediaKit启动时默认从可执行文件同目录找config.ini。容器里我们做了目录挂载所以宿主机改完配置重启容器就能生效。docker restart zlmediakit4.2 常用参数清单和推荐值我把经常需要改的参数整理成了一张表按优先级排列配置项默认值推荐值说明http.port80按需修改HTTP-FLV和HLS拉流端口http.rootPath./www默认即可设置HLS静态文件根目录rtsp.port554按需修改RTSP拉流端口rtmp.port1935按需修改RTMP拉流端口api.apiDebug10关闭API调试避免暴露接口信息api.secret空自定义一串密钥调用RESTful API的鉴权tokenprotocol.enable_rtp_proxy11保持开启可降低TCP拉流延迟ffmpeg.bin/usr/bin/ffmpeg容器内自带用于HLS切片转封装general.mediaServerId随机自定义ID方便日志和API识别api.secret一定要改尤其是你的ZLMediaKit端口暴露在公网时。默认没有鉴权别人可以通过API接口直接查看你的流信息甚至踢掉推流端。设置方法[api] secretAStrongSecretKey2024改完之后调用API要在URL后拼接?secretAStrongSecretKey2024例如curl http://127.0.0.1:8080/index/api/getMediaList?secretAStrongSecretKey20244.3 关于ffmpeg参数的补充说明容器镜像里自带FFmpeg所以ffmpeg.bin一般不用改。ZLMediaKit调用FFmpeg主要用于HLS切片、截图、转封装这些场景。如果你发现自己拉流/转码时日志报无法执行ffmpeg先确认一下容器里ffmpeg是否存在docker exec zlmediakit which ffmpeg如果不存在那可能是镜像精简版不带FFmpeg这就需要在宿主机装FFmpeg并通过-v /usr/bin/ffmpeg:/usr/bin/ffmpeg:ro挂进去或者换用完整版镜像。4.4 修改完配置必须做的验证改完config.ini后重启容器再看一次日志确认端口是否有变化。如果改错了参数导致服务起不来日志里会有配置解析失败的明显报错。我遇到过把http.port改成和API端口冲突的情况启动后日志会提示bind失败这时候逐个检查端口占用即可。5. 从推流到拉流的完整验证流程部署完服务只是第一步真正要确认它能干活至少要把“推流 - 拉流”的链路完整跑一遍。我习惯用FFmpeg推流、用ffplay和浏览器分别拉流验证。5.1 准备一路推流如果你手头有现成的摄像头或采集设备可以直接推RTSP流。没有设备的话用FFmpeg推一个本地视频循环流最简单ffmpeg -re -stream_loop -1 -i test.mp4 \ -c copy -f flv rtmp://127.0.0.1:1935/live/test如果不指定编码复制而重新编码记得选H.264和AAC兼容性最好ffmpeg -re -stream_loop -1 -i test.mp4 \ -vcodec libx264 -acodec aac -f flv rtmp://127.0.0.1:1935/live/test看到FFmpeg稳定输出muxing overhead并且没有报错说明推流端已经准备好。5.2 用rtsp和http-flv验证拉流在另一台机器上拉流验证ffplay rtsp://127.0.0.1:554/live/test ffplay http://127.0.0.1/live/test.flv能出画面就说明RTSP和HTTP-FLV链路都通了。再用浏览器验证HLS访问http://127.0.0.1/live/test/hls.m3u8多刷新几次确认切片在持续生成。5.3 通过RESTful API验证流状态最直接的方式是查API返回的流列表curl http://127.0.0.1:8080/index/api/getMediaList?secretAStrongSecretKey2024返回的code为0且data数组里能看到test这个流说明ZLMediaKit已经正确识别并管理了这路流。这个接口在排查“服务起来了但看不到流”这类问题时特别好用。6. 多次部署下来遇到的高频问题与排查链路这里把我以及身边同事在CentOSDocker部署ZLMediaKit时踩过的几个高频坑集中列出来方便你遇到问题时能快速对号入座。6.1 容器启动了但宿主机访问不到端口现象docker ps看容器正常日志也显示监听了但宿主机curl端口不通。排查链路先确认容器确实在用host网络docker inspect zlmediakit | grep NetworkMode再用ss -lntup | grep 1935在宿主机上看端口监听是否存在接着检查防火墙firewall-cmd --list-ports或者systemctl status firewalld最后检查SELinux是否阻止了访问我分别在CentOS 7.9和8 Stream上遇到过防火墙拦截尤其CentOS 7自带firewalld对非标准端口默认不放过。放行命令firewall-cmd --zonepublic --add-port1935/tcp --permanent firewall-cmd --reload6.2 Docker容器网络不通NAT规则异常现象docker run一个普通测试容器内部无法访问外网但宿主本身没问题。在CentOS 7上比较常见根源是iptables规则冲突或者net.ipv4.ip_forward没开启。处理方法systemctl restart docker sysctl -w net.ipv4.ip_forward1如果重启Docker后容器IP网段变了原来是172.17.x.x变成172.18.x.x说明docker0重建了这时候重启一下ZLMediaKit容器让它重新绑定网络即可。不过因为ZLMediaKit用的是host网络实际影响不大但如果你还用bridge模式跑其他服务就要注意这个坑。6.3 挂载目录改动不生效现象改了宿主机/data/zlmediakit/bin/config.ini重启容器后配置还是旧值。原因容器内的/opt/media/bin下可能有多个同名配置文件或者容器启动脚本指定了其他配置路径。排查方法docker exec zlmediakit ls -l /opt/media/bin/ docker exec zlmediakit cat /opt/media/bin/config.ini | head -20确认容器读的确实是挂载目录里的文件。另一种可能是文件权限问题容器内用户无权读取给文件加个644权限就够了chmod 644 /data/zlmediakit/bin/config.ini6.4 拉流返回404访问不到HLS切片现象RTMP/RTSP能拉流但HTTP-FLV和HLS总是404。这通常是www静态目录没挂好或者路径对不上。ZLMediaKit的HLS切片默认写到http.rootPath下如果你把www挂载到了错误位置切片文件不会出现在宿主机上。我在测试时就因为把www挂到了/data/conf/这种自作聪明的路径导致HLS一直找不到文件。正确做法就是严格使用/data/zlmediakit/www并保持http.rootPath./www的默认关系。6.5 升级版本时配置漂移Docker部署的优势之一就是升级方便但也有个容易忽略的习惯问题升级镜像前先备份你的配置文件和数据目录。docker cp zlmediakit:/opt/media/bin/config.ini /data/backup/config.ini.bak然后拉新镜像删旧容器重新创建。有时候新版本会新增配置项旧配置缺少这些项也不会报错但某些功能会静默失效。升级完最好对比一下新版本生成的默认配置和旧配置之间的差异。最后再分享点实际运维的小经验这套部署方案我在三台不同配置的CentOS服务器上都跑过一台是CentOS 7.9老机器、一台是CentOS 8 Stream虚拟机、还有一台是CentOS 9 Stream的物理机ZLMediaKit跑起来都稳得很没有出现和宿主机版本强绑定的问题。如果你也打算这么部署我个人建议从一开始就把端口、挂载目录、API密钥这些信息写进一份部署文档里别嫌麻烦等过了几个月要扩容或者排查问题时会感谢当时记了文档的自己。还有一个小技巧如果你的服务器内存不大可以在docker run时加-m 1g这类内存限制防止ZLMediaKit在极端情况比如大量并发拉流占用过多内存导致宿主机OOM。不过这个限制也别设太小ZLMediaKit内存占用受并发路数和转码策略影响比较大建议根据实际压测结果慢慢调整。最后提醒一点不管用Docker还是源码部署务必保证镜像和依赖来源可靠生产环境不要图方便去寻找未知来源的一键部署包或镜像。安全稳定才是部署工作的底线。
返回列表