news 2026/9/8 11:15:08

内网视频项目必看:ZLMediaKit Docker离线部署全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
内网视频项目必看:ZLMediaKit Docker离线部署全攻略

简介:面向需要在离线或内网环境快速部署 ZLMediaKit(ZLM)的运维与开发人员,该资源提供了一套完整的 Docker 离线安装方案,无需配置外部镜像源或联网拉取依赖,特别适合政企机房、生产内网等受限网络场景。压缩包共包含2个文件,tar 文件为可直接导入的 Docker 镜像,sh 脚本则封装了镜像加载、容器参数设置等关键操作,整体约 208.73MB,体量相对精简。资源目前已有 373 人学习下载,覆盖流媒体网关、视频监控、WebRTC 接入等典型私有化部署需求。通过这套资源,使用者可以快速获得可运行的 ZLM 容器环境,同时理解离线安装时的镜像导入与启动流程,减少手动构建镜像、依赖缺失等常见问题,便于在多个内网节点批量复制部署。脚本中也保留了常用的端口、挂载目录等参数入口,方便按实际业务需求快速定制容器配置。

1. 为什么内网视频项目总是绕不开ZLM

1.1 ZLM到底负责干什么

如果你做过安防项目或者直播转码场景,应该听过 ZLMediaKit,项目缩写就是 ZLM。它是一套基于 C++ 实现的开源流媒体服务器,核心能力是把各种来源的视频流收进来,再按不同协议分发出去。最常见的用法是:海康或大华的摄像头通过 GB28181 国标协议注册到 ZLM,平台侧再通过 HTTP-FLV 或 HLS 从 ZLM 取流,这样网页、小程序和 App 都能直接播放。它也可以作为 RTSP、RTMP 拉流代理,相当于一个内网视频“中转站”。

很多集成商选择它,是因为它开源免费,协议支持面广,把 RTMP、RTSP、HTTP-FLV、HLS、GB28181 这些协议统一封装在一个程序里,省去了同时部署多套服务的麻烦。对于项目报价来说,软件本身的成本是零,项目的实际开销主要在服务器硬件、带宽和定制开发上。如果你在网上搜“zlm流媒体服务器价位”,会发现有人把它当成商业产品报价来问,其实它本身不收许可证费用,价格问题更多是部署环境的成本问题。

1.2 离线部署的真实困境

我刚接手的一个项目就是标准的内网环境:视频监控平台部署在机房内网服务器上,服务器本身被安全策略限制,不能访问公网。摄像头倒是不缺,网络也都是通的,但服务器上连 Docker 都还没装,更别说从 Docker Hub 拉镜像了。这种情况下,通常的两条路是:要么找一台可以临时访问外网的机器,把镜像做成离线包带进内网;要么在内网搭一个私有镜像仓库,通过手动同步的方式导入。

ZLM 这种流媒体服务在两个场景下特别要求周密的部署准备:一是项目上线时间紧,现场网络条件无法等待在线安装;二是后续维护可能需要更新镜像,但没有外网就会很麻烦。这篇就把我在实际项目里做的离线部署过程完整写下来,包括镜像导出、Docker 离线安装、容器配置、以及排错思路,照做基本能把一台全新的内网服务器变成一个能跑 ZLM 流媒体服务的节点。

2. 在联网机器上先备好镜像:我建议的方案

2.1 两条离线部署思路,怎么选

离线部署的思路大致分两类:

  • 方案A:用docker save把ZLM镜像导出成tar包,拷贝到内网后docker load,然后直接docker run。优点是步骤少,适合单机或少量节点。
  • 方案B:搭建内网镜像仓库(例如 Harbor 或简单 registry),在联网机器上推送镜像到仓库,再在内网机器上从仓库docker pull。优点是后期更新镜像、多台服务器安装更方便,但前期复杂度高。

项目如果只有一两台服务器,我真的建议方案A,简单直接。如果后期会不断加服务器、要统一管理镜像版本,早点把方案B做起来。前一种方式的核心命令就是这么几条,在内网环境基本不会出大问题。

2.2 拉取ZLM镜像时该怎么选tag

在联网机器上,拉取 ZLM 镜像的命令就是:

docker pull zlmediakit/zlmediakit:master

tag 方面,最常看到的是master这个滚动标签,对应最新代码。如果需要稳定一点的版本,可以去 Docker Hub 看它打出的其他 tag,比如带版本号的。实际部署时我不建议直接锁死 master,因为滚动标签每次拉取可能内容不同;生产环境最好固定到某个具体的版本标签,便于后续回溯。

如果你所在网络访问 Docker Hub 特别慢,换镜像加速源是一个常见做法,配置好/etc/docker/daemon.json里的registry-mirrors后重启 Docker 再拉。这一步要在有网的机器上完成,和内网环境没有关系。

2.3 导出归档与体积控制

镜像拉下来之后,确认一下:

docker images | grep zlmediakit

看到 REPOSITORY 和 TAG 都正常后,导出:

docker save -o zlm.tar zlmediakit/zlmediakit:master

这里有个细节:如果你在用docker save时只写镜像ID,比如docker save -o zlm.tar 0e5574283393,导入到内网后镜像名和tag会变成<none>,很讨厌。所以导出时尽量用“仓库名:标签”的完整写法。导出的 tar 文件通常有几百MB,因为 ZLM 镜像里包含了完整的编译产物和运行时依赖。如果不够放心,可以先看看 tar 包的内容列表:

tar tf zlm.tar | head -20

嫌文件太大的话,可以在导出时就压缩:

docker save zlmediakit/zlmediakit:master | gzip > zlm.tar.gz

拷贝到内网后先解压再 load,或者直接docker load -i zlm.tar.gz,Docker 也能自动识别压缩格式。文件传输方式就看现场条件,U盘、内网FTP、scp都行,拷完记得做好文件大小校验,镜像文件在传输过程中损坏的情况我也遇到过,后面会讲怎么排查。

3. 内网环境导入镜像与Docker底座的准备

3.1 Docker 已装好,直接 load 就完了

内网服务器如果已经装好 Docker,这一步没什么好说的:

docker load -i zlm.tar

load 完成后docker images能看到zlmediakit/zlmediakit:master,说明镜像层已经还原。load 过程是纯本地操作,不依赖外网,所以完全可以在内网执行。如果内网是多台服务器,把这份 tar 发到每台机器重复 load 即可。

3.2 连 Docker 都没有的 CentOS7 怎么办

这是最容易卡住的地方。很多内网服务器是 CentOS 7,而且初始环境非常干净,连docker-ce都没装。离线装 Docker 的思路是:先在能上网的同版本机器上下载好 rpm 包,再到内网安装。

在联网的 CentOS 7 机器上,使用 yum 的下载模式把依赖也一起拉下来:

mkdir /tmp/docker_rpm yum install --downloadonly --downloaddir=/tmp/docker_rpm \ docker-ce docker-ce-cli containerd.io

如果机器上联不了 yum 源,也可以手动下载 rpm 包,但依赖关系会很麻烦。把整个目录拷到内网后执行:

cd /tmp/docker_rpm rpm -Uvh *.rpm

Debian/Ubuntu 系统则对应使用apt-get download或者apt-get install --download-only,把需要的一堆 deb 包打包带走,内网用dpkg -i安装。

装完 Docker,先启动服务再验证:

systemctl enable docker systemctl start docker docker version

重要提示:离线装 Docker 后不要急着挂镜像加速源,内网本来就没有外网,daemon.json 里只需要关注>{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }

这样容器日志不会把磁盘打爆。

4. 启动ZLM容器:端口、目录、配置一次理顺

4.1 端口映射到底该怎么开

ZLM 默认监听的端口主要是这几个:

作用协议默认端口
RTSP 拉流/推流TCP554
RTMP 流TCP1935
HTTP-FLV / HLSTCP80
GB28181 SIP 注册UDP5060
RTP 媒体接收UDP10000 起

如果只是测试 HTTP-FLV 播放,映射 80 和 1935 就可以。但内网安防项目往往要接 GB28181 摄像头,SIP 和 RTP 端口就必须同时开放。用 bridge 网络启动时,比较完整的命令是:

docker run -d --name zlm \ -p 1935:1935 \ -p 8080:80 \ -p 554:554 \ -p 5060:5060/udp \ -p 10000:10000/udp \ -v /opt/zlm/config:/opt/media/bin/config \ -v /opt/zlm/www:/opt/media/bin/www \ --restart=always \ zlmediakit/zlmediakit:master

注意,RTP 接收是一个端口范围,默认配置里port_range可能是 20000,意味着要接收 10000 到 30000 的 UDP 包。这在大规模摄像头接入时端口映射会非常麻烦。我一般会改小这个范围,或者直接用 host 网络模式。

4.2 配置文件的挂载是新手重灾区

这里有个很容易踩的坑:ZLM 启动时如果找不到 config.ini,会直接退出。多数容器镜像默认自带 config.ini,所以直接 run 没问题,但如果你挂载了一个空的 host 目录到/opt/media/bin/config,容器启动会报错退出。我第一次离线部署时就栽在这里,docker logs里看到类似 “can not open configure file” 的日志,才发现空目录把默认配置覆盖了。

正确的做法是:先不挂载 config 目录,启动一个临时容器,把默认配置拷出来,再停止容器,把配置放到 host 目录里重新挂载启动:

docker cp zlm:/opt/media/bin/config/config.ini /opt/zlm/config/config.ini docker rm -f zlm docker run -d --name zlm ... -v /opt/zlm/config:/opt/media/bin/config ... zlmediakit/zlmediakit:master

把 config.ini 拿出来之后,最常改的几个点也就清楚了:

  • [rtsp] port:RTSP 监听端口
  • [rtmp] port:RTMP 监听端口
  • [http] port:HTTP-FLV / HLS 的访问端口
  • [rtp_proxy] portport_range:GB28181 收流的 UDP 起始端口和范围
  • [sip] port:SIP 注册端口

改配置前建议先备份,改完重启容器生效。ZLM 对个别配置项是支持热加载的,但离线环境里图省事不如图稳,直接重启容器最保险。

4.3 host网络模式为什么更省心

在实际项目中,GB28181 接入几十路摄像头很常见,用 bridge 模式要把 10000 开始的整段RTP端口映射出来,防火墙规则也复杂。如果内网环境没有太多安全分区约束,我建议直接用 host 网络:

docker run -d --name zlm \ --network host \ -v /opt/zlm/config:/opt/media/bin/config \ -v /opt/zlm/www:/opt/media/bin/www \ zlmediakit/zlmediakit:master

用 host 网络后,容器直接使用宿主机网络栈,端口全通,也不需要-p映射。代价是宿主机端口会被 ZLM 占用,端口冲突时需要手动改 config.ini。在 Linux 服务器上这个方案最省心,适用于大部分内网视频项目。

5. 把推流和拉流跑通:验证部署是否成功

5.1 先用ffmpeg推一路流

镜像导入、容器启动后,第一步验证推流。在任意一台和 ZLM 内网可达的机器上,用 ffmpeg 推一路本地视频:

ffmpeg -re -i test.mp4 -c:v libx264 -c:a aac -f flv rtmp://服务器IP:1935/live/test

如果测试机器上没有现成的视频文件,可以生成一个测试画面:

ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=25 \ -f lavfi -i sine=frequency=1000:sample_rate=44100 \ -vcodec libx264 -acodec aac \ -f flv rtmp://服务器IP:1935/live/test

推流命令不报错并持续输出画面数据,说明 RTMP 端口工作正常。这一步如果失败,优先检查 ZLM 所在服务器的 1935 端口防火墙和容器映射。

5.2 用HTTP-FLV和HLS验证出流

推流的同时,在浏览器或 VLC 里验证三种取流协议:

  • RTMP:rtmp://服务器IP:1935/live/test
  • HTTP-FLV:http://服务器IP:8080/live/test.flv
  • HLS:http://服务器IP:8080/live/test/hls.m3u8

浏览器里直接访问 HTTP-FLV 地址能看到视频画面,HLS 的 m3u8 能正常下载并播流。如果容器端口映射的是8080:80,访问时就用 8080,这个容易搞混。ZLM 自带 Web 页面,浏览器打开http://服务器IP:8080能看到服务首页,也可以用来快速判断容器是否正常。

这里提醒一点,HLS 有切片延迟,推流后通常要等几秒到十几秒才能在播放器里看到画面,不像 HTTP-FLV 几乎是秒开。验证时别急着下结论,多等一会再刷新。

5.3 GB28181摄像头接入时的额外验证点

摄像头通过国标接入时,需要再验证两个东西:

  • 摄像头SIP服务器地址填 ZLM 所在机器的IP,端口默认 5060。
  • 平台侧发起直播请求后,ZLM 要能收到 RTP 包并输出一路新流。如果发现摄像头能注册但拉流失败,多半是 RTP 接收端口没通。

验证端口连通性可以用nc或看 Docker 容器日志,ZLM 日志里会打印收到 INVITE 请求和开始接收 RTP 的信息。生产环境建议先把单路摄像头调通,再批量接入,避免一开始就面对几十路设备的复杂排查。

6. 离线部署中我踩过的坑和排查链

6.1 容器秒退:先从日志查起

容器启动后马上退出,第一时间看日志:

docker logs zlm docker inspect zlm

常见原因有三个:配置文件缺失、挂载目录权限不对、宿主机端口被占用。日志里如果提到 config.ini,基本就是配置文件问题,把默认配置拷回来即可。Mount 权限问题发生在 SELinux 开启的 CentOS 上,目录权限不够,可以加:z或者临时关闭 SELinux 验证。

6.2 拉流黑屏但日志显示服务正常

推流已经成功,HTTP-FLV 打开黑屏。这种情况先排除浏览器的问题,很多浏览器不再直接支持 HLS 或需要 flv.js。用 VLC 测试同一路流如果正常,就是播放端兼容性问题。另一个常见原因是走 bridge 网络时只映射了 80 和 1935,视频数据流能从 RTP 端口进来,但容器没有对外暴露对应端口,导致拉流会话异常,用 host 网络能避开这类问题。

6.3 镜像导入后 tag 变成 none

load 之后docker images看到REPOSITORY= <none>,这基本就是在 save 时用了镜像ID,而不是仓库名加标签。处理办法是重新打 tag:

docker tag <镜像ID> zlmediakit/zlmediakit:master

也可以在联网机器上重新 save 一次,导出时写成docker save -o zlm.tar zlmediakit/zlmediakit:master,重点是把完整名称带上。

6.4 内网防火墙导致的半通半不通

内网不是完全没防火墙,而是经常遇到过“Ping通但端口不通”的情况。容器里服务正常运行,宿主机本机访问也正常,但其他机器无法拉流,首先检查宿主机防火墙:

firewall-cmd --list-ports

CentOS 上如果跑了 firewalld,需要放行 1935、8080、554、5060/udp 和 RTP 端口段:

firewall-cmd --permanent --add-port=1935/tcp firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload

离线部署比在线部署更依赖清晰的排查顺序:先确认镜像在,再确认容器在,最后确认端口通。镜像能 load 不代表配置文件正确,配置文件正确不代表网络通了。按这个顺序排查,大部分问题都能在十分钟内定位。

本文还有配套的精品资源,点击获取

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

滑模控制原理与Simulink仿真:四旋翼鲁棒控制实战解析

滑模控制这个名字&#xff0c;乍一听很容易被吓住——又是“滑模”又是“解锁密码”&#xff0c;好像门槛很高。但真把原理啃下来&#xff0c;再把仿真和实调走一遍&#xff0c;你会发现它其实是鲁棒控制里最“皮实”的那一类方法。尤其是做四旋翼仿真、机械臂轨迹跟踪、电机伺…

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

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

简介&#xff1a;面向需要在无外网或内网环境快速部署ZLMediaKit流媒体服务器的运维与开发人员&#xff0c;这份离线包将docker镜像与安装脚本打包在一起&#xff0c;解决了离线环境下依赖拉取困难的痛点&#xff0c;适用于视频监控、直播转码等业务场景。压缩包采用gz格式&…

作者头像 李华
网站建设 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;软件部署…

作者头像 李华