RK3588 Docker 中部署 GStreamer + MPP 并固化镜像(完整踩坑实录)

RK3588 Docker 中部署 GStreamer + MPP 并固化镜像(完整踩坑实录)

关键词:RK3588 / Docker / GStreamer / MPP / gst-rkmpp / no space left on device

目标读者:在 RK3588(或同类 Rockchip SoC)板卡上,使用 Docker 搭建多媒体开发环境的工程人员

目标

  1. 在 Docker 中完成 GStreamer + Rockchip MPP 的可用环境
  2. 将环境固化为镜像并导出到外置硬盘
  3. 系统性记录从头到尾的问题、原因与工程级解决方案

0. 背景与总体思路

在 RK3588 板卡上做多媒体开发(视频解码/编码、AI 视觉、推流显示),MPP(Media Process Platform) 是硬件能力的核心;而 GStreamer 是最常用、最工程化的多媒体框架。

本次实践采用:

  • 宿主机:RK3588 Linux
  • 容器化:Docker(便于隔离、复现与交付)
  • 目标产物 :一个可直接分发的 Docker 镜像(ddd_v2

关键难点并不在"怎么装",而在:

  • 板卡根文件系统空间极小
  • Docker 的临时目录与数据目录设计
  • GitHub / gitee 网络与 DMCA 问题
  • docker load/save 的隐藏磁盘占用

1. 初始状态与约束条件

1.1 板卡磁盘结构(典型 RK3588)

text 复制代码
/dev/mmcblk0p6   ~3G   /root-ro   (系统只读根)
/dev/mmcblk0p8  ~43G  /userdata  (Docker Root Dir 实际在这里)
/dev/sda1      120G  /media/ema/lsh (外置硬盘)

关键约束:

  • /root-ro 几乎满,不可用
  • /userdata 空间有限(30~40G)
  • 外置硬盘空间充足,但 Docker 默认不会直接使用

2. Docker 镜像加载阶段的第一个大坑

2.1 问题现象

bash 复制代码
docker load -i ddd_image.tar
# 报错:no space left on device

即便 tar 包在外置硬盘,仍然失败。

2.2 根因分析(非常关键)

  • docker load 解包时:

    • 所有 layer 都会先写入 Docker Root Dir
    • /userdata/docker
  • 与 tar 文件放在哪里 无关

结论

Docker 的真实瓶颈在 data-root,不是你 tar 包的位置。

2.3 解决思路

  • 不改 Docker 行为
  • 只保证 /userdata 有足够空间
  • 后续导出阶段还会再次遇到类似问题

3. Docker 容器内安装 GStreamer

3.1 正确进入容器(网络 + 设备映射)

bash 复制代码
docker run -it --name ddd_dev \
  --net=host --privileged \
  -v /dev:/dev \
  -v /root/zht_docker:/workspace \
  ddd_image:v01 /bin/bash

说明:

  • --net=host:避免 DNS/apt 问题
  • --privileged + /dev:访问 /dev/mpp_service

3.2 安装 GStreamer

bash 复制代码
apt update
apt install -y \
  gstreamer1.0-tools \
  gstreamer1.0-plugins-base \
  gstreamer1.0-plugins-good \
  gstreamer1.0-plugins-bad \
  gstreamer1.0-plugins-ugly \
  gstreamer1.0-libav

3.3 验证(基础验收)

bash 复制代码
gst-launch-1.0 --version
gst-launch-1.0 videotestsrc num-buffers=60 ! fakesink

通过即代表:

  • GStreamer 核心 OK
  • 插件系统 OK

4. 安装 Rockchip MPP(核心步骤)

4.1 问题:GitHub / gitee 全部需要验证

现象包括:

  • git clone 要用户名
  • SSL handshake 失败
  • GitHub 仓库 DMCA 下架

4.2 工程级结论

在受限网络/板卡环境中:
永远不要依赖 git clone。

4.3 正确解法:宿主机下载 → 容器挂载

在宿主机:

bash 复制代码
unset http_proxy https_proxy all_proxy
cd /root/zht_docker
git clone --depth=1 https://gitee.com/openFyde/rockchip-linux-mpp.git mpp

容器内直接可见:

text 复制代码
/workspace/mpp

4.4 编译与安装 MPP(容器内)

bash 复制代码
apt install -y cmake make gcc g++ pkg-config libdrm-dev
cd /workspace/mpp
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=ON
make -j$(nproc)
make install
ldconfig

4.5 验收

bash 复制代码
ldconfig -p | grep rockchip_mpp
ls -l /dev/mpp_service

至此:

  • MPP 用户态 + 内核态 已打通

5. 容器 ≠ 镜像:为什么要 commit

5.1 典型误区

  • 使用 --rm 启动容器
  • 在容器里装完一堆东西
  • exit 全没了

5.2 正确认知

  • 容器是临时运行态
  • 镜像才是交付物

5.3 正确操作(宿主机)

bash 复制代码
docker commit ddd_dev ddd_v2:latest
docker images | grep ddd_v2

到这里,哪怕你拔电、重启,ddd_v2 都不会丢。


6. docker save 的终极大坑(重点)

6.1 问题现象

bash 复制代码
docker save ddd_v2 | gzip > /media/ema/lsh/ddd_v2.tar.gz
# 报错:no space left on device

错误路径:

text 复制代码
/userdata/docker/tmp/docker-export-xxxx

6.2 根因(很多人不知道)

  • docker save

    • 先在 DockerRootDir/tmp 生成完整导出内容
    • 再写向目标文件
  • 即使目标在硬盘,tmp 仍在 /userdata

6.3 错误尝试(无效)

  • ❌ 删除容器
  • ❌ 改 tar 输出路径
  • ❌ 清理 /tmp

6.4 正确解法(工程级)

把 Docker 的 tmp 目录软链到硬盘

bash 复制代码
systemctl stop docker
mkdir -p /media/ema/lsh/docker-tmp
rm -rf /userdata/docker/tmp
ln -s /media/ema/lsh/docker-tmp /userdata/docker/tmp
systemctl start docker

验证:

bash 复制代码
ls -ld /userdata/docker/tmp
# 应指向 /media/ema/lsh/docker-tmp

6.5 导出成功

bash 复制代码
docker save ddd_v2:latest | gzip -1 > /media/ema/lsh/ddd_v2.tar.gz
sync
ls -lh /media/ema/lsh/ddd_v2.tar.gz

7. 最终状态与工程结论

7.1 你最终得到了什么

  • ✅ 可复现的 Docker 镜像 ddd_v2
  • ✅ 内含 GStreamer + MPP
  • ✅ 可离线分发(tar.gz)
  • ✅ 规避了板卡存储与网络问题

7.2 三条"血的经验"

  1. Docker 的瓶颈永远是 data-root / tmp,不是你的 tar 放哪
  2. 容器是过程,镜像才是成果
  3. 板卡环境下:zip > git clone

8. Docker 上网问题的系统性总结(高频踩坑)

在整个过程中,Docker 容器无法上网 是一个反复出现、极具迷惑性的难点。这里单独做一次工程化总结,便于今后直接对照排查。


8.1 典型问题现象

在容器内常见表现包括:

bash 复制代码
apt update           # 卡住 / 无任何输出
ping www.baidu.com   # command not found 或无法解析
curl https://xxx     # SSL handshake failed / timeout

而宿主机本身是可以正常上网的


8.2 问题根因分类(非常重要)

Docker 上网问题不是一个原因,而是以下几类叠加:

(1)容器网络模式问题
  • 默认 bridge 网络下:

    • DNS 转发依赖 Docker daemon
    • RK 板子上经常配置不完整

解决方案(推荐)

bash 复制代码
docker run --net=host ...

在嵌入式板卡 / 工程环境中,--net=host最高成功率方案


(2)DNS 配置异常(最常见)

容器内 /etc/resolv.conf 常见问题:

text 复制代码
nameserver 172.x.x.x
nameserver fe80::xxxx
  • IPv6 DNS 不可达
  • Docker 自动注入的 DNS 在板卡环境不可用

解决方式 A:强制 IPv4(最快)

bash 复制代码
apt -o Acquire::ForceIPv4=true update

解决方式 B:手动写 DNS(推荐)

bash 复制代码
echo -e "nameserver 8.8.8.8
nameserver 114.114.114.114" > /etc/resolv.conf

(3)宿主机存在代理,但容器被强制继承

明显特征:

text 复制代码
正在连接 127.0.0.1:7890...
SSL handshake failed

这是宿主机代理端口被容器继承,但容器内并没有代理服务。

解决方案(必须做)

bash 复制代码
unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY

这一条在 下载 MPP / gst-rkmpp 源码 时尤为关键。


(4)容器内基础工具缺失(误判为"没网络")

很多基础镜像中:

  • 没有 ping
  • 没有 ip
  • 没有 ifconfig

导致误以为"网络不通"。

补齐工具后再判断

bash 复制代码
apt install -y iproute2 iputils-ping net-tools curl ca-certificates

8.3 一套"必通"的 Docker 上网模板(推荐保存)

bash 复制代码
docker run -it --name dev \
  --net=host \
  --privileged \
  -v /dev:/dev \
  IMAGE /bin/bash

容器内第一件事:

bash 复制代码
unset http_proxy https_proxy all_proxy
apt -o Acquire::ForceIPv4=true update

8.4 apt update 卡住的快速定位方法

bash 复制代码
# 1. 看 DNS
cat /etc/resolv.conf

# 2. 直连 IP(不走 DNS)
apt -o Acquire::ForceIPv4=true update

# 3. 测试 TCP
curl -I https://1.1.1.1

通过这三步,可以快速判断是:

  • DNS 问题
  • IPv6 问题
  • 代理问题

8.5 工程级经验总结(建议直接记住)

  1. RK 板子 + Docker:优先 --net=host
  2. 容器内第一件事:unset *_proxy
  3. apt update 必备 ForceIPv4
  4. 不要用 ping 判断网络是否存在(先装工具)
  5. 网络问题 ≠ Docker 问题,90% 是 DNS / 代理问题

9. 后续可扩展方向

  • 编译并加入 gst-rkmpp(硬解插件)
  • 固化为 ddd_v3(真正硬解终态)
  • 加入 FFmpeg / RTSP / AI 推理
  • 用 docker-compose 做量产部署

到此为止,这套笔记已经覆盖:
Docker + RK3588 + 多媒体开发中 90% 的真实工程坑。

(完)

相关推荐
AI_56782 小时前
K8s新手入门:从“Pod创建”到“服务暴露”,3个案例理解容器编排
人工智能·学习·测试工具
炽烈小老头2 小时前
【每天学习一点算法 2026/01/21】倒二进制位
学习·算法
在繁华处2 小时前
Markdow文档初学
学习
weixin_481950352 小时前
跟AI学习用python制作下载器-3
开发语言·python·学习
代码游侠2 小时前
学习笔记——GPIO按键与中断系统
c语言·开发语言·arm开发·笔记·嵌入式硬件·学习·重构
楼田莉子2 小时前
Linux学习之库的原理与制作
linux·运维·服务器·c++·学习
枷锁—sha2 小时前
【Vulhub】1Panel 访问控制绕过实战指南 (CVE-2024-39907)
运维·学习·安全·网络安全
浅念-3 小时前
C++第一课
开发语言·c++·经验分享·笔记·学习·算法
charlie1145141913 小时前
现代嵌入式C++教程:对象池(Object Pool)模式
开发语言·c++·学习·算法·嵌入式·现代c++·工程实践