DEPLOYMENT GUIDE · DOCKER COMPOSE
UVP-GB28181 容器版部署手册
用 Docker Compose 把统一视频接入平台装到一台 Linux 服务器上。这条路径和绿色包(独立部署包)跑的是同一套程序、同一段端口,区别只在于运行形态:绿色包是「解压即用、零预装」,容器版要求宿主机先有 Docker。
先想清楚要不要选它:如果你的目标机是干净的操作系统、不想装 Docker,用Linux 绿色包更省事。容器版的价值在于「一台机器上要跑多个系统」「需要统一的容器生命周期管理」「运维团队已经有 Docker 运维规范」这几种场景。
1. 两种形态的差异
同一套平台提供了两种安装形态,功能完全一致,选择上只看运维习惯:
| 对比项 | 绿色包(独立部署包) | 容器版(Docker Compose) |
|---|---|---|
| 预装要求 | 无,解压即用 | Docker 20.10+ / Compose v2 |
| 进程形态 | 宿主机上的普通进程 | 四个容器(全部 host 网络) |
| 前端访问 | http://IP:51000 | https://IP:51000 |
| 明文 HTTP | http://IP:51001 | http://IP:51001 |
| 端口段 | 51000–51064 | 51000–51064(同一段) |
| 数据目录 | 包根的 data/、config/ | /opt/uvp-gb28181/data、config |
| 开机自启 | uvp-gb28181-service-install.sh 注册 systemd | Docker 的 restart: unless-stopped |
| 升级方式 | 页面导入离线升级包 | 页面导入离线升级包(同一条链路) |
51000 / 51001 的协议是反的:绿色包在 2026 年 10 月把默认入口改成了「明文 51000、HTTPS 51001」,而容器版仍是「HTTPS 51000、明文 51001」(已经过现场验收,未跟随改顺序)。从一种形态迁到另一种时,访问地址必须改,照抄另一份教程会落到另一套协议上。
2. 环境要求
| 项目 | 要求 |
|---|---|
| CPU 架构 | x86_64(amd64)。容器版目前只发布 amd64 |
| 操作系统 | 能装 Docker 20.10+ 的 Linux 均可:Ubuntu / Debian / CentOS / RHEL / 银河麒麟 V10 / 统信 UOS / openEuler |
| Docker | 20.10 及以上,且带 Compose v2(docker compose version 有输出) |
| 其他依赖 | python3(生成配置与建库)、openssl(生成自签证书)——主流发行版自带,精简系统可能缺 |
| 内存 | 建议 2 GB 及以上 |
| 磁盘 | 建议 20 GB 以上可用空间(要额外放四个镜像,约 1 GB) |
| 运行身份 | 安装脚本需要 root(sudo ./install.sh) |
离线包不包含 Docker 本身:这是容器版与绿色包最大的区别。目标机连不上外网时,需要先用系统的离线源把 Docker 装好,再跑安装脚本。
3. 部署步骤总览
- 确认 Docker 与 Compose v2 可用
- 下载容器版离线包并核对 SHA-256
- 解压,认识包内结构
- 执行
sudo ./install.sh完成安装 - 放行防火墙 51000–51064(TCP + UDP)
- 浏览器登录并修改初始口令
- 完成首次接入向导,配置 SIP
4. 第一步:确认 Docker 环境
在目标机执行:
docker version --format '{{.Server.Version}}'
docker compose version
python3 --version
openssl version三条都要有输出。docker compose version 报 unknown command 说明装的是老式 docker-compose(v1,Python 版),本项目用到的 compose 规范它不支持,必须先升级到 Compose v2 插件。
5. 第二步:下载并核对
打开官网下载页,在容器版那一栏下载 uvp-gb28181-docker-linux-amd64-<版本>.tar.gz,同时记下页面标注的 SHA-256:
sha256sum uvp-gb28181-docker-linux-amd64-*.tar.gz输出与下载页标注的完全一致才算传输完整。
6. 第三步:解压并认识包结构
mkdir -p /opt/uvp-docker && cd /opt/uvp-docker
tar -xzf uvp-gb28181-docker-linux-amd64-<版本>.tar.gz
cd uvp-gb28181-docker-linux-amd64-<版本>| 包内路径 | 作用 |
|---|---|
install.sh | 安装入口:加载镜像、建目录、生成配置与证书、建库、启动 |
compose.yml | 四个服务的编排模板 |
.env.example | 参数样例(端口段、镜像前缀、运行身份) |
images/*.tar | 四个容器的镜像归档,离线模式的全部来源 |
docker/ | 四个 Dockerfile 与容器入口脚本,客户要自建镜像时用 |
tools/make-config.py | 配置生成器,与绿色包用的是同一个文件 |
config/config.example.yml | 配置源模板 |
version.json | 包版本号 |
包内没有软链接、没有绝对路径条目,解压到任何目录都是自包含的。安装脚本会把运行目录建在 /opt/uvp-gb28181,与解压位置无关。
7. 第四步:执行安装
sudo ./install.sh脚本会依次完成:
- 环境预检:docker / compose v2 / python3 / openssl 逐个检查,缺哪个直接报出来并给出安装命令;
- 端口预检:按
ss的监听状态检查 51000–51064 整段。注意判据是「有没有人在监听」,不是「能不能绑定」——51000 段落在系统的动态端口范围里,任何一条出站连接都会临时占用段内端口,按 bind 判定会误报; - 加载镜像:
docker load四个归档,并逐个校验镜像身份(config id); - 生成配置:建
/opt/uvp-gb28181/{config,data,logs,run},写config.yml与.env,生成部署密钥; - 生成自签证书:SAN 里带上本机 IP,浏览器首次访问需要点「继续访问」;
- 建库:初始化 SQLite 数据库;
- 启动并等待就绪:最多等 5 分钟,超时会把后端日志打出来。
结束后打印访问地址、初始账号与常用命令。
端口段冲突时整段平移
sudo ./install.sh --port-base 53000这会得到 53000 管理页 / 53001 明文 / 53002 后端 / 53003 Redis / 53004 ZLM,RTP 收流段 53014–53063,SIP 53064。
不要只传单个端口:只写 --https-port 53000 会把其余端口留在 51000 段,形成「混合段」——功能上能跑,但防火墙就得开两条规则,而且现场看不出来。要换段请用 --port-base。
8. 第五步:放行防火墙
容器全部走 host 网络,端口直接占宿主机。要让局域网内的设备和其他电脑访问,放行 51000–51064 整段,TCP 和 UDP 都要(流媒体的收流端口是 UDP):
# Ubuntu / Debian / 统信 UOS(ufw)
sudo ufw allow 51000:51064/tcp
sudo ufw allow 51000:51064/udp
# CentOS / RHEL / 银河麒麟 / openEuler(firewalld)
sudo firewall-cmd --permanent --add-port=51000-51064/tcp
sudo firewall-cmd --permanent --add-port=51000-51064/udp
sudo firewall-cmd --reload云服务器还要在控制台的安全组里放行同样范围。
9. 第六步:登录并修改口令
浏览器访问 https://<服务器IP>:51000,初始账号 admin、口令 123456,登录后系统强制要求修改口令,改完进入首次接入向导。
证书是自签的,浏览器会提示不安全,点「继续访问」即可;要用正式证书,把证书文件放进 /opt/uvp-gb28181/config/tls/ 后重启前端容器。
10. 第七步:完成接入向导
向导录入四项信息:部署方式、网络地址、SIP 身份、确认保存。其中 SIP 端口已预填为 51064(= 端口段最后一位,用 --port-base 平移后会跟着变成 53064)。
设备侧要改成同一个 SIP 端口:国标设备出厂默认 5060,不会自动跟随平台。平台填 51064、设备填 5060,表现就是「设备显示已注册、平台里看不到」——这一条现场踩得最多。
11. 端口规划
| 端口 | 用途 |
|---|---|
| 51000 | 管理页面(HTTPS) |
| 51001 | 明文 HTTP(跳转 HTTPS + 扫码 / API) |
| 51002 | 后端 API |
| 51003 | Redis(仅回环,不对外开放) |
| 51004 | 流媒体 HTTP / API |
| 51005 | RTSP |
| 51006 | RTMP |
| 51007 | 流媒体 HTTPS |
| 51008 | WebRTC |
| 51009 / 51010 | WebRTC 信令(明文 / TLS) |
| 51011 | SRT |
| 51012 | ONVIF |
| 51013 | WebRTC ICE |
| 51014–51063 | RTP 收流段(UDP + TCP 各 50 个) |
| 51064 | SIP 信令(UDP + TCP) |
为什么必须用 host 网络:这是国标视频平台,不是普通 Web 应用。平台要把「自己的 IP」写进 SDP 发给摄像头,走 bridge 网络时写进去的是容器内网地址,设备按它推流根本连不进来 —— 表现为「信令全成功、就是没画面」,而日志里一切正常。代价是容器之间没有再隔离,端口冲突只能靠安装脚本的预检挡住。
12. 日常运维
安装根是 /opt/uvp-gb28181,在该目录下执行:
| 操作 | 命令 |
|---|---|
| 查看状态 | docker compose -p uvp-gb28181 ps |
| 跟随后端日志 | docker compose -p uvp-gb28181 logs -f backend |
| 停止(数据保留) | docker compose -p uvp-gb28181 down |
| 重新启动 | docker compose -p uvp-gb28181 up -d |
| 重启单个服务 | docker compose -p uvp-gb28181 restart backend |
备份
cd /opt/uvp-gb28181
docker compose -p uvp-gb28181 down
sudo tar -czf uvp-backup-$(date +%F).tar.gz data configdata/ 里是数据库、Redis 落盘、上传文件与升级状态;config/ 里是全部配置、部署密钥与证书。这两个目录就是整台机器的全部状态,其余都可以由镜像重新生成。
升级
首选:在页面里导入升级包
从 1.1.15 的安装包开始,容器版自带升级助手(uvp-updater.service,装在宿主机而不是容器里)。它和绿色包用的是同一条链路,操作也一样:
- 到官网下载
uvp-<版本>-linux-amd64-compose.upgrade.tar(容器版专用,与绿色包的包不通用); - 在平台里打开「系统 → 服务升级」,选「导入升级包」,把文件原样传上去(不用解压);
- 平台会依次做:导入新镜像 → 停服 → 备份数据库与编排 → 执行数据库迁移 → 切换编排 → 启动并自检。自检不通过会自动回滚到升级前的状态。
升级只替换镜像与编排模板,data/ 与 config/ 原样保留。
为什么助手要装在宿主机:升级过程中要把这几个容器停掉再重建,干这件事的进程如果本身就在被停的容器里,它会在第一步把自己杀掉,升级永远停在半路。所以它是 systemd 服务,容器里的平台只是通过 /run/uvp-updater/updater.sock 指挥它。
备用:手工换镜像
页面上导入失败、或者想完全手工控制时,按下面走。容器版升级的本质是换镜像:新版本镜像 tag 与旧版本不同,所以旧镜像还在,随时能改回来。
# 1. 把新版本的全量包解压到任意目录
tar -xzf uvp-gb28181-docker-linux-amd64-<新版本>.tar.gz
cd uvp-gb28181-docker-linux-amd64-<新版本>
# 2. 加载新镜像(只是多出几个 tag,不动旧镜像)
sudo docker load --input images/uvp-gb28181-docker-images-amd64-<新版本>.tar
# 3. 停服并备份(这一步不能省)
cd /opt/uvp-gb28181
docker compose -p uvp-gb28181 down
sudo tar -czf uvp-backup-$(date +%F-%H%M).tar.gz data config
# 4. 换编排模板与版本号
sudo cp <解压目录>/compose.yml /opt/uvp-gb28181/compose.yml
sudo sed -i 's/^UVP_VERSION=.*/UVP_VERSION=<新版本>/' /opt/uvp-gb28181/.env
# 5. 起服
docker compose -p uvp-gb28181 up -d起完后 docker compose -p uvp-gb28181 ps 看四个容器是否都 healthy,再打开页面确认右上角版本号已变。
回滚同样简单:把 .env 里的 UVP_VERSION 改回旧版本,docker compose -p uvp-gb28181 up -d 即可 —— 旧镜像没有被删。只有当数据库迁移已经执行过、且新版本做了不兼容的结构变更时,才需要连 data/ 一起还原(所以第 3 步的备份必须做)。
1.1.15 之前装的容器版没有升级助手,页面里会显示「升级助手未运行」。这种实例请先按上面的手工步骤升到 1.1.15 或更高(install.sh 会把助手装上),之后就能用页面内升级了。
不要手工编辑 /opt/uvp-gb28181/compose.yml:它是受管模板,升级时会被新版整体替换 —— 改过的内容会丢。要改端口或挂载,改同目录的 .env,或者用 install.sh --port-base 重新生成。
迁移到另一台机器
- 新机器装好同版本的容器版(
install.sh); down掉新机器上的服务;- 把旧机器的
data/与config/覆盖过去; up -d。
跨形态迁移(容器版 ↔ 绿色包)同样只搬这两个目录,但记得改访问端口顺序,并核对 config/config.env 里的端口段。
13. 常见问题
安装报「需要 Docker Compose v2」
先跑 docker compose version。报 unknown command: docker compose 是只装了老式 docker-compose;报权限错误是当前用户在 docker 组之外 —— 安装脚本本来就要 sudo,但手工验证时用 sudo docker compose version 确认。
提示缺少 python3 或 openssl
最小化安装的系统会缺。Debian/Ubuntu:apt install -y python3 openssl;RHEL / 麒麟 / openEuler:yum install -y python3 openssl。装完重跑 install.sh。
报「端口被占用」
脚本用的是 ss 的监听状态判定,不会把出站连接的临时端口误判成占用。真被占了(比如机器上已经跑着别的 Web 服务)就整段平移:sudo ./install.sh --port-base 53000。注意 SIP 端口会跟着变成 53064,设备侧要一起改。
装完页面打不开
先 sudo docker compose -p uvp-gb28181 ps 看四个容器是不是都 Up。都 Up 却打不开,检查三件事:端口是不是 51000 而不是 51002;协议是不是 https://(容器版 HTTPS 在前);证书警告是不是点了「继续访问」。只有前端没起来时看 /opt/uvp-gb28181/logs/nginx/。
设备注册不上,或注册上了没画面
两种情况最常见:① 设备侧 SIP 端口没改成 51064(出厂默认 5060);② 防火墙只放行了 TCP,UDP 没放 —— RTP 收流走 UDP,不放行就是「信令通、画面空」。
重复执行 install.sh 会不会覆盖数据
不会。安装根已存在且非空时脚本直接拒绝执行,并提示「已装过就用升级流程」。要在同一台机器装第二套实例,用 --root 指定别的目录。
和绿色包的数据能互相迁移吗
能。搬 data/ 与 config/ 两个目录即可,数据库结构、业务数据完全一致。需要额外确认的只有两件事:访问端口的协议顺序(容器版 HTTPS 在 51000,绿色包在 51001),以及 config.env 里的端口段。