ubuntu16.04 利用Docker 部署C++ Gui項目(OpenCV PCL動態庫集成)


1、打包你的C++程序

一個良好的可移植的C++程序應該包含可執行文件、依賴的動態庫、以及參數和數據項。其中,依賴的動態庫需要ldd命令查看,如下圖:

 

通過ldd ./yourexe  可快速的查看你的程序所依賴的動態庫文件和他們所在的文件位置,為了方便,接下來使用腳本ldd.sh將他們拷貝至特定文件夾:

 1 function useage()
 2 {
 3     cat << EOU
 4 Useage: bash $0 <path to the binary> <path to copy the dependencies>
 5 EOU
 6 exit 1
 7 }
 8 
 9 #Validate the inputs
10 [[ $# < 2 ]] && useage
11 
12 #Check if the paths are vaild
13 [[ ! -e $1 ]] && echo "Not a vaild input $1" && exit 1 
14 [[ -d $2 ]] || echo "No such directory $2 creating..."&& mkdir -p "$2"
15 
16 #Get the library dependencies
17 echo "Collecting the shared library dependencies for $1..."
18 deps=$(ldd $1 | awk 'BEGIN{ORS=" "}$1\
19 ~/^\//{print $1}$3~/^\//{print $3}'\
20  | sed 's/,$/\n/')
21 echo "Copying the dependencies to $2"
22 
23 #Copy the deps
24 for dep in $deps
25 do
26     echo "Copying $dep to $2"
27     cp "$dep" "$2"
28 done
29 
30 echo "Done!"

使用的方法:ldd.sh yourexe(可執行文件) des_path(目標文件夾)。此后,獲取到所有依賴的動態庫文件之后,將可執行文件、庫文件一起打包即可移植到其他電腦運行,當然還需要指定程序運行時查找動態庫的路徑。(ubuntu系統下查找路徑常為:/lib .usr/lib /usr/local/lib) 可以修改環境變量的方式將庫文件路徑加入到環境變量中,告訴系統在程序運行時到哪里去找依賴庫,因此運行腳本run.sh可以這樣寫:

 

 1   path_curr=$(cd `dirname $0`; pwd)
 2 #dirname $0,取得當前執行的腳本文件的父目錄
 3 #cd `dirname $0`,進入這個目錄(切換當前工作目錄)
 4 #pwd,顯示當前工作目錄(cd執行后的)
 5 
 6 # add share lib path to system
 7 export PATH="${path_curr}:$PATH"
 8 export LD_LIBRARY_PATH="${path_curr}:$LD_LIBRARY_PATH"
 9 
10 # print for debug
11 #echo $LD_LIBRARY_PATH
12 #ldd ./main
13 
14 # execute
15 ./yourexename $prama1 $prama2 $3prama3
16 # $0 $1 $2 $3 is the parameters from Terminal

因此現在打包之后的文件夾中應該包含——所有動態庫文件(.so)、可執行文件(exe)及數據文件、啟動腳本(.sh)

 

2、Docker理解與使用

         為什么要用Docker?假設有這樣一個場景,你在你的ubuntu中編寫並編譯通過了的程序需要交付給測試人員測試,如何做?直接發可執行文件?當然不行,這樣你的測試人員會問你為什么我運行報錯,你會說缺少一個某某庫,你編譯一下某某庫再運行吧,顯然,這是一種極其不合理的測試方式,換一台電腦就要重新配置,將浪費大量的時間。或者你可以說把你的電腦拷貝給測試人員,這很傳統也很好地解決了這個問題,docker解決了“把你的電腦拷貝”這個問題。你可以利用docker制造一個與你的電腦環境相同的母本(image)並上傳到你的個人倉庫(dockerhub),測試人員只需要到倉庫pull你的image,並根據你的image創造一個一摸一樣的運行環境(container)即可解決問題。這與GitHub相似,因此上手非常容易。

         制造image——Dockerfile的書寫。想要制造與本地環境相同的image,必須利用Dockerfile來實現,這類似於CmakeLists能很好地聲明預編譯組織結構一樣,Dockerfile能很好地說明將要生成的Image中應該包含什么,做什么。例如,我想要一個基於Ubuntu16.04的image,並且拷貝我本地的可執行文件和庫文件以及其他數據或是配置文件(步驟1里面說明),具體的Dockerfile語法參考Dockerfile命令詳解。我的Dockerfile如下:

 

 1 FROM ubuntu:16.04
 2 
 3 RUN apt-get update
 4 RUN apt-get install -y ocl-icd-opencl-dev
 5 
 6 RUN  mkdir /usr/src/OESM_Rebuild
 7 RUN  mkdir /usr/src/OESM_Rebuild/build
 8 
 9 
10 
11 
12 COPY so_lib /usr/src/OESM_Rebuild/build
13 COPY resource /usr/src/OESM_Rebuild/build
14 
15 
16 
17 RUN ["chmod", "a+x", "/usr/src/OESM_Rebuild/build/run.sh"]
18 
19 WORKDIR /usr/src/OESM_Rebuild/build
20 
21 
22 CMD ./run.sh

 

 

 

          Dockers 幾個常見命令:

sudo apt-get install docker-ce  —— 下載安裝Docker社區版

docker images  —— 查看本地的images(會以列表形式顯示本地的images)

 

 

docker rmi  IMAGE ID  —— 刪除特定ID的image

docker ps -a ——查看本地所有容器

 

docker rm CONTAINER ID  —— 刪除特定ID的容器

docker login —— 登錄你的Docker

docker  push  IMAGE:TAG ——上傳image到你的倉庫 

docker pull IMAGE:TAG ——拉取Image

docker save -o filepath.tar  IMAGE  —— 保存image到壓縮包

docker load -i  filepath.tar  —— 從壓縮包中加載image

 

最重要的命令:docker run [OPTIONS] IMAGE [COMMAND] [ARG...] ——理解為參考某鏡像並生成容器運行。這里的COMMOND會覆蓋Dockerfile中的CMD命令作為容器生成后的第一條指令。

 

        通過dockerfile書寫生成鏡像image后,可以通過save命令保存成壓縮包,隨后可以通過load加載壓縮包生成鏡像(這個速度比Dockerfile要快),因此現在具有鏡像壓縮包后只要調用load命令和docker run命令似乎就可以在別的電腦運行自己的程序了。但還是有問題,引文我的C++利用了PCL點雲庫和OpneCV圖形庫,會具有許多GUI界面,直接docker run會報錯:cannot open display。問題很好理解,你的容器不知道該去哪兒顯示這些界面,要知道它可不能直接用你的電腦屏幕,因此查找解決辦法

因此最終包括的內容包括:image.tar、docker_run.sh其中docker_run內容如下:

 

 1 apt-get install -y x11-xserver-utils
 2 
 3 xhost +
 4 
 5 docker load -i oesm_rebuild.tar
 6 
 7 docker run -i -t \
 8   -v /etc/localtime:/etc/localtime:ro \
 9   -v /tmp/.X11-unix:/tmp/.X11-unix \
10   -e DISPLAY=unix$DISPLAY \
11   -e GDK_SCALE \
12   -e GDK_DPI_SCALE \
13    oesm_rebuild:v1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM