为drone制作qt编译打包的ubuntu环境的docker镜像

2023/09/27

Tags: C++ CI/CD Ubuntu Qt Docker

Table of Contents

0.前言

之前我已经写了 Drone+Forgejo+SonarQube 持续集成code review的文档,

但在之前的文档中,我们并没有自己动手创建docker,都是用别人做好的镜像。

现在我们需要把开发环境打到docker镜像中,并且把我们的代码库拉到镜像中,做一个基线 ,

每次Forgejo上触发一个webhook时,我们上Drone基于这个基线,执行指令递归拉取所有git submodule,执行打包脚本。

1 三种思路

摆在我们面前有三种选择

前者的好处是,文件系统分层情况良好,当你有很多镜像时,他们可能可以复用某一些文件层,节约空间和网络流量

不好的地方就是步骤比较繁琐。后者的好处就是操作简单,但基础镜像的分层信息会丢失。

因为我们除了Drone构建打包用docker,基本上没其他事了,ubuntu16裸机的这个分层,复用率不高,另外我们只在ci cd的这台电脑上加载这个镜像,没有什么docker集群,所以也不用担心网络流量的问题。所以综合考虑,我们可以考虑使用第二种方式或第三种方式, 由于我硬盘剩余空间比较小,故采用第二种方式

1 安装docker

由于闫工给我的机器是ubuntu,所以我用apt安装 docker,略

2.制作开发环境docker

2.1 docker镜像 拉取,启动

拉一个下载量最多的

1
root@drone-ci-8-20:~# docker pull homebrew/ubuntu16.04

这时查看电脑上的镜像可以看到已经拉取的

1
2
3
root@drone-ci-8-20:~# docker images
REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
homebrew/ubuntu16.04   latest    6347afdf9148   6 months ago   1.27GB

实例化容器

1
2
root@drone-ci-8-20:~# docker run -d homebrew/ubuntu16.04 tail -f /dev/null
ed1c0b7568119b788b940e21fb1b2d50d63c3e9fe74a48a1dabd0d02987b3a5c

tail -f /dev/null 会使这个容器一启动就 一直保持运行,这样我们才有机会进去安装环境

1
2
3
root@drone-ci-8-20:~# docker ps -a
CONTAINER ID   IMAGE                  COMMAND               CREATED          STATUS          PORTS     NAMES
ed1c0b756811   homebrew/ubuntu16.04   "tail -f /dev/null"   25 seconds ago   Up 24 seconds             sharp_shtern

查看一下容器,已经有一个状态 为up的容器,说明运行成功了。

接下来使用 exec -it 以交互的形式执行容器的bash ,

1
2
root@drone-ci-8-20:~# docker exec -it ed1c /bin/bash
linuxbrew@149b1d533469:~$

看一下系统内核

1
2
3
linuxbrew@ed1c0b756811:~$ uname -a
Linux ed1c0b756811 5.15.0-84-generic #93-Ubuntu SMP Tue Sep 5 17:16:10 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
linuxbrew@ed1c0b756811:~$

内核显示为5.15,而实际上ubuntu内核最新的是4.15.142, 两者显示不一样是因为docker container使用的是host的内核

不过我们只是编译软件,应该没有太多问题,先不管内核版本

接下来的操作,就和ubuntu裸机安装环境没太多区别了,甚至更简单,因为我们只是要编译软件,不需要安装运行环境,比如驱动

2.2 安装基础依赖

接下来更新一下我们公司的apt源 ,下载一下闫工之前写的脚本

1
2
3
4
5
6
sudo -i 
apt update
apt install wget
cd ~
wget http://file.deepvision-tech.net/scripts/apt.sh
chmod +x apt.sh

因为docker中的网络环境和主机中不一样,所以我们需要修改一下脚本 ,手动注释掉 杭州或北京的脚本 逻辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash

# v1.1
# 2023.3.21
# yanqianling@deepvision-tech.com

OldSource=`grep ^deb /etc/apt/sources.list|awk '{print $2}'|sort |uniq |sed '/security.ubuntu.com/d'`

NewSource="-apt.deepvision-tech.net/repository/apt-"

OsVer=`cat /etc/issue|awk -F'[ .]+' '{print $2}'`

IP=`ip a | awk '-F[ .]+' '/255/{print $3"."$4"."$5}'|egrep '10.[1,2,8]{1}.'`

YELOW='\E[1;33m'
RED='\E[1;31m'
RES='\E[0m'

#case $IP in
#       "10.2.1")
#               cp -f /etc/apt/sources.list /etc/apt/sources.list.bak
#               echo ""
#               echo -e  "${YELOW} Old apt sources backup to [/etc/apt/sources.list.bak] ${RES}"
#               sed -i "s#${OldSource}#http://bj${NewSource}${OsVer}/#g" /etc/apt/sources.list
#               echo -e "${YELOW} new apt source replaced by [http://bj${NewSource}${OsVer}] ${RES}"
#               echo -e "${YELOW} Please run command [sudo apt update],Let config become effective ${RES}"
                #;;
#       "10.1.1"|"10.1.8")
                cp -f /etc/apt/sources.list /etc/apt/sources.list.bak
                echo ""
                echo -e  "${YELOW} Old apt sources backup to [/etc/apt/sources.list.bak] ${RES}"
                sed -i "s#${OldSource}#http://hz${NewSource}${OsVer}/#g" /etc/apt/sources.list
                echo -e "${YELOW} new apt source replaced by [http://hz${NewSource}${OsVer}] ${RES}"
                echo -e "${YELOW} Please run command [sudo apt update],Let config become effective ${RES}"
#               ;;
#       *)
#               echo -e "${YELOW} ${IP} ${RES}"
#               echo -e "${YELOW}YOU IP Error ${RES}"
#esac
~
~
~

例如我操作的这个机器是在杭州的,我就把脚本中的case 语句注释掉,只留下杭州这一段逻辑

然后执行它

1
./apt.sh

替换完源后 ,更新一下

1
apt update

然后开始安装编译环境

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
sudo apt install  -y liblapack-dev
sudo apt install  -y libjpeg-dev libpng12-dev libtiff-dev libjasper-dev libdc1394-22-dev
sudo apt install  -y libva1 libva-dev libva-drm1 libva-egl1 libva-glx1
sudo apt install  -y libswscale-dev libavcodec-dev libavformat-dev
sudo apt install  -y libssh2-1 zlib1g-dev
sudo apt install  -y libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev libsndio-dev
sudo apt install  -y python3-pip
pip3 install openpyxl==2.6.4
pip3 install xlrd==1.2.0
sudo apt install  -y libcap-dev libx11-dev libxext-dev libgtk-3-dev libglade2-0 libglade2-dev libpcap0.8  libcap2 ethtool
sudo apt install  -y libsndio-dev
sudo apt install  -y  libxcb-keysyms1-dev  libxcb-image0-dev  libxcb-shm0-dev  libxcb-icccm4-dev  libxcb-sync0-dev  libxcb-xfixes0-dev  libxcb-shape0-dev  libxcb-randr0-dev  libxcb-render-util0-dev  libfontconfig1-dev  libfreetype6-dev  libx11-dev  libxext-dev  libxfixes-dev  libxi-dev  libxrender-dev  libxcb1-dev  libx11-xcb-dev  libxcb-glx0-dev  x11vnc  xauth  build-essential  mesa-common-dev  libglu1-mesa-dev  libxkbcommon-dev  libxcb-xkb-dev  libxslt1-dev  libgstreamer-plugins-base0.10-dev  libxkbcommon-x11-0  
sudo apt-get install build-essential  libgli-mesa-dev   libglul-mesa-dev   freeglut3-dev

sudo apt install -y libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libfontconfig1-dev libfreetype6-dev libx11-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libx11-xcb-dev libxcb-glx0-dev x11vnc xauth build-essential mesa-common-dev libglu1-mesa-dev libxkbcommon-dev libxcb-xkb-dev libxslt1-dev libgstreamer-plugins-base0.10-dev libxkbcommon-x11-0 

2.3 安装Qt

2.3.1 方式一,编译源码安装

安装qt 5.12.6

传统的方式是 在有gui的环境下运行.run的安装包, 但docker 里的ubuntu默认是没有图形界面的。

所以直接下载官网的源码编译,安装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
wget https://download.qt.io/archive/qt/5.12/5.12.6/single/qt-everywhere-src-5.12.6.tar.xz

tar -zxvf qt-everywhere-src-5.12.6.tar.xz 

cd qt-everywhere-src-5.12.6

./configure

make -j8

make install 

# 如果出现问题make confclean 清除配置信息 重新编译

安装完后会有 /local/Qt-5.12.6/这个路径, 把qmake复制到/usr/bin ,然后键入 qmake -v 查看是否编译安装正常

1
2
3
linuxbrew@ed1c0b756811:/usr$ qmake -v
QMake version 3.1
Using Qt version 5.12.6 in /usr/local/Qt-5.12.6/lib

因为我们只是用docker来构建,不需要启动图形界面,所以这种可以减少不必要的依赖安装,但编译时长较长,如果不想编译源码的话,可以使用另一种方案,docker宿主机上安装桌面环境

2.3.2 方式二,docker挂载宿主机图形相关卷启动

1
2
sudo apt install ubuntu-desktop
xhost local:root

使用vnc远程到宿主机后,然后参照这个设置,把docker挂载上显示相关的卷,

1
docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -v /dev/shm:/dev/shm --device /dev/dri 

就可以在docker容器中打开 run安装包安装了, 如果还打不开run安装包,可以尝试指定 不依赖硬件的平台

1
qt-opensource-linux-x64-5.12.6.run -platform minimal

1
qt-opensource-linux-x64-5.12.6.run -platform offscreen

p latform 的可选项

directfbegl,directfb,eglfs,linuxfb,minimal,minimalegl,offscreen,wayland-egl,wayland,xcb。

以及这个, 使用脚本,静默安装 installation - Silent install Qt run installer on ubuntu server - Stack Overflow

2.4 克隆源码构建

全安装后, 克隆一下源码

1
2
3
4
mkdir -p ~/source/repos
cd ~/source/repos/
git clone http://10.1.8.8/AL/dv-detector.git
git submodule update --init --recursive

然后就可以运行打包脚本构建了

1
./pkg.sh 1.1.1.1  tst_build

2.5 把现有docker container 转换为docker image

删除掉不需要的文件,尽可能减少容器占用的空间,然后再打镜像

1
2
3
4
5
root@drone-ci-8-20:~# docker ps -a
CONTAINER ID   IMAGE                  COMMAND               CREATED          STATUS          PORTS     NAMES
ed1c0b756811   homebrew/ubuntu16.04   "tail -f /dev/null"   25 seconds ago   Up 24 seconds             sharp_shtern

docker commit ed1c0b756811 dv_detector:master1.1.1.1

因为我们目前没有搭建docker 私有仓库,所以一般通过导入导出 docker 镜像到文件系统传输

导出docker 镜像到文本系统

1
docker save -o myimage_exported.tar dv_detector:master1.1.1.1

从文件系统导入

1
docker load -i myimage_exported.tar

3 配置drone,执行docker runner

Overview | Drone

官网之述备矣

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
kind: pipeline
type: docker
name: build

clone:
  disable: true

steps:
  - name: pkg
    image: dv_detector:master1.1.1.1
    environment:
      DRONE_BRANCH: $DRONE_BRANCH
      PKG_VERSION: "1.1.1.2"
      PKG_NAME: "测试打包"

    settings:
      detach: false
      entrypoint: [""]  
    commands:
      - cd ~/source/repos/dv-detector
      - git reset --hard
      - git clean -xdf
      - git pull origin master
      - git submodule update --recursive
      - bash -c "./pkg.sh $PKG_VERSION $PKG_NAME''_$(git rev-parse --short=6 HEAD)"

最终打出的包放在容器中没后续动作,因为本文只做技术验证

如果需要,只需要在comands里加额外的处理就可以了

image-20230927200630893


end

100. 附录:Docker 常用命令

100.1 容器生命周期管理:

100.2 镜像操作:

100.3容器日志和信息:

100.4容器文件传输:

100.5构建镜像:

100.6Docker Compose:

100.7网络操作:

100.8清理:

>> Home

Comments