1. Docker 相关

1. Docker 相关

1.1. Docker 支持

Firefly 发布的普通固件一般不满足 Docker 的运行要求,如果有需求,可以使用 SDK 打开内核的相关配置,重新编译烧录内核以支持 Docker。

以下案例是基于 Firefly Ubuntu 20.04,内核配置部分是通用的!

1.1.1. 检查 Kernel 配置

首先需要通过工具检查当前设备的内核缺少了哪些 Docker 需要的配置。检测脚本check-config.sh可以前往社区论坛获取。

获取到脚本之后,开始进行检测:

#将脚本拷贝到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. 开启需要的配置

从上面的检测结果中得知需要打开哪些配置后,即可使用make ARCH=arm64 menuconfig进入菜单,搜索对应项目将其打开。请认真查看菜单中的操作说明,遇到不可选中的项目请注意依赖关系。

开启所有必要配置以及部分可选配置后,注意保存:

make ARCH=arm64 savedefconfig
mv defconfig arch/arm64/configs/firefly_linux_defconfig

之后进行编译内核:

#退回到SDK目录
cd ..
#编译内核
./build.sh kernel

1.1.3. 安装 Docker

烧录完新内核之后,可以开始在设备上安装 Docker 并验证:

#这里仅介绍直接使用脚本快速安装
apt-get update
wget -qO- https://get.docker.com/ | sh

等待安装成功之后应该会看见 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://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

1.2. 使用 Docker 搭建分布式编译环境

distcc 是个通过网络上的若干台机器用来分布式编译 C、C++、Objective-C 或 Objective-C++ 代码的程序。distcc 不要求所有的机器共享文件系统,有同步的时钟,或者安装有同样的库和头文件,只要作为服务器的机器有合适的编译工具即可进行编译。本例在两个 Firefly-RK3399 板卡 (arm64) 和一台 PC 机 (x86_64) 上利用 Docker 技术来布署 distcc 分布式编译服务,进而实现在其中一个 Firefly-RK3399 板卡上利用 distcc 的分布式编译特性来加速内核的编译过程。

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            # 添加 docker 用户组
sudo gpasswd -a $USER docker    # 将当前用户添加到 docker 用户组中
newgrp docker                   # 更新 docker 用户组

启动 Docker 后台服务:

sudo service docker start

新建一个 Dockerfile_distcc.x86_64 文件。其文件内容如下:

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 .

可以用命令 docker images 查看生成的 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

用命令 docker ps 可以查看正在运行中的容器:

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

启动 Docker 后台服务:

service docker start

新建 Dockerfile_distcc.arm64 文件,内容如下:

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 端口提供 distcc 服务:

docker run -d -p 3632:3632 distcc_server:arm64

用 docker save 命令导出新建的镜像:

docker save -o distcc_server.tar distcc_server:arm64

将生成的 distcc_server.tar 文件复制到另一块设备上,然后导入镜像:

docker load -i distcc_server.tar

导入镜像后,在这个设备上也有了 distcc_server:arm64 镜像,然后可以运行一个容器:

docker run -d -p 3632:3632 distcc_server:arm64

提示:用户如果注册了 Docker Hub 帐号,可以用 docker push 推送镜像到远程仓库,在另一设备上用 docker pull 拉取远程仓库的镜像。用户可以自行了解相关操作。

1.2.4. 客户端用 distcc 编译内核

到这里,三个机器都部署了分布式编译环境。可以选择任意一台机器作为客户端,剩下两个机器作为服务器。这里选择其中一个设备作为客户端。

在客户端中创建 Dockerfile_compile.arm64 文件,生成一个编译内核的 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 .

在启动容器前先将内核文件拉到客户端中。然后创建 /etc/distcc/hosts 文件,其内容是列举出所有提供 distcc 服务的机器的 IP 地址。内容如下:

# As described in the distcc manpage, this file can be used for a global
# list of available distcc hosts.
#
# The list from this file will only be used, if neither the
# environment variable DISTCC_HOSTS, nor the file $HOME/.distcc/hosts
# contains a valid list of hosts.
#
# Add a list of hostnames in one line, seperated by spaces, here.
192.168.1.100
192.168.1.101
193.168.1.102

为了测试结果更准确,先清除客户端设备上的缓存:

echo 3 > /proc/sys/vm/drop_caches

用 compile:arm64 镜像启动一个 Docker 容器,同时将主机当前内核目录挂载到容器中的 /mnt 目录,将主机的 /etc/distcc/hosts 文件挂载到容器的 /etc/distcc/hosts 中,并用参数 -it 以交互模式启动容器:

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/

进入到容器中的 /mnt 目录,然后开始用 distcc 编译内核,加入 time 命令可以查看编译命令执行耗时,CC 参数指明用 distcc 进行编译:

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"

编译过程中,可以在用于编译的容器内新的窗口中用命令 distccmon-text 1 查看编译情况:

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 平台上,需要安装对应的交叉编译工具 gcc-aarch64-linux-gnu。在 arm64 平台则只需要安装 gcc 编译工具即可。用户需要根据实际情况在对应的 Dockerfile 文件里指定安装正确的工具。

  • 如果用 PC 机做客户端,则在用于编译的容器中编译内核的时候,要用参数 CC="distcc aarch64-linux-gnu-gcc" 指明用 aarch64-linux-gnu-gcc 交叉编译工具编译。

 

本公司成本价甩卖工控主板,欢迎大家选购:
PCIE总线转八串口卡,PCIE总线转IO卡,瑞芯微3568板卡,寒武纪CE3226摄像头板卡,龙芯3A4000工控板卡,龙芯3A5000工控板卡,海光3250工控板卡,飞腾FT-2000/4板卡

联系方式:
电话、微信:15918785568 罗生
Email:13279654@qq.com
公众号:开发之美

posted @ 2022-04-15 16:39  DMCF  阅读(417)  评论(0编辑  收藏  举报