☰
Docker部署WVP-Pro:GB28181视频接入平台完整实战指南
2026/10/19 5:41:35 网站建设 项目流程

做视频监控接入的同学,应该都经历过这种场面:项目现场几十上百个摄像头,品牌型号五花八门,每家都有自己的SDK和私有协议,想统一拉流预览、录像回放,不是对接这套SDK就是适配那套协议,折腾一圈下来头发都白了几根。后面有了GB28181国标协议,设备只要支持国标,就能主动注册到平台,平台直接拉流,终于不用再跟厂家SDK死磕了。WVP-Pro就是干这个的——一个基于GB28181的视频接入平台,配套ZLMediaKit做流媒体分发,能实现设备管理、实时预览、录像回放、云台控制、语音对讲这些常用功能。而用docker部署 WVP-Pro,是我目前觉得最省心、最不容易翻车的方式。

这篇文章我会从整体架构、配置拆解、完整部署流程,到摄像头接入验证、常见问题排查,一步一步讲清楚。不管你是刚接触国标接入的运维,还是准备在项目里搭一套视频汇聚平台的开发者,照着这篇文章走,基本能把docker部署 WVP-Pro这条路完整跑通。

1. WVP-Pro到底是做什么的,docker部署前先搞懂这几个组件

1.1 GB28181接入的核心逻辑

先花两分钟把基础说清楚。GB28181是视频监控领域的国家标准协议,核心思路是:摄像头等终端设备主动向一个SIP服务器注册,注册成功之后,平台可以向上级平台或者终端发起请求,拉取实时视频流、历史录像文件,也能下发云台控制指令。

这套机制里有两个角色。一个是设备端,也就是摄像头、NVR;另一个是平台端,也就是我们搭的WVP-Pro。设备端配置好SIP服务器的IP、端口、域、用户名、密码之后,就会定时向平台发起注册请求。平台收到请求后校验信息,合法就把设备加入在线列表。整个过程有点像一个电话总机,设备是分机,总机就是SIP服务器。

WVP-Pro做的核心事情,就是把这一整套复杂的SIP信令交互、设备目录树管理、录像文件索引、云台控制协议封装成Web界面和API接口。你不需要自己去写SIP协议栈,也不需要关心设备厂商私有差异,只要设备支持GB28181,就能接进平台。

1.2 WVP-Pro和ZLMediaKit的分工

很多第一次接触的人会把WVP-Pro和ZLMediaKit搞混,以为是一个东西。实际上它们是两个独立的服务,配合起来才能完成整个视频链路。

WVP-Pro是Java写的后端平台,负责所有和信令相关的逻辑:设备注册、目录查询、点播请求、录像检索、平台级联。你可以把它理解成整个系统的“大脑”,它不直接转发视频流。

ZLMediaKit是C++写的流媒体服务器,负责真正处理视频流:接收设备推过来的RTP流,转封装成RTMP、HTTP-FLV、HLS、WebRTC等格式,再分发给前端播放器。你可以把它理解成“血管和四肢”,视频数据从这里过。

docker部署 WVP-Pro的时候,这两个东西都要部署,再加上MySQL存设备数据、Redis做缓存和会话,一共四个核心服务。用docker-compose编排起来,一条命令就能把整套环境拉起来,比起手动编译Java项目和ZLMediaKit的C++源码,效率高太多。

提示:WVP-Pro和ZLMediaKit必须保持通信正常。WVP-Pro会把ZLMediaKit的secret、端口等信息写进配置,ZLMediaKit也会通过hook接口回调WVP-Pro,两端配置不一致,后面点播肯定出问题。

2. 部署WVP-Pro前,先把架构和网络模式想明白

2.1 为什么我强烈建议用docker方式部署

部署WVP-Pro的方式大致有三种:源码编译、Release包直接运行、docker容器化。前两种我都踩过坑,才最后固定用docker。

源码编译最折腾。WVP-Pro的后端是Java项目,需要JDK、Maven,还得自己改配置再打包;前端还有一套Vue项目,要Node环境编译。ZLMediaKit更麻烦,拉源码、装cmake、装依赖库、编译,运气好二十几分钟,运气不好报错能折腾一下午。现场项目最怕这种环境问题纠缠不清。

Release包直接跑,省去了编译,但环境依赖还是绕不开。Java版本对不对、FFmpeg有没有装、MySQL和Redis版本兼容性如何,都要一件一件核对。docker方式就不一样了,官方已经把应用和运行环境一起打包进镜像,你只需要把配置文件和数据库准备好,容器拉起来就是一个完整环境。

更重要的是可复制性。一个现场部署通了,把docker-compose文件和配置目录打个包,下一个现场直接搬过去改一下IP就能用。这对经常跑项目的兄弟来说,简直是刚需。

2.2 网络模式的选择,这里藏着一个大坑

docker部署 WVP-Pro时,最常见的问题是设备能注册但拉不了流,或者根本注册不上。排查到最后,十有八九是网络模式选错了。

Docker默认是bridge网络,容器有独立的IP,通过端口映射对外提供服务。看起来没什么问题,但GB28181这套协议和普通HTTP不一样。SIP信令报文里携带的IP地址是服务器自身的地址,设备会根据这个地址和端口回传RTP流。如果用bridge模式加端口映射,很容易出现信令里写的IP和实际端口映射对不上,设备把流推到错误地址去,导致点播失败。

我的建议是直接使用host网络模式。容器共享宿主机网络栈,SIP信令里携带的就是宿主机真实IP,端口也不存在映射关系,设备能直接访问流媒体端口,整个链路最简单也最不容易出错。

代价是端口规划需要自己管理,几个核心端口不能冲突:SIP的5060、WVP前端的8080、ZLMediaKit的HTTP端口、RTP收流端口范围。后面我会把端口规划列出来。

2.3 部署WVP-Pro需要的软硬件准备

梳理一下最低要求。CPU双核以上、内存4G以上,磁盘看录像留存需求,一般建议至少给系统盘留几十G以上空间,因为视频流转储和录像回放的目录都比较吃空间。操作系统我用的是Ubuntu Server和CentOS都跑过,命令上稍有差异,但docker部署的流程基本一致。

软件方面需要提前确认:Docker Engine 20.10以上,docker-compose插件或者docker-compose工具,这两个必须装好。另外准备好本项目的源码压缩包或者官方镜像,确保服务器能拉取到需要的镜像。有些内网环境没法直接拉docker仓库,那就需要提前把镜像导出再导入,这个细节后面会说。

注意:如果服务器上有旧版MySQL或者Redis占用端口,先把它们停掉或者换端口,避免容器启动时端口冲突。我见过不少现场环境,本来好好的,一执行docker compose up直接把现有服务搞挂了。

3. docker-compose编排与WVP-Pro配置拆解

3.1 端口规划与compose文件设计

部署之前,我把端口规划提前列出来,免得后面配置时来回改:

服务端口说明
WVP-Pro5060/UDPSIP注册监听
WVP-Pro8080/TCP后端API和前端页面
ZLMediaKit1935/TCPRTMP拉流
ZLMediaKit8081/TCPHTTP-FLV、HLS等
ZLMediaKit10000-20000/UDPRTP收流端口范围
MySQL3306/TCP数据库
Redis6379/TCP缓存

这里的10000到20000是ZLMediaKit收RTP流的端口范围,摄像头回传的RTP包会落在这些端口上。很多人只放行了SIP端口,拉流时设备端显示发送成功,平台这边就是播放不出来,大概率就是这个范围没放行。

docker-compose我写成了一个编排文件,四个服务放一起,network_mode全部用host,MySQL和Redis只在宿主机访问,不对外暴露额外端口。大概长这样:

version: "3.8" services: mysql: image: mysql:5.7 container_name: wvp-mysql restart: always environment: MYSQL_ROOT_PASSWORD: "your_password" MYSQL_DATABASE: "wvp" TZ: Asia/Shanghai volumes: - ./data/mysql:/var/lib/mysql - ./sql:/docker-entrypoint-initdb.d command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci network_mode: host redis: image: redis:6.2 container_name: wvp-redis restart: always command: redis-server --requirepass "your_redis_password" volumes: - ./data/redis:/data network_mode: host zlm: image: zlmediakit/zlmediakit:master container_name: wvp-zlm restart: always volumes: - ./data/zlm:/opt/media/bin/config network_mode: host wvp: build: ./wvp container_name: wvp-pro restart: always volumes: - ./conf:/wvp/conf - ./data/log:/wvp/log depends_on: - mysql - redis - zlm network_mode: host

有一点要说明,WVP-Pro建议用官方提供的镜像或者源码自行构建镜像。手动构建的好处是版本锁定、可以改配置,劣势是要花时间拉依赖打包。我更推荐先看官方仓库的docker目录,如果官方镜像能直接用,就直接拉;拉了起不来再考虑自己build。

3.2 application.yml里最容易配错的几个参数

配置是docker部署 WVP-Pro的重头戏,几乎九成的问题都出在这一个文件里。打开WVP-Pro配置目录下的application.yml,重点看以下几块。

第一块是SIP配置。sip.ip要写服务器真实内网IP,不能写127.0.0.1或者容器IP,因为这个地址会写进SIP信令,摄像头会往这个地址注册和回传。sip.port默认5060,设备配置的端口要保持一致。sip.domain是SIP域,默认3402000000,设备端填的SIP服务器ID必须和这个一致。sip.password是SIP鉴权密码,设备端配置错了,注册就不会成功。

sip: ip: 192.168.1.100 port: 5060 domain: 3402000000 password: 12345678

第二块是媒体服务配置。如果是host网络模式,media.ip写宿主机IP,media.port大部分情况下和WVP端口不同,要看README说明。media.secret要和ZLMediaKit配置文件里的secret完全一致,默认值很多文档里写的是“035c73f7-bb6b-4889-a715-d9eb2d1925cc”这种uuid格式。如果两边不一致,ZLMediaKit会拒绝WVP-Pro下发的播放指令,具体表现是设备注册正常,一点播就失败。

media: id: wvp_media ip: 192.168.1.100 port: 8081 secret: your_zlm_secret

第三块是数据库和Redis连接。MySQL地址如果是host网络,直接写127.0.0.1加端口。Redis要配置密码,并且在redis容器启动时也设置相同密码,两边对不上会导致登录会话异常。

核心经验:每次改配置,都把格式对齐检查一遍。YAML对缩进极其敏感,一个空格错位就可能导致配置没生效。我遇到过一次sip.ip没生效,排查半天发现是配置文件里多了一个多余空格。

3.3 数据库初始化这一步千万别跳过

WVP-Pro启动时不会自动建表,需要先手动初始化数据库。源码目录下有sql文件夹,里面放着建库建表的脚本。你可以把sql文件挂载到MySQL容器的/docker-entrypoint-initdb.d目录,这样MySQL第一次启动时就会自动执行,见上面的compose文件。

如果MySQL容器已经启动过,初始化脚本不会重复执行,那就要手动进容器执行:

docker exec -i wvp-mysql mysql -uroot -p"your_password" --default-character-set=utf8mb4 -e "create database if not exists wvp default character set utf8mb4 collate utf8mb4_unicode_ci;" docker exec -i wvp-mysql mysql -uroot -p"your_password" --default-character-set=utf8mb4 wvp < ./sql/初始化脚本.sql

数据库字符集务必用utf8mb4,不然设备名称带中文或者特殊字符时,存储可能报错或者乱码。初始化完成之后,检查一下表是否建好:

docker exec -i wvp-mysql mysql -uroot -p"your_password" -e "use wvp; show tables;"

这里要注意,有些版本的SQL脚本里有“source /xxx.sql”这种语句,需要把依赖脚本一起放进去,否则执行到一半会报文件找不到的错误。

4. 从零开始完整部署WVP-Pro实操记录

4.1 拉代码、改配置、启动容器

我以一套全新环境为例,完整走一遍。假设宿主机IP是192.168.1.100,系统是Ubuntu Server 22.04。

第一步,确认docker和compose已经就绪:

docker version docker compose version

第二步,创建工作目录,把WVP-Pro源码和配置目录准备好:

mkdir -p /opt/wvp-pro/{conf,sql,data/{mysql,redis,zlm,log}} cd /opt/wvp-pro git clone https://github.com/你的WVP-Pro仓库地址.git wvp-source cp -r wvp-source/sql ./sql cp -r wvp-source/src/main/resources/application.yml ./conf/

第三步,重点修改conf/application.yml,把上一步讲的sip、media、数据库、Redis参数逐项填好。改完之后可以用一个简单命令检查YAML格式:

python3 -c "import yaml; print(yaml.safe_load(open('./conf/application.yml')))"

如果缩进有问题,这条命令会直接报错。这一步很值得做,能省下很多容器起不来的时间。

第四步,准备好docker-compose.yml,放在/opt/wvp-pro目录下。然后先把MySQL、Redis、ZLMediaKit三个服务启动起来:

docker compose up -d mysql redis zlm

等待几秒后看容器状态:

docker compose ps

三个服务都要是Up状态。MySQL容器第一次启动会自动执行sql目录下的初始化脚本,等日志里出现“ready for connections”再往下走。

第五步,初始化数据库完成之后,启动WVP-Pro服务:

docker compose up -d wvp

然后持续跟踪日志,确认启动过程没有报错:

docker compose logs -f wvp

看到类似“Tomcat started on port(s): 8080”或者“wvp-pro启动成功”之类的日志输出,说明后端服务已经起来了。

4.2 前端页面与媒体服务联动验证

启动成功之后,浏览器访问http://192.168.1.100:8080,就能打开WVP-Pro的登录页面。默认账号密码以官方说明为准,我这边所用版本的初始账号是admin/admin,首次登录后建议立刻改密码。

进去之后先不要急着填设备,先把ZLMediaKit配置到平台里。在系统管理或媒体服务管理页面,新增一条媒体服务记录,填上媒体服务名称、ZLMediaKit的IP、HTTP端口、secret。保存之后,ZLMediaKit日志里一般会出现hook注册成功的提示,同时平台页面上的媒体服务状态会变成在线。

这一步完成,说明WVP-Pro和ZLMediaKit之间的双向通信已经建立,后面设备点播才有可能通。

4.3 启动后必做的健康检查

很多人看到页面能打开就觉得部署完成了,其实还有几个地方需要排查。

第一,确认SIP端口确实在监听。宿主机上执行:

netstat -lunp | grep 5060

如果没有任何输出,说明WVP-Pro的SIP服务没起来,检查sip配置或者查看docker日志。

第二,确认ZLMediaKit的RTP端口范围在监听:

netstat -lunp | grep 10000

如果没有任何输出,说明RTP收流端口没有打开,可能是ZLM配置的问题。

第三,确认防火墙没有拦截。很多云主机的安全组和本地firewalld都需要额外放行:

firewall-cmd --permanent --add-port=5060/udp firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --permanent --add-port=8081/tcp firewall-cmd --permanent --add-port=1935/tcp firewall-cmd --permanent --add-port=10000-20000/udp firewall-cmd --reload

第四,检查时区。容器默认有时是UTC,比北京时间慢8小时,录像回放和报警时间戳对不上,非常容易踩。compose文件里已经设了TZ=Asia/Shanghai,启动后可以进容器确认一下:

docker exec -it wvp-pro date

看到中国时区时间就没问题,否则要在容器或者系统的环境变量里补上时区设置。

5. 摄像头接入验证与常见问题排查

5.1 摄像头SIP注册配置与实测

平台跑起来之后,拿一台支持GB28181的摄像头做实测。进入摄像头的Web管理页面,找到GB28181或者SIP配置菜单。不同厂家界面差异很大,但核心字段一致。

SIP服务器ID填平台的SIP域,也就是配置里的sip.domain,默认是3402000000。SIP服务器地址填宿主机IP,也就是192.168.1.100。SIP服务器端口填5060。SIP用户ID一般是摄像头的国标编码,20位数字,比如34020000001320000001这种格式。SIP密码填平台上sip.password的值。SIP通道编号一般是摄像头的通道编码,也是一串20位数字。

保存配置之后,回到WVP-Pro平台页面,刷新一下设备列表,离线列表里应该出现这台摄像头。点击上线,设备状态变成在线。如果列表里一直不出现,优先检查平台日志,看SIP注册请求有没有进来:

docker compose logs -f wvp | grep -i sip

能看到注册相关日志,说明信令已经到平台,没见到设备是因为鉴权或者编码不匹配;看不到任何日志,那就是网络层就没通,去查防火墙和IP地址。

设备在线之后,直接点击实时预览,选一个通道拉流。前端正常出画面,说明整个链路已经通了。这个链路拆开看是这样的:平台向摄像头发送INVITE请求,摄像头收到请求后向平台指定的RTP端口推送视频流,ZLMediaKit在对应端口收到RTP流,再将流转换为HTTP-FLV或WebRTC格式分发给浏览器播放。

5.2 常见问题排查速查表

日常使用中遇到的问题,我整理成一张速查表,按现象排查,效率最高:

现象可能原因排查方向
设备一直注册不上SIP域、密码、端口不匹配核对平台sip.domain、password,设备端SIP服务器ID/密码/端口
平台日志看不到任何SIP包防火墙拦截UDP 5060检查安全组、firewalld、iptables,用tcpdump抓包确认
设备在线但点播放黑屏ZLM和WVP的secret不一致比对application.yml和ZLM配置文件中的secret
点播时提示媒体服务不存在WVP页面没有添加ZLMediaKit到媒体服务管理页面配置ZLM并确认在线
RTP端口无接收流量10000-20000/UDP被防火墙拦截放行端口范围,或用tcpdump确认UDP包是否到达宿主机
能出图但卡顿严重带宽不足或RTP丢包检查网络稳定性,降低摄像头码率,确认交换机带宽
录像时间不对容器时区是UTC设置TZ=Asia/Shanghai并重启容器
中文设备名乱码数据库字符集不是utf8mb4初始化时指定utf8mb4,存量数据转编码
重启后WVP起不来端口被旧进程占用排查宿主机5060或8080端口占用
页面能开但登录报错Redis密码不一致核对application.yml和redis容器启动参数

这里面有一类问题特别隐蔽。有些摄像头在注册时会校验SIP服务器ID的国标编码行政区划段,如果平台的SIP域和摄像头本身的国标编码前缀不一致,摄像头会拒绝注册,但摄像头日志里显示“注册成功”,现象非常迷惑。遇到这种情况,把平台的SIP域改成摄像头国标编码前10位所在的行政区域,再试一次。

5.3 几个我踩过之后才想明白的细节

第一个细节是改配置之后要重建还是重启。如果WVP-Pro是build镜像方式部署的,application.yml被拷进了镜像,单纯执行docker compose restart不会让新配置生效,必须重新build镜像或者用挂载方式把配置文件放进去。我建议直接用上面compose里的挂载方式,改完配置执行docker compose restart wvp就行,省去重新build的等待。

第二个细节是摄像头密码不一定只在注册时用。国标协议要求SIP信令带鉴权,如果密码错误,表现不一定是注册失败,而是注册成功后每隔一段时间被平台踢下线、重新注册。排查这类“设备掉线又上线”的问题,优先改密码重新注册。

第三个细节是媒体服务添加之后,平台里可能不会立即显示在线。可以先去ZLMediaKit的Web管理页面看一下流列表和hook事件,确认ZLMediaKit是否收到了WVP-Pro的下发指令,再回到WVP侧排查。

6. 关于WVP-Pro部署的一些心得建议

把docker部署 WVP-Pro整个流程跑下来之后,说几个我个人很看重的经验,不一定写在哪篇文档里,但对实际项目很有用。

第一个经验是能先跑通再扩容。我第一次在一个现场部署的时候,一上来就想把一百多路摄像头全部接入,结果设备填了一大半,平台日志各种报错,排查起来非常吃力。后来学乖了,先在测试环境部署好,用一两台摄像头把注册、点播、录像、云台全部验证通过,再带着配置去现场,二十分钟就能搞定基础环境。这个习惯帮我避开了很多现场翻车的场景。

第二个经验是记录的初始配置比什么都重要。搞完一套环境之后,把application.yml、docker-compose.yml、初始化SQL打包存一份,把宿主机IP、端口、密码记在小本子上。后面不管是迁移还是复制部署,这套记录可以节省一整个下午的排查时间。光靠记忆,不出一个星期就忘干净了。

第三个经验是版本锁定。不要看见latest标签就直接拉,WVP-Pro和ZLMediaKit的版本更新节奏不算慢,有时候大版本之间的配置格式变了,新镜像和老配置文件不兼容,起都起不来。最好锁定稳定版本标签,升级前先看变更说明,在测试环境验证过再动生产部署。

最后说一个可以继续深入的方向。如果WVP-Pro跑通了基础功能,可以试试平台级联,把下级平台的设备和录像共享给上级监管平台,这在很多园区、学校、工厂项目里是刚需。docker部署的架构本身就是分布式的,后面再挂级联服务、扩展存储节点,都比单机部署灵活得多。先把这套基础环境搭稳,后面的一切都好说。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询