ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ZLM Docker离线安装全攻略:内网断网环境快速部署流媒体服务

2026/9/8 11:13:25 拓冰建站 浏览量
ZLM Docker离线安装全攻略:内网断网环境快速部署流媒体服务 简介面向需要在无外网或内网环境快速部署ZLMediaKit流媒体服务器的运维与开发人员这份离线包将docker镜像与安装脚本打包在一起解决了离线环境下依赖拉取困难的痛点适用于视频监控、直播转码等业务场景。压缩包采用gz格式仅含2个文件分别为docker镜像tar包和可执行的安装shell脚本二者配合即可完成导入镜像与启动容器整体大小约208.73MB轻量且便于传输。目前已有373人学习下载对于需要在内网交付流媒体服务的团队具有直接参考价值。通过该离线包使用者可获得完整的ZLMediaKit docker化部署所需镜像和自动化安装流程省去手动查找镜像、编写启动命令的繁琐步骤同时脚本也便于二次修改以适配自身端口与挂载目录配置是快速落地ZLMediaKit服务的一项实用工具。 公司内网部署流媒体服务最怕的就是那种“看似啥都有、其实啥都拉不下来”的环境。ZLMZLMediaKit作为目前国产开源里性能非常能打的流媒体服务框架平时大家习惯了docker pull一行命令把镜像拉下来跑起来真到了离线内网环境这套行云流水的操作全卡在“没有外网”这一步。我前阵子在客户机房做视频汇聚项目服务器是 centos7安全策略卡得死死的外网一律不给通最后把 zlm 以 docker 镜像的形式完整搬了进去。这篇文章就是这次“zlm docker 离线安装”全过程的复盘里面包含离线 docker 引擎安装、镜像导出导入、端口规划、配置持久化以及我能想到的全部坑适合手里有一台断网服务器、又要快速落地 RTSP/RTMP/HLS 转流业务的同学直接抄作业。1. 项目背景zlm 能干什么为什么非要用容器跑1.1 流媒体服务框架的核心能力ZLMediaKit 本质是一套基于 C11 开发的高性能流媒体服务框架它最拿手的事情是“协议接入”和“协议转换”。比如你有一台海康摄像头它默认走 RTSP 或 GB28181 国标协议而你的业务平台要的是 HTTP-FLV 或 HLS 拉流。ZLM 可以同时把这些协议接进来再以你需要的协议推出去而且单机并发能力和延时控制都做得相当好。在我们这个项目里ZLM 充当的角色就是安防视频汇聚节点。摄像头通过 RTSP 上报平台侧用 HTTP-FLV 拉流做实时预览同时切片输出 HLS 给 Web 端播放。没有 ZLM 这种中间层你就要自己在业务代码里同时维护多种协议既累又容易出问题。所以“zlm”这个搜索词背后其实是大量弱网、内网、行业视频项目里的硬需求。1.2 为什么选择 docker 化部署很多人问ZLMediaKit 不是直接给编译好的二进制包吗为什么非要 docker我实际对比过两条路原生二进制部署要先装依赖库openssl、libsrtp、ffmpeg 相关还要处理版本兼容问题升级时容易把系统环境搞乱。尤其在 centos7 这种老系统上编译高版本 ZLM 可能踩一堆坑。docker 部署镜像自带了运行环境和所有依赖拉到服务器上一条docker run就能跑升级就是换镜像、删容器、再启新容器异常干净。所以我在这套方案里把 docker 作为了唯一交付形态。就算目标机器连 docker 都没有我们也可以把 docker 引擎的安装包一起打包带过去。这就是“离线安装”的核心工作在有网机器上把需要的包准备好到断网机器上一次性铺开。1.3 离线环境的现实约束这次部署的服务器是 centos7.9内网环境不允许访问外网。服务器本身是全新初始化状态连 docker 都没有。我提前确认了三件事CPU 架构是 x86_64这决定了镜像和 rpm 包必须选 x86 版本。操作系统版本是 centos7所以需要准备 el7 系列的 rpm 包。存储空间足够镜像加运行缓存至少预留 3GB。以上信息一定要先确认不然到了现场才发现架构不对准备的所有包全部作废。这一点我在最开始就强调因为踩过一次坑后你会非常痛恨自己没多问一句。2. 离线安装方案整体设计2.1 两条技术路线怎么选离线安装 zlm docker 方案其实有两套思路目标服务器上先装好 docker然后在有外网的机器上用docker save导出 zlm 镜像拷进内网后docker load加载最后运行容器。如果目标服务器连 docker 都没有还需要在另外一台同系统版本、有外网的机器上把 docker 引擎的 rpm 包全部下载好、也一起拷进去离线安装。我这个项目属于第二种所以要准备两部分离线包docker 引擎安装包和 zlm 镜像文件。顺序上必须先装 docker 引擎再 load 镜像再启动容器。2.2 镜像版本选型和多架构问题zlm 官方镜像在 Docker Hub 上的仓库名是zlmediakit/zlmediakit常用的标签是master也就是最新开发版。这里我要多说一句如果你追求生产稳定建议不要一上来就抓master而应选用固定版本的标签。但 ZLM 官方打 tag 的频率不算很低所以实际使用中大量项目都在用master。在下载镜像前要确认源机器架构。如果源机器是 x86_64目标机器也是 x86_64直接导出导入没问题。万一目标机器是 arm64比如鲲鹏或飞腾那就必须在 arm64 的机器上拉镜像或者用docker pull --platform linux/arm64拉取对应架构镜像。跨架构的镜像 load 进去也跑不了这是个非常容易忽略的点。2.3 端口规划要提前定死zlm 容器运行时要暴露的端口比较多我建议在离线安装开始前就把端口规划好避免后期业务方频繁改配置。常用端口如下用途默认端口说明RTSP 接入554摄像头和客户端 RTSP 拉流RTMP 接入1935RTMP 推流和拉流HTTP/API/Web80zlm 的 Web 后台和 HTTP APIRTP 收流10000国标或 RTP 推流默认端口在实际规划时宿主机的 80 端口经常被 nginx 占用所以我会把容器内的 80 映射到宿主机的 8080 上Web 访问用http://ip:8080。RTP 端口在高并发场景下是一个范围比如 10000-20000但映射这么多端口有点重如果只在测试阶段映射一两个就够。3. 在有网环境准备离线安装包3.1 下载 docker 引擎全套 rpm这一步要在“和 centos7 同版本的系统、且有外网”的跳板机上做。我用的方式是配置 docker 官方 yum 源然后用yumdownloader带--resolve参数把所有依赖包下载下来。# 安装 yum-utils提供 yumdownloader 命令 yum install -y yum-utils # 添加 docker 官方 centos 源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 在干净目录里下载 docker 相关安装包及全部依赖 mkdir -p /data/docker-offline cd /data/docker-offline yumdownloader --resolve docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-buildx-plugin下载完成后目录里会出现一堆 rpm 文件。我建议不要在这一步顺手删除要把它们原样打包目标机器上也是原样保留。因为rpm -ivh安装时有依赖顺序要求文件多了反而保险。如果你手头连 yumdownloader 都没有也可以用repotrack效果差不多。只要能能拿到 rpm 包就行。我在实际下载时发现 docker-ce 版本迭代很快所以我会顺手docker-ce --showduplicates看一下版本选择一个比较稳的稳定版比如当时的 24.0.x 系列。3.2 导出 zlm 镜像文件有外网的机器上先安装好 docker这步很简单直接 yum 或者 apt 就行然后 pull 和 save# 拉取 zlm 官方镜像 docker pull zlmediakit/zlmediakit:master # 导出成 tar 包建议使用 gzip 压缩减小体积 docker save zlmediakit/zlmediakit:master | gzip zlm-master.tar.gz一个 zlm 镜像大约 400MB 到 700MB 不等压缩后通常能小不少。导出的 tar 包可以直接打包进交付清单也可以单独拷贝。我习惯把zlm-master.tar.gz文件名带上架构后缀比如zlm-master-x86_64.tar.gz这样后续维护时一眼就能认出来。这里还建议额外准备一个docker-compose.yml示例文件虽然目标机器上不一定会装 docker-compose 插件但留着给运维同学做参考会显得专业很多。3.3 提前准备需要的配置文件zlm 容器内部的工作目录通常是/opt/media配置文件在/opt/media/conf/config.ini。我强烈建议你不要直接进容器去改配置而是把配置目录挂载到宿主机这样升级镜像不丢配置。在有网机器上可以先创建一个目录结构mkdir -p /data/zlm/conf mkdir -p /data/zlm/log mkdir -p /data/zlm/data其中 conf 目录里的 config.ini 可以从容器里拷贝出来改也可以直接用默认配置。关键在于把config.ini里的http.port确认清楚。默认是 80如果我们宿主机映射为 8080那容器内保持 80 就行不用改配置文件。但如果你要改 API 鉴权密钥那就是另一个话题了。4. 离线服务器上的完整部署过程4.1 安装 docker 引擎并启动服务把/data/docker-offline整个目录拷到目标服务器的/opt/docker-offline下然后执行cd /opt/docker-offline rpm -ivh *.rpm如果提示依赖缺失说明你打包时--resolve没生效这时需要把报错信息里提到的包名记下来回有网机器重新下载。如果顺利执行完再执行systemctl daemon-reload systemctl enable --now docker docker version看到 Client 和 Server 两个版本信息都正常输出就说明 docker 引擎装好了。我在实际安装中遇到过一个问题containerd.io版本老旧导致 docker 启动失败。如果systemctl start docker后一直起不来先journalctl -u docker看日志里面会直接告诉你哪个组件报错。大多数情况下就是containerd.io版本不对建议下载包时不要指定太老的 tag。4.2 导入 zlm 镜像docker 引擎起来之后导入镜像cd /opt/docker-offline docker load -i zlm-master.tar.gz如果之前存的是 gzip 压缩包docker load也能自动解压不需要手动解压。load 完成后用docker images确认docker images | grep zlm如果看到zlmediakit/zlmediakit这条记录说明镜像导入成功。有些同学在这个环节会踩坑load 命令执行了半天没有反应其实是 tar 包太大加上服务器磁盘 IO 慢。这个时候不要急看下top和iostat等就完了。4.3 启动 zlm 容器镜像加载好之后以我之前规划的端口为例启动命令如下mkdir -p /data/zlm/log /data/zlm/data docker run -d --name zlm \ --restartalways \ -p 554:554 \ -p 1935:1935 \ -p 8080:80 \ -p 10000:10000 \ -v /data/zlm/conf:/opt/media/conf \ -v /data/zlm/log:/opt/media/log \ -v /data/zlm/data:/opt/media/bin/www \ zlmediakit/zlmediakit:master参数说明--restartalways服务器重启后容器自动拉起这在无人值守的内网环境非常关键。-p 554:554RTSP 默认端口摄像头直接推流到这个端口。-p 1935:1935RTMP 端口。-p 8080:80把容器内 HTTP 端口 80 映射为宿主机 8080避免和 nginx 冲突。-p 10000:10000RTP 收流端口GB28181 国标平台接入时会用到。三个-v挂载配置、日志、数据目录。启动后通过docker ps查看状态是否为 Up。如果处于 Restarting 状态立刻docker logs zlm看日志。我最常遇到的启动失败原因是端口被占用比如宿主机 554 已经被原生 zlm 或其他服务占了。这时先netstat -lnp | grep 554找到占用进程要么停掉它要么换端口映射。4.4 验证流媒体服务是否正常容器跑起来之后从浏览器访问http://服务器IP:8080如果看到 zlm 的 Web 管理页面说明 HTTP 服务正常。页面右上角一般有 API 接口地址、流列表等信息。再验证一下动态拉流能力# 在任意内网机器上使用 ffplay 或者 vlc 拉流测试 ffplay rtsp://服务器IP:554/rtp/01实际项目中摄像头推流到 zlm 后可以通过rtsp://服务器IP:554/live/xxx这种 URL 拉流。不同推流方式产生的流 ID 不一样最好先在 Web 后台的“流列表”里看一眼确认流 ID 再拼 URL免得瞎猜。5. 常见问题与排查技巧实录5.1 rpm 安装时依赖报错离线安装 docker 引擎时最尴尬的是rpm -ivh *.rpm报“依赖被拒绝”。我在第一次做离线包时就是因为只下了docker-ce一个包结果 containerd.io、docker-ce-cli 全都没带上。解决办法就是回到有网机器用yumdownloader --resolve下载全部依赖。如果目标服务器已经装有部分依赖包直接rpm -ivh也不会覆盖安全起见可以加--replacefiles但一般不建议。5.2 docker load 后镜像名不一致有时候你明明导出的镜像是zlmediakit/zlmediakit:master但docker load之后docker images看到的却是一个长串的 image ID名称变成了none。这种情况往往发生在导入包不带完整 tag 信息时。解决思路很简单导出时尽量用docker save 镜像名:tag不要用 image ID 去 save。已经导错了也没关系load 进来之后手动打 tagdocker tag IMAGE_ID zlmediakit/zlmediakit:master5.3 RTSP 拉流一直超时如果你确认容器已经启动、端口映射也写了但ffplay rtsp://192.168.1.10:554/...就是超时我第一个想到的是防火墙。内网服务器很多是带 firewalld 的默认不会放行 554、1935 这些端口。执行firewall-cmd --permanent --add-port554/tcp firewall-cmd --permanent --add-port554/udp firewall-cmd --permanent --add-port1935/tcp firewall-cmd --permanent --add-port8080/tcp firewall-cmd --permanent --add-port10000/tcp firewall-cmd --reload注意 RTSP 实际会同时用到 TCP 和 UDP不要把 UDP 漏了。有些云安全组环境下还要在控制台放行对应入方向规则。5.4 容器升级时配置目录权限异常因为我把 config.ini 挂载出来了容器内进程运行用户可能和宿主机上的文件 owner 不一致导致 zlm 启动后写不了日志或者读不了配置。这种情况的直观表现是容器起来了但日志目录里什么都没有。我用过最简单的处理方式是把挂载目录直接授权给一个大范围权限chmod -R 777 /data/zlm生产环境不建议这么粗暴但在内网测试阶段这是最省时间的。如果想规范一些可以docker exec zlm id查一下容器内 uid然后宿主机上chown -R 那个uid /data/zlm。我这里为了快速交付通常先 777后面再细调。5.5 磁盘空间不足导致镜像导入失败镜像压缩包也不小导入时 docker 需要解压并写入 overlay 目录。如果/var/lib/docker所在分区满了load 会中途失败而且没有任何特别明确的提示只看得到write: no space left on device。排查命令df -h /var/lib/docker如果确实空间紧张有两个方向一个清掉历史镜像和多余容器日志另一个是把 docker 的数据目录迁到其他大分区改/etc/docker/daemon.json里的style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />