RK3588 Docker 中部署 GStreamer + MPP 并固化镜像(完整踩坑实录)
关键词:RK3588 / Docker / GStreamer / MPP / gst-rkmpp / no space left on device
目标读者:在 RK3588(或同类 Rockchip SoC)板卡上,使用 Docker 搭建多媒体开发环境的工程人员
目标:
- 在 Docker 中完成 GStreamer + Rockchip MPP 的可用环境
- 将环境固化为镜像并导出到外置硬盘
- 系统性记录从头到尾的问题、原因与工程级解决方案
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 三条"血的经验"
- Docker 的瓶颈永远是 data-root / tmp,不是你的 tar 放哪
- 容器是过程,镜像才是成果
- 板卡环境下: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 工程级经验总结(建议直接记住)
- RK 板子 + Docker:优先
--net=host - 容器内第一件事:
unset *_proxy apt update必备ForceIPv4- 不要用 ping 判断网络是否存在(先装工具)
- 网络问题 ≠ Docker 问题,90% 是 DNS / 代理问题
9. 后续可扩展方向
- 编译并加入
gst-rkmpp(硬解插件) - 固化为
ddd_v3(真正硬解终态) - 加入 FFmpeg / RTSP / AI 推理
- 用 docker-compose 做量产部署
到此为止,这套笔记已经覆盖:
Docker + RK3588 + 多媒体开发中 90% 的真实工程坑。
(完)