QT程序打包并部署在docker内
最进尝试写qt的界面程序,想将qt程序打出一个独立的包,并运行在docker内,网上的教程都存在部分问题(或者是不满足我的使用场景)
参考网址
一. 安装 linuxdeployqt
1.1 下载 linuxdeployqt
在 linuxdeployqt 下载 , 下载的包是一个静态程序可以直接使用
1.2 安装 linuxdeployqt
即将下载的程序重命名,并放在合适的位置
mv linuxdeployqt-6-x86_64.AppImage linuxdeployqt
chmod 777 linuxdeployqt
mv linuxdeployqt /usr/local/bin
测试是否安装成功
linuxdeployqt --version
二. 使用 linuxdeployqt 找寻依赖库
运行打包指令(Test是我的qt程序,且是 release 版本的,假定我们的qt程序放在 ~/data/
目录下,当前命令也在~/data/
目录执行)
linuxdeployqt Test -appimage
此时的包都放在当前目录的 lib/ 目录下.
注意: 当前只是找寻了所需的Qt依赖,但是Qt环境需要的基础依赖库没有找齐,将其放在docker下仍然跑不起来
当报错 .desktop file is missing a Categories= key
时, 在当前目录下的 default.desktop 文件末尾添加
Categories=Application;
然后重新运行
linuxdeployqt Test -appimage
三. 补齐 libqxcb.so 依赖的库
也可以在docker内直接安装 libfontconfig1 libgl1 libxcb1 这三个库来补齐,就可以省略这一步骤了.
3.1 编写脚本 lib_qt_copy.sh
这个脚本的目的是为了找寻依赖的xcb库
#!/bin/bash
if [ $# != 1 ]
then
echo "传参数顺序: ./脚本.sh <要发布的可执行文件文件>"
exit 0
fi
LibDir=$PWD/xcblib
mkdir $LibDir
Target=$1
lib_array=($(ldd $Target | grep -o "/.*" | grep -o "/.*/[^[:space:]]*"))
for Variable in ${lib_array[@]}
do
cp "$Variable" $LibDir
done
3.2 执行脚本
libqxcb.so 在 plugins/platforms/ 目录下
bash ./lib_qt_copy.sh plugins/platforms/libqxcb.so
那么 依赖的Qt库和Qt依赖的库分别放在 lib/ 和 xcblib/ 目录下,它们之间有些库是重复的,可以将它们合成一个目录.
四. 给予 docker 访问 gui 的权限.
在 /etc/profile 末尾添加
if [ "$DISPLAY" != "" ]
then
xhost +
fi
然后在当前终端执行
source /etc/profile
此后所有的操作都需要在当前终端上执行,因为当前终端开启了x11权限.重启后就不会有这些顾虑了,因为已经应用到了全局.
4.1 进入docker终端
有两种方式,第一种就是编写 docker compose 的配置文件,第二种就是直接在 docker run 后面接参数.
两种方式使用一个就行
方式一. 使用 docker compose 进入终端
创建 docker-compose.yml 文件,并添加以下内容
注意: 我们添加了一个docker目录的映射,所以将前面打包的qt程序放在当前目录下的docker目录下,这样就不用后续拷贝到docker里面的.
version: '3.9'
name: code-develop
services:
ubuntu:
environment:
- DISPLAY
tty: true
image: ubuntu:18.04
profiles: ["ubuntu"]
network_mode: host
privileged: true
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- ~/data:/data
如果没有 docker 镜像,记得先拉取 ubuntu:18.04 镜像
执行 docker 容器的生成
docker compose up ubuntu -d
进入 docker 容器
docker compose exec ubuntu bash
方式二. 使用 docker run 命令进入终端
执行命令
docker run -itd -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY -e GDK_SCALE -e GDK_DPI_SCALE --name test-gui --privileged -v ./data:/data --network host ubuntu:18.04 bash
docker exec -it test-gui bash
4.2 测试 gui 权限是否开放成功
在docker容器内运行下面指令,如果 apt 比较慢的话,可以自己手动更改镜像源(推荐华为镜像源和清华镜像源)
apt update
apt install xarclock
xarclock
如果 xarclock 运行起来的话,就说话gui权限已经开放,若报错 can't open display
,则重启电脑,并重新进入docker ,看能否执行成功.
五. 运行 qt 程序
进入docker后,开始测试我们的Qt程序能否执行.
设置依赖库的环境变量和Qt调试环境变量
cd /data/
# 这一步是为了报错的时候,可以看到报错的地方
export QT_DEBUG_PLUGINS=1
# 这一步是给出依赖的库路径,请根据实际情况调整
export LD_LIBRARY_PATH=./lib/:./xcblib
./Test
如果中间报错缺少库,设置 QT_DEBUG_PLUGINS 为 1 后可以看到缺少库的名称,可以在主机中找到对应的库并拷贝到 docker 中.
也可以通过 apt-file search libxx.so
来查找属于哪个包,然后安装对应的包.
要写的东西比较多,所以有些混乱,有不同见解的地方可以沟通,我也会持续更新和改善这篇文章.