首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >openharmoney中运行docker

openharmoney中运行docker

作者头像
用户9048088
发布2026-06-15 20:11:32
发布2026-06-15 20:11:32
50
举报

OpenHarmony 5.0.3 适配 Docker 环境的全流程技术实践与解析

一、引言:OpenHarmony 容器化生态的技术价值

OpenHarmony 作为面向全场景的分布式操作系统,其嵌入式与工业级应用场景对应用隔离环境一致性资源可控性提出了更高需求。Docker 作为轻量级容器技术,可通过内核级虚拟化实现应用与宿主环境的解耦,为 OpenHarmony 扩展复杂应用生态(如边缘计算、工业控制组件)提供关键支撑。

本文基于 OpenHarmony 5.0.3 版本,以 PurplePiOH 开发板(瑞芯微 RK3566 架构)为硬件载体,从环境构建→源码适配→内核配置→镜像编译→Docker 初始化全流程,拆解嵌入式场景下 OpenHarmony 支持 Docker 的技术细节,为开发者提供可复用的工程化方案。

二、环境前置准备:硬件规格与系统优化

Docker 运行依赖内核特性与充足资源,需先完成硬件配置与系统参数调优,避免编译失败或容器启动异常。

2.1 硬件最小规格定义

OpenHarmony 5.0.3 编译与 Docker 运行需满足以下硬件阈值,核心瓶颈在于磁盘空间(源码 + 中间文件 + 镜像)与内存(内核 BTF 编译需求):

硬件组件

规格要求

技术说明

存储(HD)

≥250GB

含源码(约 50GB)、编译中间文件(约 100GB)、最终镜像(约 20GB)及预留空间

CPU

4C(x86-64)

多核心可并行加速编译,推荐 8C 以上缩短耗时

内存(Mem)

≥4GB

需配合虚拟内存满足 Linux 5.10 内核 BTF 编译的 10GB 内存需求

2.2 系统级资源优化
2.2.1 减少磁盘预留空间

Linux 系统默认预留 5% 磁盘空间用于 root 紧急修复,编译场景下可通过 tune2fs 调整为 1%,释放存储空间:

代码语言:javascript
复制
tune2fs -m 1 /dev/vda  # /dev/vda 为系统根分区,需根据实际分区调整

技术原理tune2fs 是 ext 系列文件系统工具,-m 1 表示将预留空间比例设为 1%,避免默认 5% 预留导致的存储空间浪费(250GB 磁盘可多释放约 10GB)。

2.2.2 配置虚拟内存(Swap)

编译 Linux 5.10 内核 BTF(BPF Type Format,用于 BPF 程序类型信息解析)需至少 10GB 内存,4GB 物理内存需补充 8GB 虚拟内存:

代码语言:javascript
复制
\# 1. 创建 8GB 交换文件

fallocate -l 8G /swapfile  # 比 dd 命令更高效,直接分配连续空间

\# 2. 限制权限,仅 root 可访问(避免安全风险)

chmod 600 /swapfile

\# 3. 格式化为交换分区

mkswap /swapfile

\# 4. 启用交换分区

swapon /swapfile

\# 5. 配置开机自动挂载(避免重启失效)

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

关键说明:BTF 是内核态与用户态 BPF 程序交互的类型元数据,Docker 网络(如 bridge 模式)与安全策略(如 seccomp)依赖 BPF 机制,因此必须保证内核 BTF 编译成功,虚拟内存是低配置环境的关键补充。

三、编译环境与工具链构建:基础依赖标准化

OpenHarmony 编译依赖多工具链与库文件,需基于 Ubuntu 22.04(LTS 版本,兼容性最优)完成标准化部署。

3.1 系统环境选择

推荐使用 Ubuntu 22.04 LTS,原因如下:

  1. 内核版本(5.15)与 OpenHarmony 5.0.3 依赖的 Linux 5.10 内核兼容性好,减少交叉编译冲突;
  2. 官方软件源包含编译所需的大部分工具,无需手动编译依赖;
  3. LTS 版本支持周期长(5 年),适合稳定的开发环境。
3.2 工具链与依赖安装

通过 apt 与手动部署结合,完成编译工具、交叉编译链、版本控制工具等核心依赖的安装:

代码语言:javascript
复制
\# 1. 安装 aptitude(比 apt 更智能的依赖解决工具)

sudo apt-get install aptitude

\# 2. 安装核心编译依赖(分类说明见下文)

sudo aptitude install -y binutils binutils-dev git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib gcc-arm-none-eabi gcc-arm-linux-gnueabi x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 bc gnutls-bin python3-pip ruby genext2fs device-tree-compiler make libffi-dev e2fsprogs pkg-config perl openssl libssl-dev libelf-dev libdwarf-dev u-boot-tools mtd-utils cpio doxygen liblz4-tool openjdk-8-jre gcc g++ texinfo dosfstools mtools default-jre default-jdk libncurses5 apt-utils wget scons tar rsync git-core libxml2-dev lib32z-dev grsync xxd libglib2.0-dev libpixman-1-dev kmod jfsutils reiserfsprogs xfsprogs squashfs-tools git-lfs

\# 3. 补充系统工具依赖

sudo apt-get install -y pcmciautils quota ppp libtinfo-dev libtinfo5 libncurses5-dev libncursesw5 libstdc++6 vim ssh locales gcc-arm-linux-gnueabi

\# 4. 部署 repo 工具(多仓库管理,OpenHarmony 源码依赖)

mkdir -p /root/bin  # 创建 repo 存放目录

curl -o /root/bin/repo https://mirrors.tuna.tsinghua.edu.cn/git/git-repo  # 国内源加速

chmod a+x /root/bin/repo  # 赋予执行权限

\# 5. 配置环境变量(永久生效)

vi \~/.bashrc

\# 添加以下内容:

export PATH=/root/bin:\$PATH  # 加入 repo 路径

export NODE\_HOME=./prebuilts/build-tools/common/nodejs/current  # Node.js 路径(编译脚本依赖)

export NODE\_PATH=\$NODE\_HOME/lib/node\_modules

export PATH=\$PATH:\$NODE\_HOME/bin

alias rm='rm -rf'  # 简化删除命令(可选)

alias rmdir='rm -rf'

\# 生效环境变量

source \~/.bashrc
工具链分类解析

工具类别

关键组件

作用说明

版本控制

git、git-lfs、repo

git 管理单仓库,git-lfs 处理大文件(如预编译镜像),repo 管理多仓库源码

编译工具链

gcc-multilib、g+±multilib

多架构编译支持(x86-64 宿主→ARM64 目标)

交叉编译

gcc-arm-linux-gnueabi

ARM 架构交叉编译工具,用于编译内核与硬件驱动

构建工具

scons、make、ninja(隐含)

OpenHarmony 采用 scons+ninja 构建系统,ccache 加速编译缓存

内核与驱动依赖

device-tree-compiler、libelf-dev

DTC 编译设备树,libelf 处理 ELF 格式文件(内核模块)

系统工具

e2fsprogs、dosfstools

格式化文件系统(如 ext4、vfat),用于生成镜像分区

四、源码获取与配置调优:适配 Docker 编译需求

OpenHarmony 源码需通过 repo 拉取,并针对 Docker 依赖进行配置修正,解决编译冲突与版本兼容问题。

4.1 源码拉取(基于 5.0.3 Release 版本)
代码语言:javascript
复制
\# 1. 进入源码目录(需保证 /data 分区 ≥200GB)

cd /data

\# 2. 初始化 repo 仓库(指定 5.0.3 稳定版本)

repo init -u https://gitee.com/openharmony/manifest -b refs/tags/OpenHarmony-v5.0.3-Release --no-repo-verify

\# 3. 同步源码(-c 仅同步当前分支,节省流量)

repo sync -c

\# 4. 拉取 LFS 大文件(如预编译工具、固件)

repo forall -c 'git lfs pull'

注意事项:源码同步过程可能因网络中断失败,可重复执行 repo sync -c 继续同步,直至无报错。

4.2 编译配置修正(关键步骤,解决 Docker 依赖冲突)
4.2.1 Node.js 版本适配

编译脚本依赖特定 Node.js 版本(16.20.2),需修改 build.sh 确保版本匹配:

代码语言:javascript
复制
vi build.sh

\# 将 EXPECTED\_NODE\_VERSION 改为 16.20.2

EXPECTED\_NODE\_VERSION="16.20.2"

原因:Node.js 版本过高(如 18+)会导致 ETS 编译器(ace_ets2bundle)依赖解析失败,16.20.2 为官方验证的稳定版本。

4.2.2 npm 依赖配置与安装
代码语言:javascript
复制
\# 1. 配置 npm 国内源与依赖解析策略

npm config set -g registry https://repo.huaweicloud.com/repository/npm  # 华为云源加速

npm config set -g legacy-peer-deps=true  # 启用旧版 peer 依赖解析(避免依赖冲突)

\# 2. 编写 npm 依赖安装脚本(批量处理核心模块)

cat > npm-install.sh

dirs=("developtools/ace\_ets2bundle/compiler" "developtools/ace\_js2bundle/ace-loader" "third\_party/jsframework" "third\_party/parse5/packages/parse5" "third\_party/weex-loader" "arkcompiler/ets\_frontend/legacy\_bin/api8" "interface/sdk-js/build-tools" "arkcompiler/ets\_frontend/arkguard")

for dir in "\${dirs\[@]}"; do

        echo -e "run npm install in /data/\${dir}"

        cd "/data/\${dir}"

        \# 指定 Node.js 路径、缓存目录与依赖源

        /data/prebuilts/build-tools/common/nodejs/current/bin/npm install --registry https://repo.huaweicloud.com/repository/npm/ --cache \~/.npm/\_cacache/compiler --unsafe-perm --legacy-peer-deps

        echo -e "run finished in /data/\${dir}"

done

\# 执行脚本(赋予权限后)

chmod +x npm-install.sh && ./npm-install.sh

核心模块说明ace_ets2bundle 是 ETS 语言编译器,jsframework 是 OpenHarmony JS 应用框架,这些模块的 npm 依赖未包含在源码中,需手动安装。

4.2.3 SELinux 与 SDK 版本配置
  1. SELinux 策略目录指定:SELinux 是强制访问控制机制,Docker 安全依赖 SELinux 策略,需指定产品级策略目录:
代码语言:javascript
复制
vi base/security/selinux\_adapter/selinux.gni

\# 添加以下内容(指定 OHOS\_PRODUCT\_DIR 为产品策略目录)

OHOS\_PRODUCT\_DIR = "base/security/selinux\_adapter/sepolicy/ohos\_product"
  1. 统一 compileSdkVersion:applications 目录下的应用需统一 SDK 版本为 15,避免编译时版本不一致:
代码语言:javascript
复制
\# 查找并替换所有 .json5 文件中的 compileSdkVersion

find applications -type f -name "\*.json5"|xargs grep '"compileSdkVersion": '

\# 手动将结果中的版本改为 15(如 "compileSdkVersion": 15)
4.2.4 编译错误修复(针对 5.0.3 已知问题)

OpenHarmony 5.0.3 源码存在部分编译错误,需修改以下文件:

  1. foundation/arkui/napi/jsvm/``build_jsvm_inter.sh:修复 ASAN 与 HWASAN 同时启用的逻辑冲突:
代码语言:javascript
复制
vi foundation/arkui/napi/jsvm/build\_jsvm\_inter.sh

\# 修正条件判断:if \[\[ "\${IS\_ASAN}" = "true" && "\${USE\_HWASAN}" = "true" ]]
  1. foundation/window/window_manager/window_scene/session_manager/src/scene_session_manager.cpp:修复日志格式中的类型不匹配(%{public}u 需对应 unsigned int):
代码语言:javascript
复制
vi foundation/window/window\_manager/window\_scene/session\_manager/src/scene\_session\_manager.cpp

\# 修正 TLOGI 日志:

TLOGI(WmsLogTag::WMS\_PATTERN, "type: %{public}s, capacity: %{public}u", systemConfig\_.uiType\_.c\_str(), (unsigned int)snapshotCapacity\_)
  1. 其他关键修复(如 Python 脚本类型转换、变量初始化):
  • arkcompiler/ets_runtime/script/``run_ark_executable.pytimeout_limit = int(args.timeout_limit) if args.timeout_limit else 3600(确保类型为 int)
  • base/security/security_component_manager/frameworks/enhance_adapter/src/sec_comp_enhance_adapter.cppvoid* handler = nullptr;(初始化指针,避免野指针)

五、Docker 环境适配:内核配置与补丁应用

Docker 运行依赖内核特性(如 cgroup、namespace、overlay2)与硬件适配,需通过补丁与内核配置实现。

5.1 硬件适配补丁(PurplePiOH 开发板)
代码语言:javascript
复制
\# 1. 下载 PurplePiOH 补丁包

wget 'https://PurplePiOH_HOST/IDO\_PurplePiOH\_V1A\_OHOS5.0r\_Patch\_241017.zip' -O IDO\_PurplePiOH\_V1A\_OHOS5.0r\_Patch\_241017.zip

unzip IDO\_PurplePiOH\_V1A\_OHOS5.0r\_Patch\_241017.zip

cd IDO\_PurplePiOH\_V1A\_OHOS5.0r\_Patch\_241017

\# 2. 更新 Uboot(引导程序,适配 PurplePiOH 硬件)

wget 'https://PurplePiOH_HOST/Uboot.zip' -O Uboot.zip

unzip Uboot.zip

cp -f Uboot/uboot.img ido\_device/board/industio/purple\_pi\_oh/loader/uboot.img  # 替换 Uboot 镜像

\# 3. 修正安全配置(添加核心服务为关键进程,Docker 依赖系统服务稳定)

vi ido\_vendor/industio/purple\_pi\_oh/security\_config/critical\_reboot\_process\_list.json

\# 添加以下内容(accesstoken\_service 与 privacy\_service 为权限管理核心服务):

{ 

   "name" : "accesstoken\_service",

   "critical" : \[1, 4, 240]

},

{ 

    "name" : "privacy\_service",

    "critical" : \[1, 4, 240]

}

\# 4. 删除兼容问题配置(init\_feature\_loader 与 5.0.3 版本不兼容)

vi ido\_vendor/industio/purple\_pi\_oh/config.json

\# 删除 init\_feature\_loader 相关配置项

\# 5. 修正 Sanitizer 检查(绕过 Docker 无关模块的检查,避免编译失败)

vi ido\_vendor/industio/purple\_pi\_oh/security\_config/sanitizer\_check\_list.gni

\# 修改以下项:

bypass\_graphic\_2d libnative\_color\_space\_manager

bypass\_dlp\_permission\_service ohdlp\_permission

bypass\_hiview hiview\_param\_update\_for\_tdd hiviewplatform\_config\_for\_tdd

\# 6. 应用补丁(将硬件适配与配置修改合并到源码)

./ido\_patch.sh
5.2 内核 Docker 特性配置(核心步骤)

需为 Linux 5.10 内核添加 Docker 必需的特性,通过 audit-defconfig 合并配置。

5.2.1 创建 Docker 内核配置文件
代码语言:javascript
复制
cd kernel/linux

\# 1. 查找当前 defconfig(PurplePiOH 硬件配置)

find . -type f -name "\*defconfig"  # 全局查找 defconfig

find ../../device/board/industio/purple\_pi\_oh/kernel/ido\_patchs -type f -name "\*defconfig"  # 查找板级 defconfig

\# 2. 创建 audit-defconfig(Docker 必需内核特性)

cat > audit-defconfig

\# 添加以下配置(关键特性解析见下文):

CONFIG\_ACCESS\_TOKENID=y

CONFIG\_ANDROID\_PARANOID\_NETWORK=y

CONFIG\_AUFS\_FS=y

CONFIG\_BINFMT\_MISC=y

CONFIG\_BLK\_CGROUP=y

CONFIG\_BLK\_DEV\_THROTTLING=y

CONFIG\_BPF\_SYSCALL=y

CONFIG\_BRIDGE\_NETFILTER=y

CONFIG\_BRIDGE\_VLAN\_FILTERING=y

CONFIG\_BRIDGE=y

CONFIG\_BTRFS\_FS\_POSIX\_ACL=y

CONFIG\_BTRFS\_FS=y

CONFIG\_CGROUP\_BPF=y

CONFIG\_CGROUP\_HUGETLB=y

CONFIG\_CGROUP\_NET\_PRIO=y

CONFIG\_CGROUP\_PERF=y

CONFIG\_CGROUP\_PIDS=y

CONFIG\_CRYPTO\_SEQIV=y

CONFIG\_DRIVERS\_HDF\_LIGHT=y

CONFIG\_DRM\_DW\_HDMI\_I2S\_AUDIO=y

CONFIG\_DUMMY=y

CONFIG\_F2FS\_GRADING\_SSR=y

CONFIG\_HUGETLBFS=y

CONFIG\_HUGETLB\_PAGE=y

CONFIG\_HYPERHOLD\_DEBUG=y

CONFIG\_HYPERHOLD\_FILE\_LRU=y

CONFIG\_HYPERHOLD\_MEMCG=y

CONFIG\_HYPERHOLD=y

CONFIG\_HYPERHOLD\_ZSWAPD=y

CONFIG\_INET\_ESP=y

CONFIG\_IP\_MROUTE\_MULTIPLE\_TABLES=y

CONFIG\_IP\_MULTIPLE\_TABLES=y

CONFIG\_IP\_NF\_CONNTRACK=y

CONFIG\_IP\_NF\_FILTER=y

CONFIG\_IP\_NF\_FTP=y

CONFIG\_IP\_NF\_IRC=y

CONFIG\_IP\_NF\_MATCH\_LIMIT=y

CONFIG\_IP\_NF\_MATCH\_STATE=y

CONFIG\_IP\_NF\_NAT=y

CONFIG\_IP\_NF\_TARGET\_LOG=y

CONFIG\_IP\_NF\_TARGET\_MASQUERADE=y

CONFIG\_IP\_NF\_TARGET\_REDIRECT=y

CONFIG\_IP\_SET\_HASH\_IP=y

CONFIG\_IP\_SET\_HASH\_NET=y

CONFIG\_IP\_SET=y

CONFIG\_IPV6\_MIP6=y

CONFIG\_IPV6\_MROUTE\_MULTIPLE\_TABLES=y

CONFIG\_IPV6\_MROUTE=y

CONFIG\_IPV6\_MULTIPLE\_TABLES=y

CONFIG\_IPVLAN=y

CONFIG\_IP\_VS\_NFCT=y

CONFIG\_IP\_VS\_PROTO\_TCP=y

CONFIG\_IP\_VS\_PROTO\_UDP=y

CONFIG\_IP\_VS\_RR=y

CONFIG\_IP\_VS\_SH=y

CONFIG\_IP\_VS\_WRR=y

CONFIG\_IP\_VS=y

CONFIG\_MACVLAN=y

CONFIG\_MEMCG\_KMEM=y

CONFIG\_MEMCG\_SWAP\_ENABLED=y

CONFIG\_NET\_CLS\_CGROUP=y

CONFIG\_NETFILTER\_XT\_MARK=y

CONFIG\_NETFILTER\_XT\_MATCH\_ADDRTYPE=y

CONFIG\_NETFILTER\_XT\_MATCH\_CGROUP=y

CONFIG\_NETFILTER\_XT\_MATCH\_CONNTRACK=y

CONFIG\_NETFILTER\_XT\_MATCH\_IPVS=y

CONFIG\_NETFILTER\_XT\_SET=y

CONFIG\_NETFILTER\_XT\_TARGET\_CHECKSUM=y

CONFIG\_NF\_CONNTRACK\_FTP=y

CONFIG\_NF\_CONNTRACK\_TFTP=y

CONFIG\_NF\_CONNTRACK=y

CONFIG\_NF\_NAT\_FTP=y

CONFIG\_NF\_NAT\_TFTP=y

CONFIG\_NF\_NAT=y

CONFIG\_OVERLAY\_FS=y

CONFIG\_PAGE\_COUNTER=y

CONFIG\_POSIX\_MQUEUE=y

CONFIG\_PSI=y

CONFIG\_REGMAP\_SPI=y

CONFIG\_RT\_GROUP\_SCHED=y

CONFIG\_SCHED\_WALT=y

CONFIG\_SND\_DMAENGINE\_PCM=y

CONFIG\_SND\_DRIVERS=y

CONFIG\_SND\_DYNAMIC\_MINORS=y

CONFIG\_SND\_HDA\_PREALLOC\_SIZE=64

CONFIG\_SND\_HRTIMER=y

CONFIG\_SND\_HWDEP=y

CONFIG\_SND\_JACK\_INPUT\_DEV=y

CONFIG\_SND\_JACK=y

CONFIG\_SND\_MAX\_CARDS=32

CONFIG\_SND\_PCM\_ELD=y

CONFIG\_SND\_PCM\_IEC958=y

CONFIG\_SND\_PCM\_TIMER=y

CONFIG\_SND\_PCM=y

CONFIG\_SND\_PROC\_FS=y

CONFIG\_SND\_RAWMIDI=y

CONFIG\_SND\_SEQ\_DEVICE=y

CONFIG\_SND\_SEQ\_DUMMY=y

CONFIG\_SND\_SEQ\_HRTIMER\_DEFAULT=y

CONFIG\_SND\_SEQ\_MIDI\_EVENT=y

CONFIG\_SND\_SEQ\_MIDI=y

CONFIG\_SND\_SEQUENCER=y

CONFIG\_SND\_SIMPLE\_CARD\_UTILS=y

CONFIG\_SND\_SIMPLE\_CARD=y

CONFIG\_SND\_SOC\_DUMMY\_CODEC=y

CONFIG\_SND\_SOC\_ES7202=y

CONFIG\_SND\_SOC\_ES7243E=y

CONFIG\_SND\_SOC\_ES8311=y

CONFIG\_SND\_SOC\_ES8316=y

CONFIG\_SND\_SOC\_GENERIC\_DMAENGINE\_PCM=y

CONFIG\_SND\_SOC\_HDMI\_CODEC=y

CONFIG\_SND\_SOC\_MAX98090=y

CONFIG\_SND\_SOC\_RK3308=y

CONFIG\_SND\_SOC\_RK3328=y

CONFIG\_SND\_SOC\_RK817=y

CONFIG\_SND\_SOC\_RK\_CODEC\_DIGITAL=y

CONFIG\_SND\_SOC\_RL6231=y

CONFIG\_SND\_SOC\_ROCKCHIP\_HDMI=y

CONFIG\_SND\_SOC\_ROCKCHIP\_I2S\_TDM=y

CONFIG\_SND\_SOC\_ROCKCHIP\_I2S=y

CONFIG\_SND\_SOC\_ROCKCHIP\_MAX98090=y

CONFIG\_SND\_SOC\_ROCKCHIP\_MULTICODECS=y

CONFIG\_SND\_SOC\_ROCKCHIP\_PDM=y

CONFIG\_SND\_SOC\_ROCKCHIP\_RT5645=y

CONFIG\_SND\_SOC\_ROCKCHIP\_SPDIFRX=y

CONFIG\_SND\_SOC\_ROCKCHIP\_SPDIF=y

CONFIG\_SND\_SOC\_ROCKCHIP=y

CONFIG\_SND\_SOC\_RT5616=y

CONFIG\_SND\_SOC\_RT5640=y

CONFIG\_SND\_SOC\_RT5645=y

CONFIG\_SND\_SOC\_RT5651=y

CONFIG\_SND\_SOC\_SPDIF=y

CONFIG\_SND\_SOC\_TS3A227E=y

CONFIG\_SND\_SOC=y

CONFIG\_SND\_TIMER=y

CONFIG\_SND\_USB\_AUDIO\_USE\_MEDIA\_CONTROLLER=y

CONFIG\_SND\_USB\_AUDIO=y

CONFIG\_SND\_USB=y

CONFIG\_SND\_VERBOSE\_PROCFS=y

CONFIG\_STREAM\_PARSER=y

CONFIG\_TLS=y

CONFIG\_VETH=y

CONFIG\_VXLAN=y

CONFIG\_ZLIST\_DEBUG=y

CONFIG\_ZRAM\_GROUP\_DEBUG=y

CONFIG\_ZRAM\_GROUP\_WRITEBACK=y

CONFIG\_ZRAM\_GROUP=y
关键内核特性解析

特性类别

关键配置项

作用说明

容器资源控制

CONFIG_CGROUP_*

cgroup 子系统(cpu、memory、pids 等),Docker 基于此实现容器资源限制

网络虚拟化

CONFIG_BRIDGE、CONFIG_VETH、CONFIG_IPVLAN

桥接网络、虚拟网卡、IP 虚拟化,支撑 Docker 桥接 /host 等网络模式

存储驱动

CONFIG_OVERLAY_FS、CONFIG_AUFS_FS

Overlay2/AUFS 是 Docker 主流存储驱动,实现镜像分层存储

BPF 支持

CONFIG_BPF_SYSCALL

Docker 网络策略(如端口映射)、安全审计依赖 BPF 机制

网络过滤

CONFIG_NETFILTER_、CONFIG_IP_NF_

网络地址转换(NAT)、连接跟踪(conntrack),实现容器访问外部网络

5.2.2 合并内核配置

编写脚本将 audit-defconfig 合并到板级 defconfig,避免手动修改冲突:

代码语言:javascript
复制
cat > audit-defconfig.sh

def\_config\_file\_path=\$1  # 传入板级 defconfig 路径(如 ../../device/xxx/defconfig)

tmp\_def\_config\_file\_path="/tmp/defconfig\_\`date -u +%s\`"  # 临时文件(避免覆盖原文件)

\# awk 命令逻辑:1. 读取 audit-defconfig 并存储 CONFIG\_ 项;2. 读取板级 defconfig,替换重复的 CONFIG\_ 项,保留其他项

awk -F '=' '{if(NR==FNR){if(/^CONFIG\_/){a\[\$1]=\$2;print \$0}}else{if(/^CONFIG\_/ && (\$1 in a)){}else{print \$0}}}' audit-defconfig \$def\_config\_file\_path > \$tmp\_def\_config\_file\_path

\# 备份原 defconfig 并替换

mv -f \$def\_config\_file\_path \$def\_config\_file\_path".bak"

mv -f \$tmp\_def\_config\_file\_path \$def\_config\_file\_path

\# 删除临时文件

rm -rf \$tmp\_def\_config\_file\_path

执行脚本合并配置:

代码语言:javascript
复制
chmod +x audit-defconfig.sh

./audit-defconfig.sh ../../device/board/industio/purple\_pi\_oh/kernel/ido\_patchs/xxx\_defconfig  # 替换为实际 defconfig 路径
5.2.3 镜像构建配置(添加 Docker 必需目录)

修改镜像构建脚本,确保生成的根文件系统包含 Docker 运行所需目录:

代码语言:javascript
复制
vi build/ohos/images/build\_image.py

\# 在 \_dir\_list 中添加以下目录(Docker 运行依赖):

'run', 'var', 'opt', 'usr'

修改 SELinux 上下文,允许 Docker 访问这些目录:

代码语言:javascript
复制
vi base/security/selinux/sepolicy/base/system/file\_contexts

\# 添加以下内容(设置目录安全上下文为 rootfs:s0,避免 SELinux 拦截):

/run                u:object\_r:rootfs:s0

/var                u:object\_r:rootfs:s0

/opt                u:object\_r:rootfs:s0

/usr                u:object\_r:rootfs:s0

/lib                u:object\_r:rootfs:s0

六、镜像编译与烧录:生成可运行 Docker 的系统镜像

基于上述配置,编译 PurplePiOH 专属镜像,并通过瑞芯微工具烧录到硬件。

6.1 镜像编译(全量 / 增量构建)
代码语言:javascript
复制
\# 1. 全量构建(首次编译,从 0 开始,耗时较长)

./build.sh --product-name purple\_pi\_oh --ccache --target-cpu arm64 --gn-args allow\_sanitize\_debug=false --ninja-args=-v

\# 2. 增量构建(修改代码后,仅编译变更部分,加速调试)

./build.sh --product-name purple\_pi\_oh --fast-rebuild --target-cpu arm64 --gn-args allow\_sanitize\_debug=false --ninja-args=-v
编译参数解析

参数

作用说明

–product-name

指定产品名称(purple_pi_oh,对应板级配置)

–ccache

启用编译缓存,重复编译时复用中间文件,节省时间

–target-cpu arm64

指定目标架构为 ARM64(PurplePiOH 基于 RK3566,ARM64 架构)

–gn-args allow_sanitize_debug=false

关闭 Sanitize 调试(减少镜像大小,提高性能)

–ninja-args=-v

显示详细编译日志,便于排查编译错误

6.2 编译产物说明

编译成功后,镜像文件生成于 /out/purple_pi_oh/packages/phone/images,核心文件如下:

镜像文件

作用说明

uboot.img

Uboot 引导程序,初始化硬件并加载内核

MiniLoaderAll.bin

Loader 程序,瑞芯微芯片烧录时的初始化程序

system.img

系统分区镜像,包含 OpenHarmony 核心系统组件

vendor.img

厂商分区镜像,包含 PurplePiOH 硬件驱动与配置

userdata.img

用户数据分区镜像,可读写,用于存储 Docker 镜像与容器数据

parameter.txt

分区表配置,定义各镜像的烧录地址与大小

config.cfg

瑞芯微烧录工具配置文件,自动关联镜像与烧录地址

6.3 镜像烧录(瑞芯微开发工具)
  1. 工具准备:安装瑞芯微开发工具(v2.84+),将硬件设置为 MASKROM 模式(硬件复位时按住烧录键,接入电脑)。
  2. 导入配置:打开工具,右键选择 “导入配置”,选择 /out/purple_pi_oh/packages/phone/images/config.cfg,自动加载各镜像的烧录地址。
  3. 确认镜像路径:检查工具中各镜像(如 Loader、Uboot、System)的路径是否正确,若有误手动选择 /out/purple_pi_oh/packages/phone/images 下的对应文件。
  4. 执行烧录:点击 “执行”,等待烧录完成(进度 100% 且无报错),烧录成功后设备自动重启。

七、系统级 Docker 环境初始化:启动并验证 Docker 服务

设备启动后,通过 HDC 工具连接设备,完成 Docker 运行环境的最终配置。

7.1 设备连接与权限获取
代码语言:javascript
复制
\# 1. 挂载设备分区(获取读写权限)

hdc target mount

\# 2. 进入超级用户模式(root 权限,执行后续操作)

hdc smode

说明:HDC(HarmonyOS Device Connector)是 OpenHarmony 官方设备调试工具,支持设备连接、文件传输与命令执行。

7.2 cgroup 配置(容器资源控制基础)

创建 cgroups.json 配置文件,定义 cgroup 子系统的挂载规则:

代码语言:javascript
复制
\# 在 /etc/ 目录下创建 cgroups.json

vi /etc/cgroups.json

\# 添加以下内容(JSON 格式,指定各 cgroup 子系统的挂载路径、权限与所有者):

{

  "Cgroups": \[

    {

      "UID": "system",

      "GID": "system",

      "Mode": "0755",

      "Controller": "blkio",

      "Path": "/dev/blkio"

    },

    {

      "UID": "system",

      "GID": "system",

      "Mode": "0755",

      "Controller": "cpu",

      "Path": "/dev/cpu"

    },

    {

      "Mode": "0555",

      "Path": "/dev/cpuacct",

      "Controller": "cpuacct"

    },

    {

      "UID": "system",

      "GID": "system",

      "Mode": "0755",

      "Controller": "cpuset",

      "Path": "/dev/cpuset"

    },

    {

      "UID": "system",

      "GID": "system",

      "Mode": "0755",

      "Controller": "memory",

      "Path": "/dev/memcg"

    },

    {

      "UID": "system",

      "GID": "system",

      "Mode": "0755",

      "Controller": "schedtune",

      "Path": "/dev/stune"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "devices",

      "Path": "/dev/devices"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "freezer",

      "Path": "/dev/freezer"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "hugetlb",

      "Path": "/dev/hugetlb"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "net\_cls",

      "Path": "/dev/net\_cls"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "net\_prio",

      "Path": "/dev/net\_prio"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "perf\_event",

      "Path": "/dev/perf\_event"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "pids",

      "Path": "/dev/pids"

    },

    {

      "GID": "system",

      "UID": "system",

      "Mode": "0755",

      "Controller": "rdma",

      "Path": "/dev/rdma"

    }

  ],

  "Cgroups2": {

    "UID": "root",

    "GID": "root",

    "Mode": "0600",

    "Path": "/dev/cg2\_bpf"

  }

}
7.3 Docker 静态二进制部署

嵌入式环境下,推荐使用静态二进制文件(无需依赖系统库)部署 Docker:

代码语言:javascript
复制
\# 1. 下载 Docker 18.03.1 静态二进制(ARM64 架构)

wget https://download.docker.com/linux/static/stable/aarch64/docker-18.03.1-ce.tgz -O docker.tgz

\# 2. 解压到 /system/bin/docker 目录(系统可执行路径)

tar zxvf docker.tgz -C /system/bin/

\# 3. 赋予执行权限(所有 Docker 二进制文件)

cd /system/bin/docker

chmod 777 docker docker-containerd-ctr docker-init docker-runc docker-containerd docker-containerd-shim docker-proxy dockerd
7.4 系统环境配置(解决嵌入式限制)

嵌入式设备的 /system 分区通常为只读,需通过绑定挂载将 Docker 依赖目录映射到可读写的 /data 分区:

代码语言:javascript
复制
\# 1. 开启 IP 转发(Docker 网络必需)

echo "1" > /proc/sys/net/ipv4/ip\_forward

\# 2. 创建可读写目录(/data 分区可写)

mkdir /system/etc/docker

mkdir /data/var /data/run /data/tmp /data/opt /data/etc /data/etc/docker /data/usr

\# 3. 绑定挂载(将只读目录映射到可写目录)

mount --bind /data/etc/docker /etc/docker

mount --bind /data/var /var

mount --bind /data/run /run

mount --bind /data/tmp /tmp

mount --bind /data/opt /opt

mount --bind /data/usr /usr

\# 4. 初始化 cgroup 挂载(tmpfs 内存文件系统,高效)

mount tmpfs /sys/fs/cgroup -t tmpfs -o size=1G

\# 创建各 cgroup 子系统目录并挂载

mkdir /sys/fs/cgroup/blkio /sys/fs/cgroup/cpu /sys/fs/cgroup/cpuacct /sys/fs/cgroup/cpuset /sys/fs/cgroup/devices /sys/fs/cgroup/freezer /sys/fs/cgroup/hugetlb /sys/fs/cgroup/memory /sys/fs/cgroup/net\_cls /sys/fs/cgroup/net\_prio /sys/fs/cgroup/perf\_event /sys/fs/cgroup/pids /sys/fs/cgroup/rdma /sys/fs/cgroup/schedtune /sys/fs/cgroup/systemd

\# 挂载各 cgroup 子系统

mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd

mount -t cgroup -o blkio,nodev,noexec,nosuid cgroup /sys/fs/cgroup/blkio

mount -t cgroup -o cpu,nodev,noexec,nosuid cgroup /sys/fs/cgroup/cpu

mount -t cgroup -o cpuacct,nodev,noexec,nosuid cgroup /sys/fs/cgroup/cpuacct

mount -t cgroup -o cpuset,nodev,noexec,nosuid cgroup /sys/fs/cgroup/cpuset

mount -t cgroup -o devices,nodev,noexec,nosuid cgroup /sys/fs/cgroup/devices

mount -t cgroup -o freezer,nodev,noexec,nosuid cgroup /sys/fs/cgroup/freezer

mount -t cgroup -o hugetlb,nodev,noexec,nosuid cgroup /sys/fs/cgroup/hugetlb

mount -t cgroup -o memory,nodev,noexec,nosuid cgroup /sys/fs/cgroup/memory

mount -t cgroup -o net\_cls,nodev,noexec,nosuid cgroup /sys/fs/cgroup/net\_cls

mount -t cgroup -o net\_prio,nodev,noexec,nosuid cgroup /sys/fs/cgroup/net\_prio

mount -t cgroup -o perf\_event,nodev,noexec,nosuid cgroup /sys/fs/cgroup/perf\_event

mount -t cgroup -o pids,nodev,noexec,nosuid cgroup /sys/fs/cgroup/pids

mount -t cgroup -o rdma,nodev,noexec,nosuid cgroup /sys/fs/cgroup/rdma

mount -t cgroup -o schedtune,nodev,noexec,nosuid cgroup /sys/fs/cgroup/schedtune

\# 5. 配置 Docker 守护进程(daemon.json)

echo "{\\"insecure-registries\\":\[\\"ghcr.io\\",\\"registry.cn-chengdu.aliyuncs.com\\",\\"registry.cn-beijing.aliyuncs.com\\"],\\"experimental\\":true,\\"storage-driver\\": \\"vfs\\"}" > /etc/docker/daemon.json

\# 说明:insecure-registries 配置国内镜像源;storage-driver: vfs 适配嵌入式(无 overlay2 支持时)

\# 6. 临时关闭 SELinux(避免拦截 Docker 操作,后续可配置策略)

setenforce 0
7.5 Docker 服务启动与验证
代码语言:javascript
复制
\# 1. 添加 Docker 路径到环境变量

export PATH=\$PATH:/system/bin/:/system/bin/docker/

\# 2. 启动 Docker 守护进程(后台运行)

rm -rf /var/run/docker.pid  # 删除残留进程 ID(避免启动失败)

nohup dockerd -D -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock >/dev/null 2>&1 &

\# 3. 验证 Docker 状态

docker info  # 查看 Docker 系统信息,无报错则启动成功

docker run --rm arm64v8/hello-world  # 运行 hello-world 容器(ARM64 版本),验证功能正常

八、总结与优化方向

本文通过 “环境准备→源码适配→内核配置→镜像编译→Docker 初始化” 五阶段流程,实现了 OpenHarmony 5.0.3 在 PurplePiOH 上的 Docker 环境支持,核心突破点包括:

  1. 解决了 Linux 5.10 内核 BTF 编译的内存不足问题(虚拟内存配置);
  2. 适配了 Docker 必需的内核特性(cgroup、overlay2、BPF 等);
  3. 解决了嵌入式只读分区限制(绑定挂载到 /data 可写分区);
  4. 修复了 OpenHarmony 5.0.3 源码的编译冲突(Node.js 版本、日志格式等)。
后续优化方向
  1. 存储驱动优化:替换 vfs 为 overlay2,提升 Docker 镜像读写性能(需确保内核与文件系统支持 overlay2);
  2. SELinux 策略持久化:编写 Docker 专属 SELinux 策略,替代临时关闭 setenforce 0,提升安全性;
  3. Docker 服务自启动:将 Docker 启动脚本加入 OpenHarmony 系统服务,实现开机自动启动;
  4. 资源限制优化:通过 cgroups.json 精细配置容器资源上限,避免单容器占用过多系统资源。

通过以上实践,OpenHarmony 可借助 Docker 容器技术扩展应用生态,为工业控制、边缘计算等场景提供更灵活的应用部署方案。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OpenHarmony 5.0.3 适配 Docker 环境的全流程技术实践与解析
    • 一、引言:OpenHarmony 容器化生态的技术价值
    • 二、环境前置准备:硬件规格与系统优化
      • 2.1 硬件最小规格定义
      • 2.2 系统级资源优化
    • 三、编译环境与工具链构建:基础依赖标准化
      • 3.1 系统环境选择
      • 3.2 工具链与依赖安装
    • 四、源码获取与配置调优:适配 Docker 编译需求
      • 4.1 源码拉取(基于 5.0.3 Release 版本)
      • 4.2 编译配置修正(关键步骤,解决 Docker 依赖冲突)
    • 五、Docker 环境适配:内核配置与补丁应用
      • 5.1 硬件适配补丁(PurplePiOH 开发板)
      • 5.2 内核 Docker 特性配置(核心步骤)
    • 六、镜像编译与烧录:生成可运行 Docker 的系统镜像
      • 6.1 镜像编译(全量 / 增量构建)
      • 6.2 编译产物说明
      • 6.3 镜像烧录(瑞芯微开发工具)
    • 七、系统级 Docker 环境初始化:启动并验证 Docker 服务
      • 7.1 设备连接与权限获取
      • 7.2 cgroup 配置(容器资源控制基础)
      • 7.3 Docker 静态二进制部署
      • 7.4 系统环境配置(解决嵌入式限制)
      • 7.5 Docker 服务启动与验证
    • 八、总结与优化方向
      • 后续优化方向
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档