1. Docker 相关
1.1. Docker 支持
Firefly 发布的普通固件一般不满足 Docker 的运行要求,如果有需求,可以使用 SDK 打开内核的相关配置,重新编译烧录内核以支持 Docker。
以下案例是基于 Firefly Ubuntu 20.04,内核配置部分是通用的!
1.1.1. 检查 Kernel 配置
首先需要通过工具检查当前设备的内核缺少了哪些 Docker 需要的配置。
获取到脚本之后,开始进行检测:
#将脚本拷贝到SDK的kernel目录下
cp check-config.sh PathToSDK/kernel/
cd PathToSDK/kernel
chmod +x check-config.sh
#获取当前内核配置
make ARCH=arm64 firefly_linux_defconfig
#检测
./check-config.sh .config
执行后的结果如下,主要是两部分:
Generally Necessary:
- cgroup hierarchy: properly mounted [/sys/fs/cgroup]
- apparmor: enabled and tools installed
- CONFIG_NAMESPACES: enabled
- CONFIG_NET_NS: enabled
- CONFIG_PID_NS: enabled
- CONFIG_IPC_NS: enabled
- CONFIG_UTS_NS: enabled
- CONFIG_CGROUPS: enabled
......
Optional Features:
- CONFIG_USER_NS: enabled
- CONFIG_SECCOMP: enabled
- CONFIG_SECCOMP_FILTER: enabled
- CONFIG_CGROUP_PIDS: enabled
- CONFIG_MEMCG_SWAP: enabled
......
Generally Necessary: 表示必要的配置,如果有显示 missing 的地方,就需要在内核配置中打开它。 Optional Features: 是可选配置,根据需要打开。
1.1.2. 开启需要的配置
从上面的检测结果中得知需要打开哪些配置后,即可使用<span class="pre">make <span class="pre">ARCH=arm64 <span class="pre">menuconfig</span></span></span>
进入菜单,搜索对应项目将其打开。请认真查看菜单中的操作说明,遇到不可选中的项目请注意依赖关系。
开启所有必要配置以及部分可选配置后,注意保存:
make ARCH=arm64 savedefconfig
mv defconfig arch/arm64/configs/firefly_linux_defconfig
之后进行编译内核:
cd ..
./build.sh kernel
1.1.3. 安装 Docker
烧录完新内核之后,可以开始在设备上安装 Docker 并验证:
#这里仅介绍直接使用脚本快速安装
apt-get update
wget -qO- https:
等待安装成功之后应该会看见 Docker 版本信息,然后运行 demo:
root@firefly:~# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
93288797bd35: Pull complete
Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm64v8)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https:
For more examples and ideas, visit:
https:
1.2. 使用 Docker 搭建分布式编译环境
<span class="pre">distcc</span>
是个通过网络上的若干台机器用来分布式编译 C、C++、Objective-C 或 Objective-C++ 代码的程序。<span class="pre">distcc</span>
不要求所有的机器共享文件系统,有同步的时钟,或者安装有同样的库和头文件,只要作为服务器的机器有合适的编译工具即可进行编译。本例在两个 Firefly-RK3399 板卡 (arm64) 和一台 PC 机 (x86_64) 上利用 Docker 威廉希尔官方网站
来布署 <span class="pre">distcc</span>
分布式编译服务,进而实现在其中一个 Firefly-RK3399 板卡上利用 <span class="pre">distcc</span>
的分布式编译特性来加速内核的编译过程。
1.2.1. 准备工作
两个 Firefly-RK3399 板卡
路由器、网线
PC 机
将两块设备和 PC 机都连接到同一个局域网内。连接好后对应的 IP 地址别是:
PC 机:192.168.1.100
设备 A:192.168.1.101
设备 B:192.168.1.102
1.2.2. PC 机部署 Docker
使用脚本安装 Docker:
wget -qO- https://get.docker.com/ | sh
为了可以使当前普通用户可以执行 docker 相关命令,需要将当前用户添加到 dokcer 用户组中:
sudo groupadd docker
sudo gpasswd -a $USER docker
newgrp docker
启动 Docker 后台服务:
sudo service docker start
新建一个 <span class="pre">Dockerfile_distcc.x86_64</span>
文件。其文件内容如下:
FROM ubuntu:bionic
MAINTAINER Firefly <service@t-firefly.com>
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests\
gcc-aarch64-linux-gnu distcc\
&& apt-get clean \
&& rm -rf /var/lib/apt/lists
RUN ln -s aarch64-linux-gnu-gcc /usr/bin/gcc &&\
ln -s aarch64-linux-gnu-gcc /usr/bin/cc
EXPOSE 3632
ENTRYPOINT ["/usr/bin/distccd"]
CMD ["--no-detach" , "--log-stderr" , "--log-level", "debug", "--allow" , "0.0.0.0/0"]
生成 Docker 镜像:
docker build -t distcc_server:x86_64 -f Dockerfile_distcc.x86_64 .
可以用命令 <span class="pre">docker <span class="pre">images</span></span>
查看生成的 Docker 镜像:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
distcc_server x86_64 138c0b7e3801 9 minutes ago 66.1MB
用新建的镜像启动 Docker 容器,在主机网络的 3632 TCP 端口提供 distcc 服务:
docker run -d -p 3632:3632 distcc_server:x86_64
用命令 <span class="pre">docker <span class="pre">ps</span></span>
可以查看正在运行中的容器:
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa468d068185 distcc_server:x86_64 "/usr/bin/distccd --…" 9 minutes ago Up 9 minutes 0.0.0.0:3632->3632/tcp epic_chatterjee
1.2.3. 设备部署 Docker
apt-get update
wget -qO- https://get.docker.com/ | sh
将当前用户添加到 dokcer 用户组中:
sudo groupadd docker
sudo gpasswd -a $USER docker
newgrp docker
启动 Docker 后台服务:
service docker start
新建 <span class="pre">Dockerfile_distcc.arm64</span>
文件,内容如下:
FROM ubuntu:bionic
MAINTAINER Firefly <service@t-firefly.com>
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
gcc distcc\
&& apt-get clean \
&& rm -rf /var/lib/apt/lists
EXPOSE 3632
ENTRYPOINT ["/usr/bin/distccd"]
CMD ["--no-detach" , "--log-stderr" , "--log-level", "debug", "--allow" , "0.0.0.0/0"]
生成 Docker 镜像:
docker build -t distcc_server:arm64 -f Dockerfile_distcc.arm64 .
用新建的镜像启动 Docker 容器,在主机网络的 3632 TCP 端口提供 <span class="pre">distcc</span>
服务:
docker run -d -p 3632:3632 distcc_server:arm64
用 <span class="pre">docker <span class="pre">save</span></span>
命令导出新建的镜像:
docker save -o distcc_server.tar distcc_server:arm64
将生成的 <span class="pre">distcc_server.tar</span>
文件复制到另一块设备上,然后导入镜像:
docker load -i distcc_server.tar
导入镜像后,在这个设备上也有了 <span class="pre">distcc_server:arm64</span>
镜像,然后可以运行一个容器:
docker run -d -p 3632:3632 distcc_server:arm64
提示:用户如果注册了 Docker Hub 帐号,可以用 <span class="pre">docker <span class="pre">push</span></span>
推送镜像到远程仓库,在另一设备上用 <span class="pre">docker <span class="pre">pull</span></span>
拉取远程仓库的镜像。用户可以自行了解相关操作。
1.2.4. 客户端用 distcc 编译内核
到这里,三个机器都部署了分布式编译环境。可以选择任意一台机器作为客户端,剩下两个机器作为服务器。这里选择其中一个设备作为客户端。
在客户端中创建 <span class="pre">Dockerfile_compile.arm64</span>
文件,生成一个编译内核的 Docker 镜像,文件内容如下:
FROM ubuntu:bionic
MAINTAINER Firefly <service@t-firefly.com>
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends --no-install-suggests \
bc make python sed libssl-dev binutils build-essential distcc\
liblz4-tool gcc \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists
然后生成镜像:
docker build -t compile:arm64 -f Dockerfile_compile.arm64 .
在启动容器前先将内核文件拉到客户端中。然后创建 <span class="pre">/etc/distcc/hosts</span>
文件,其内容是列举出所有提供 distcc 服务的机器的 IP 地址。内容如下:
192.168.1.100
192.168.1.101
193.168.1.102
为了测试结果更准确,先清除客户端设备上的缓存:
echo 3 > /proc/sys/vm/drop_caches
用 <span class="pre">compile:arm64</span>
镜像启动一个 Docker 容器,同时将主机当前内核目录挂载到容器中的 <span class="pre">/mnt</span>
目录,将主机的 <span class="pre">/etc/distcc/hosts</span>
文件挂载到容器的 <span class="pre">/etc/distcc/hosts</span>
中,并用参数 <span class="pre">-it</span>
以交互模式启动容器:
docker run -it --rm -v $(pwd):/mnt -v /etc/distcc/hosts:/etc/distcc/hosts compile:arm64 /bin/bash
root@f4415264351b:/# ls
bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
root@f4415264351b:/# cd mnt/
进入到容器中的 <span class="pre">/mnt</span>
目录,然后开始用 distcc 编译内核,加入 <span class="pre">time</span>
命令可以查看编译命令执行耗时,<span class="pre">CC</span>
参数指明用 <span class="pre">distcc</span>
进行编译:
time make ARCH=arm64 rk3399-firefly.img -j32 CC="distcc"
注意:如果用 PC 机作为客户端,则需要用以下命令进行编译:
time make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- rk3399-firefly.img -j32 CC="distcc aarch64-linux-gnu-gcc"
编译过程中,可以在用于编译的容器内新的窗口中用命令 <span class="pre">distccmon-text <span class="pre">1</span></span>
查看编译情况:
distccmon-text 1
...
15713 Compile perf_regs.c 192.168.1.101[0]
15327 Compile fork.c 192.168.1.101[2]
15119 Compile dma-mapping.c 192.168.1.101[3]
15552 Compile signal32.c 192.168.1.100[0]
15644 Compile open.c 192.168.1.100[2]
15112 Compile traps.c 192.168.1.100[3]
15670 Compile arm64ksyms.c 192.168.1.102[0]
15629 Compile mempool.c 192.168.1.102[2]
15606 Compile filemap.c 192.168.1.102[3]
15771 Preprocess localhost[0]
15573 Preprocess localhost[1]
15485 Preprocess localhost[2]
...
最后编译命令完成后可以看到编译所用时间:
real 15m44.809s
user 16m0.029s
sys 6m22.317s
下边是单独使用一块设备进行内核编译所耗费的时间:
real 23m33.002s
user 113m2.615s
sys 9m29.348s
对比可见,用采用 distcc 实现的分布式编译可以有效提高编译速度。
注意:
平台不同,所需的编译器也不同。如在 x86_64 平台上,需要安装对应的交叉编译工具 <span class="pre">gcc-aarch64-linux-gnu</span>
。在 arm64 平台则只需要安装 <span class="pre">gcc</span>
编译工具即可。用户需要根据实际情况在对应的 <span class="pre">Dockerfile</span>
文件里指定安装正确的工具。
如果用 PC 机做客户端,则在用于编译的容器中编译内核的时候,要用参数 <span class="pre">CC="distcc <span class="pre">aarch64-linux-gnu-gcc"</span></span>
指明用 <span class="pre">aarch64-linux-gnu-gcc</span>
交叉编译工具编译。
原作者:DMCF