OpenHarmony 作为面向全场景的分布式操作系统,其嵌入式与工业级应用场景对应用隔离、环境一致性与资源可控性提出了更高需求。Docker 作为轻量级容器技术,可通过内核级虚拟化实现应用与宿主环境的解耦,为 OpenHarmony 扩展复杂应用生态(如边缘计算、工业控制组件)提供关键支撑。
本文基于 OpenHarmony 5.0.3 版本,以 PurplePiOH 开发板(瑞芯微 RK3566 架构)为硬件载体,从环境构建→源码适配→内核配置→镜像编译→Docker 初始化全流程,拆解嵌入式场景下 OpenHarmony 支持 Docker 的技术细节,为开发者提供可复用的工程化方案。
Docker 运行依赖内核特性与充足资源,需先完成硬件配置与系统参数调优,避免编译失败或容器启动异常。
OpenHarmony 5.0.3 编译与 Docker 运行需满足以下硬件阈值,核心瓶颈在于磁盘空间(源码 + 中间文件 + 镜像)与内存(内核 BTF 编译需求):
硬件组件 | 规格要求 | 技术说明 |
|---|---|---|
存储(HD) | ≥250GB | 含源码(约 50GB)、编译中间文件(约 100GB)、最终镜像(约 20GB)及预留空间 |
CPU | 4C(x86-64) | 多核心可并行加速编译,推荐 8C 以上缩短耗时 |
内存(Mem) | ≥4GB | 需配合虚拟内存满足 Linux 5.10 内核 BTF 编译的 10GB 内存需求 |
Linux 系统默认预留 5% 磁盘空间用于 root 紧急修复,编译场景下可通过 tune2fs 调整为 1%,释放存储空间:
tune2fs -m 1 /dev/vda # /dev/vda 为系统根分区,需根据实际分区调整技术原理:tune2fs 是 ext 系列文件系统工具,-m 1 表示将预留空间比例设为 1%,避免默认 5% 预留导致的存储空间浪费(250GB 磁盘可多释放约 10GB)。
编译 Linux 5.10 内核 BTF(BPF Type Format,用于 BPF 程序类型信息解析)需至少 10GB 内存,4GB 物理内存需补充 8GB 虚拟内存:
\# 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 版本,兼容性最优)完成标准化部署。
推荐使用 Ubuntu 22.04 LTS,原因如下:
通过 apt 与手动部署结合,完成编译工具、交叉编译链、版本控制工具等核心依赖的安装:
\# 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),用于生成镜像分区 |
OpenHarmony 源码需通过 repo 拉取,并针对 Docker 依赖进行配置修正,解决编译冲突与版本兼容问题。
\# 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 继续同步,直至无报错。
编译脚本依赖特定 Node.js 版本(16.20.2),需修改 build.sh 确保版本匹配:
vi build.sh
\# 将 EXPECTED\_NODE\_VERSION 改为 16.20.2
EXPECTED\_NODE\_VERSION="16.20.2"原因:Node.js 版本过高(如 18+)会导致 ETS 编译器(ace_ets2bundle)依赖解析失败,16.20.2 为官方验证的稳定版本。
\# 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 依赖未包含在源码中,需手动安装。
vi base/security/selinux\_adapter/selinux.gni
\# 添加以下内容(指定 OHOS\_PRODUCT\_DIR 为产品策略目录)
OHOS\_PRODUCT\_DIR = "base/security/selinux\_adapter/sepolicy/ohos\_product"\# 查找并替换所有 .json5 文件中的 compileSdkVersion
find applications -type f -name "\*.json5"|xargs grep '"compileSdkVersion": '
\# 手动将结果中的版本改为 15(如 "compileSdkVersion": 15)OpenHarmony 5.0.3 源码存在部分编译错误,需修改以下文件:
foundation/arkui/napi/jsvm/``build_jsvm_inter.sh:修复 ASAN 与 HWASAN 同时启用的逻辑冲突:vi foundation/arkui/napi/jsvm/build\_jsvm\_inter.sh
\# 修正条件判断:if \[\[ "\${IS\_ASAN}" = "true" && "\${USE\_HWASAN}" = "true" ]]foundation/window/window_manager/window_scene/session_manager/src/scene_session_manager.cpp:修复日志格式中的类型不匹配(%{public}u 需对应 unsigned int):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\_)arkcompiler/ets_runtime/script/``run_ark_executable.py:timeout_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.cpp:void* handler = nullptr;(初始化指针,避免野指针)
Docker 运行依赖内核特性(如 cgroup、namespace、overlay2)与硬件适配,需通过补丁与内核配置实现。
\# 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需为 Linux 5.10 内核添加 Docker 必需的特性,通过 audit-defconfig 合并配置。
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),实现容器访问外部网络 |
编写脚本将 audit-defconfig 合并到板级 defconfig,避免手动修改冲突:
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执行脚本合并配置:
chmod +x audit-defconfig.sh
./audit-defconfig.sh ../../device/board/industio/purple\_pi\_oh/kernel/ido\_patchs/xxx\_defconfig # 替换为实际 defconfig 路径修改镜像构建脚本,确保生成的根文件系统包含 Docker 运行所需目录:
vi build/ohos/images/build\_image.py
\# 在 \_dir\_list 中添加以下目录(Docker 运行依赖):
'run', 'var', 'opt', 'usr'修改 SELinux 上下文,允许 Docker 访问这些目录:
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基于上述配置,编译 PurplePiOH 专属镜像,并通过瑞芯微工具烧录到硬件。
\# 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 | 显示详细编译日志,便于排查编译错误 |
编译成功后,镜像文件生成于 /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 | 瑞芯微烧录工具配置文件,自动关联镜像与烧录地址 |
/out/purple_pi_oh/packages/phone/images/config.cfg,自动加载各镜像的烧录地址。
/out/purple_pi_oh/packages/phone/images 下的对应文件。
设备启动后,通过 HDC 工具连接设备,完成 Docker 运行环境的最终配置。
\# 1. 挂载设备分区(获取读写权限)
hdc target mount
\# 2. 进入超级用户模式(root 权限,执行后续操作)
hdc smode说明:HDC(HarmonyOS Device Connector)是 OpenHarmony 官方设备调试工具,支持设备连接、文件传输与命令执行。
创建 cgroups.json 配置文件,定义 cgroup 子系统的挂载规则:
\# 在 /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"
  }
}嵌入式环境下,推荐使用静态二进制文件(无需依赖系统库)部署 Docker:
\# 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嵌入式设备的 /system 分区通常为只读,需通过绑定挂载将 Docker 依赖目录映射到可读写的 /data 分区:
\# 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\# 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 环境支持,核心突破点包括:
通过以上实践,OpenHarmony 可借助 Docker 容器技术扩展应用生态,为工业控制、边缘计算等场景提供更灵活的应用部署方案。