news 2026/9/8 11:13:21

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ZLM Docker离线安装全攻略:内网断网环境快速部署流媒体服务

简介:面向需要在无外网或内网环境快速部署ZLMediaKit流媒体服务器的运维与开发人员,这份离线包将docker镜像与安装脚本打包在一起,解决了离线环境下依赖拉取困难的痛点,适用于视频监控、直播转码等业务场景。压缩包采用gz格式,仅含2个文件,分别为docker镜像tar包和可执行的安装shell脚本,二者配合即可完成导入镜像与启动容器,整体大小约208.73MB,轻量且便于传输。目前已有373人学习下载,对于需要在内网交付流媒体服务的团队具有直接参考价值。通过该离线包,使用者可获得完整的ZLMediaKit docker化部署所需镜像和自动化安装流程,省去手动查找镜像、编写启动命令的繁琐步骤,同时脚本也便于二次修改以适配自身端口与挂载目录配置,是快速落地ZLMediaKit服务的一项实用工具。 公司内网部署流媒体服务,最怕的就是那种“看似啥都有、其实啥都拉不下来”的环境。ZLM(ZLMediaKit)作为目前国产开源里性能非常能打的流媒体服务框架,平时大家习惯了docker pull一行命令把镜像拉下来跑起来,真到了离线内网环境,这套行云流水的操作全卡在“没有外网”这一步。我前阵子在客户机房做视频汇聚项目,服务器是 centos7,安全策略卡得死死的,外网一律不给通,最后把 zlm 以 docker 镜像的形式完整搬了进去。这篇文章就是这次“zlm docker 离线安装”全过程的复盘,里面包含离线 docker 引擎安装、镜像导出导入、端口规划、配置持久化以及我能想到的全部坑,适合手里有一台断网服务器、又要快速落地 RTSP/RTMP/HLS 转流业务的同学直接抄作业。

1. 项目背景:zlm 能干什么,为什么非要用容器跑

1.1 流媒体服务框架的核心能力

ZLMediaKit 本质是一套基于 C++11 开发的高性能流媒体服务框架,它最拿手的事情是“协议接入”和“协议转换”。比如你有一台海康摄像头,它默认走 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 方案,其实有两套思路:

  1. 目标服务器上先装好 docker,然后在有外网的机器上用docker save导出 zlm 镜像,拷进内网后docker load加载,最后运行容器。
  2. 如果目标服务器连 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 API
RTP 收流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 慢。这个时候不要急,看下topiostat,等就完了。

4.3 启动 zlm 容器

镜像加载好之后,以我之前规划的端口为例,启动命令如下:

mkdir -p /data/zlm/log /data/zlm/data docker run -d --name zlm \ --restart=always \ -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

参数说明:

  • --restart=always:服务器重启后容器自动拉起,这在无人值守的内网环境非常关键。
  • -p 554:554:RTSP 默认端口,摄像头直接推流到这个端口。
  • -p 1935:1935:RTMP 端口。
  • -p 8080:80:把容器内 HTTP 端口 80 映射为宿主机 8080,避免和 nginx 冲突。
  • -p 10000:10000:RTP 收流端口,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 进来之后手动打 tag:

docker tag <IMAGE_ID> zlmediakit/zlmediakit:master

5.3 RTSP 拉流一直超时

如果你确认容器已经启动、端口映射也写了,但ffplay rtsp://192.168.1.10:554/...就是超时,我第一个想到的是防火墙。内网服务器很多是带 firewalld 的,默认不会放行 554、1935 这些端口。执行:

firewall-cmd --permanent --add-port=554/tcp firewall-cmd --permanent --add-port=554/udp firewall-cmd --permanent --add-port=1935/tcp firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --permanent --add-port=10000/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;" />

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 11:13:01

DeepSeek-OCR 部署调用与 LoRA 微调实战:从最小闭环到 RAG 接入

保姆级 DeepSeek-OCR 部署与调用指南&#xff1a;从最小闭环到 LoRA 微调实战最早意识到 OCR 不能继续被忽视&#xff0c;是做一个 RAG 知识库项目的时候。文档量一上来&#xff0c;真正卡住系统的不是向量模型&#xff0c;不是检索算法&#xff0c;而是最前面的解析环节。扫描…

作者头像 李华
网站建设 2026/9/8 11:11:08

VS2010绿色精简版实战:打造可移植的MFC编译环境

简介&#xff1a;VS2010 绿色精简版是一份轻量化集成开发环境资源&#xff0c;面向需要快速搭建基础开发环境、又不想被完整版安装过程拖累的用户。压缩包已提前处理好环境变量等配置&#xff0c;下载解压后即可直接运行&#xff0c;无需手动设置系统参数&#xff0c;对新手或临…

作者头像 李华
网站建设 2026/9/8 11:11:00

Java线程池核心机制与配置实践:参数、队列、拒绝策略全解析

线程池这东西&#xff0c;Java面试十次有八次会问&#xff0c;工作里十个线程池有七个参数是从网上抄的。我刚开始写Java那会儿也是这样&#xff0c;corePoolSize、maximumPoolSize、workQueue、handler背得滚瓜烂熟&#xff0c;interview的时候能把“线程池的七大参数”倒着背…

作者头像 李华
网站建设 2026/9/8 11:10:59

2026年软件部署工具排行榜:8款主流自动化运维工具选型指南

做运维这些年&#xff0c;每年都会被问到同一个问题&#xff1a;项目要上线&#xff0c;几百台服务器要装同一个软件包&#xff0c;难道真的还要一台台 SSH 连上去手动敲命令吗&#xff1f;前几年不少团队确实是这么干的&#xff0c;但到了2026年这个时间点&#xff0c;软件部署…

作者头像 李华
网站建设 2026/9/8 11:10:17

开源办公套件+本地大模型,打造无广告可控的AI办公方案

办公软件这块&#xff0c;被 WPS 和 Office 的弹窗广告、会员订阅、隐私策略劝退过的人不在少数。想用 AI 写文档、改表格、润色排版&#xff0c;又不想被“AI 会员”二次收费&#xff0c;更不想去下载来路不明的破解版。这次我们就把目光放到 GitHub 上&#xff1a;有没有开源…

作者头像 李华
网站建设 2026/9/8 11:10:04

React零基础入门:从JSX到组件与Hooks核心知识

1. 项目概述&#xff1a;为什么我建议你这样入门 React在正式开始之前&#xff0c;先明确一个事实&#xff1a;React 不是一个框架&#xff0c;它是一个用于构建用户界面的 JavaScript 库。这句话听起来简单&#xff0c;但无数新人恰恰是因为没理解这一点&#xff0c;才会在上手…

作者头像 李华