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% 的真实工程坑。

(完)

相关推荐
西岸行者2 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意2 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码2 天前
嵌入式学习路线
学习
毛小茛2 天前
计算机系统概论——校验码
学习
babe小鑫2 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms2 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下2 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。2 天前
2026.2.25监控学习
学习
im_AMBER2 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J2 天前
从“Hello World“ 开始 C++
c语言·c++·学习