基于Docker的ONIE编译环境搭建与常见问题解决指南

1. 简介

本教程介绍如何使用Docker容器快速搭建ONIE(Open Network Install Environment)编译环境。通过Docker,可以在隔离、可复现的环境中完成ONIE镜像的编译,避免主机环境污染和依赖冲突。


2. Docker环境准备

2.1 安装Docker

以Debian/Ubuntu为例:

sudo apt-get update
sudo apt-get install -y docker.io

2.2 配置用户权限(可选)

将当前用户加入docker组,避免每次都用sudo:

sudo adduser $USER docker

需重新登录或执行 su - $USER 使权限生效。


3. 构建ONIE编译环境镜像

假设你已在ONIE源码的contrib/build-env目录下,且有Dockerfile文件。

cd ~/src/onie/contrib/build-env
sudo docker build -t debian:build-env .

如需重新构建镜像(Dockerfile有变更):

docker stop onie
docker rm onie
sudo docker build -t debian:build-env .

4. 挂载主机目录(用于产物输出)

在主机上创建一个目录,供容器内build用户读写,建议权限为777:

mkdir --mode=0777 -p ${HOME}/src

该目录会在容器内映射为 /home/build/src


5. 启动并进入ONIE编译容器

sudo docker run -it -v ${HOME}/src:/home/build/src --name onie debian:build-env
  • -it:交互式终端
  • -v:挂载主机目录到容器
  • --name onie:容器命名为onie,便于后续管理

进入容器后,命令提示符类似:

build@xxxxxxx:~$

如意外断开,可用 docker attach onie 重新连接。


6. 容器内编译ONIE

6.1 克隆ONIE源码

容器内已提供clone-onie脚本,执行:

./clone-onie

源码会被克隆到 /home/build/src/onie

6.2 进入build-config目录

cd src/onie/build-config

6.3 编译ONIE镜像

以KVM平台为例:

make MACHINE=kvm_x86_64 all

以Accton平台为例:

make MACHINEROOT=../machine/accton MACHINE=accton_as7816_64x all

具体平台参数请参考ONIE源码的INSTALL文件或machine目录。


7. 获取编译产物

编译完成后,产物会出现在主机的 ${HOME}/src/onie/build/images 目录下。例如:

ls -l ${HOME}/src/onie/build/images

常见产物包括:

  • onie-recovery-*.iso 恢复镜像
  • onie-updater-* 升级器
  • *.vmlinuz 内核
  • *.initrd initrd

8. 常见注意事项与容器管理

  • .gitconfig:容器内默认的.gitconfig为虚拟用户信息,正式开发请自行修改为真实信息。
  • 用户/组ID:容器内build用户的UID/GID与主机不一致,建议挂载目录设为777,避免权限问题。
  • 容器管理
    • 断开后可用 docker attach onie 重新连接。
    • 停止容器:docker stop onie
    • 删除容器:docker rm onie
  • 镜像重建:如Dockerfile有变更,需先停止并删除旧容器,再重新build。

9. 参考


10. 常见问题与解决方法

10.1 依赖包缺失导致编译失败

  • 表现:编译中报错找不到如rsyncperlbcbisonflexlibssl-devlibelf-devautopointgettext等命令或库。
  • 解决方法
    在Dockerfile或容器内安装所有必需依赖:
    apt-get update && apt-get install -y \
      build-essential gcc g++ make autoconf automake bison flex \
      texinfo libtool libtool-bin gawk libncurses5-dev bc \
      dosfstools mtools pkg-config git wget help2man libexpat1-dev \
      fakeroot python3 python3-pip python3-dev python3-setuptools \
      libssl-dev libelf-dev libpopt-dev uuid-dev cpio unzip \
      bsdmainutils curl sudo rsync perl locales autopoint gettext procps
    

    特别注意:rsyncperlbcbisonflexlibssl-devlibelf-devautopointgettextmakegccg++ 必须有!

10.2 locale(en_US.UTF-8)缺失导致构建失败

  • 表现:日志出现 could not find a UTF8 locale ... please enable en_US.UTF-8,或locale相关报错。
  • 解决方法
    apt-get update && apt-get install -y locales
    echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
    locale-gen
    update-locale LANG=en_US.UTF-8
    export LANG=en_US.UTF-8
    export LANGUAGE=en_US:en
    export LC_ALL=en_US.UTF-8
    

    检查locale -a输出应包含en_US.utf8

10.3 工具链gcc未生成

  • 表现x86_64-onie-linux-uclibc-gcc等交叉编译器未生成,只有binutils工具。
  • 排查思路
    1. 查看build/x-tools/.../build.log,搜索errorfailgcc等关键字,找到gcc构建失败的具体原因。
    2. 检查依赖包是否齐全。
    3. 检查locale是否配置正确。
    4. 检查基础镜像兼容性。

10.4 基础镜像选择建议

  • ONIE官方推荐使用Debian 9(stretch)或Debian 10(buster)作为基础镜像,兼容性最佳。
  • Debian 11及以上可能因部分包名、工具链、locale等兼容性问题导致构建失败。
  • 如遇到莫名其妙的依赖或构建问题,建议先尝试回退基础镜像。

10.5 容器内root权限安装依赖

  • build用户无sudo密码时,可用root用户进入容器:
    sudo docker exec -it --user root onie /bin/bash
    # 安装依赖
    apt-get update && apt-get install -y rsync ...
    exit
    # 再用build用户进入
    sudo docker attach onie
    
  • 推荐所有依赖都在Dockerfile中一次性安装,避免手动操作。

10.6 git相关问题

  • 表现
    • fatal: detected dubious ownership in repository ...
    • Author identity unknown ... please tell me who you are.
  • 解决方法
    在容器内执行:
    git config --global --add safe.directory <出错目录>
    git config --global user.name "build"
    git config --global user.email "build@example.com"
    

    可批量信任所有目录:git config --global --add safe.directory '*'

10.7 busybox setuid root 提示

  • 表现
    • You will probably need to make your busybox binary setuid root to ensure all configured applets will work properly.
  • 说明
    这是busybox的常规提示,ONIE构建流程会自动处理,无需手动干预。

10.8 Secure Boot/GRUB/GPG签名相关报错

  • 表现
    • Can't load key from file ... ONIE-shim-key-secret-key.pemONIE-shim-key-cert.pem 不存在
    • gpg: no default secret key: No secret keygpg: signing failed: No secret key
  • 解决方法
    1. 关闭签名
      • 构建时加参数:
        make all SECURE_BOOT_ENABLE=no SECURE_GRUB=no GPG_SIGN_ENABLE=no
        
      • 或在Config.*/platform-config等文件中注释/删除ONIE_SIGN_KERNELCONFIG_SIGN_KERNELONIE_GPG_SIGN_KERNEL等变量。
    2. 如需签名,手动生成自签名密钥
      mkdir -p <key目录>
      openssl req -new -x509 -newkey rsa:2048 -keyout ONIE-shim-key-secret-key.pem -out ONIE-shim-key-cert.pem -days 3650 -nodes -subj "/CN=ONIE Test Shim Key/"
      
    3. 安装GPG依赖:如遇pgrep: not found,需apt-get install -y procps
    4. 说明:关闭签名不会影响普通BIOS/非Secure Boot环境下的启动,但在开启UEFI Secure Boot的设备上会导致无法启动。

10.9 多线程编译的风险与建议

  • 表现
    • 多线程编译时,错误信息容易被淹没,部分任务失败会导致"半成品"状态,后续编译易遇到git/stgit等二次报错。
  • 建议
    • 开发/调试阶段建议单线程编译(不加-j-j1)。
    • 自动化流水线可用多线程,但每次都make clean或用全新源码树。
    • 遇到异常中断,建议先make clean或手动清理相关目录。

10.10 stgit/git补丁管理相关清理建议

  • 表现
    • stg init: master: branch already initialized 或补丁应用失败
  • 解决方法
    • 执行make cleanmake kernel-cleanmake user-clean等目标,或手动删除相关源码目录(如build/kvm_x86_64-r0/kernel/linux-*build/user/.../grub)。
    • 保证每次补丁应用前源码树是"干净"的。

10.11 如何彻底刷新源码状态,解决源码"脏"或补丁无法应用问题

  • 场景:遇到grub等源码目录"脏"、补丁无法应用、stgit/git状态异常等问题时。

  • 推荐操作流程

    1. 备份download目录(防止重复下载大文件):
      cp -a /home/build/src/onie/build/download /home/build/src/onie/build/download.bak
      
    2. 清理download状态
      make download-clean
      
    3. 还原download文件
      cp -a /home/build/src/onie/build/download.bak/* /home/build/src/onie/build/download/
      
    4. 刷新download状态
      make download
      
    5. 删除有问题的源码目录(如grub):
      rm -rf /home/build/src/onie/build/user/x86_64-g8.3.0-lnx5.4.86-uClibc-ng-1.0.38/grub
      
    6. 重新make,此时会自动重新解包源码,彻底解决源码"脏"或补丁应用失败问题。
  • 说明

    • 只删除源码目录不够,必须配合download-clean和download,才能保证依赖链和stamp文件同步刷新。
    • 该方法适用于所有ONIE源码包(如grub、kernel等)。

10.12 关于Debian 11环境的说明

  • 背景
    • 原版Debian 9官方源apt update经常报错,导致依赖无法安装。
    • 所以使用Debian 11(bullseye)作为基础镜像,并使用国内镜像源(如清华/中科大)。
  • Debian 11下的注意事项
    • 需补充autopointgettextprocps等依赖包。
    • 某些老旧ONIE/crosstool-ng源码可能与新系统有兼容性问题,遇到依赖缺失、包名变化、locale等问题请参考本节其他小节的解决办法。
    • Dockerfile示例:
      FROM debian:11
      RUN echo "deb http://mirrors.ustc.edu.cn/debian/ bullseye main contrib non-free" > /etc/apt/sources.list && \
          echo "deb http://mirrors.ustc.edu.cn/debian/ bullseye-updates main contrib non-free" >> /etc/apt/sources.list && \
          echo "deb http://mirrors.ustc.edu.cn/debian/ bullseye-backports main contrib non-free" >> /etc/apt/sources.list && \
          echo "deb http://mirrors.ustc.edu.cn/debian-security bullseye-security main contrib non-free" >> /etc/apt/sources.list
      # 其余依赖安装同10.1
      

10.13 其他典型问题与最终有效解决办法总结

  • stgit补丁栈与HEAD不同步
    • 彻底删除源码目录+配合download-clean/download刷新,保证源码和补丁链一致。
  • stgit uninit命令不存在
    • 直接rm -rf .git/patches,再stg init
  • 多线程编译导致补丁/源码状态混乱
    • 开发调试建议单线程编译,遇到异常优先make clean或彻底清理相关目录。
  • Debian 9源不可用
    • 推荐Debian 11+国内镜像源,所有依赖和脚本均已适配。
  • 源码包/补丁反复失败
    • 按10.11流程彻底刷新源码和download状态。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐