【泡泡Docker樂園】Dockerfile簡易教程 & LARVIO鏡像(親測完美)
簡介:【泡泡Docker樂園】第二期來啦!本期我們將簡要介紹使用Dockerfile進行image構建的方法。利用Dockerfile可以將image構建的完整過程清晰的展現出來,同時也可方便用戶複用layer,減少構建新image的時間開銷。最後將提供一個用Dockerfile構建的image項目,單目視覺慣性里程計LARVIO。
編輯:邱笑晨
審覈:王強,劉富強,吳奇,王琛
歡迎個人轉發朋友圈;其他機構或自媒體如需轉載,後臺留言申請授權
感謝晨博,感謝泡泡機器人
1、前言
本期將簡要的介紹利用Dockerfile構建image的方法。
在上一期中,image的構建採用的步驟是:首先pull一個現成的image,然後實例化一個該image的container,再在該container中進行各種操作,最後將該container進行提交(commit),從而構建一個新的image。這比較符合我們通常在虛擬機中的工作流程,即進入虛擬系統,然後在該系統內進行各種操作。
這種方式的一個缺點是,其他人在拿到這個image時無法容易地知曉該image到底是如何構建的。同時一些可複用的操作在我們下一次構建新image時又要重新來一遍,比較浪費時間。
Docker中提供了另外一種構建image的方式,即採用Dockerfile。在Dockerfile中,我們可以實現構建image所需的一切操作,包括pull基礎image、安裝各種庫、編輯腳本等等等等。所有的操作都以明文的形式寫在Dockerfile中,方便用戶掌握構建image的步驟,同時每一條Dockerfile語句都形成一層(layer),當用戶在同一基礎image上有相同操作時,這些layer可以方便的進行復用,無需重新構建。
Dockerfile基礎指令
這部分將介紹一些Dockerfile中常用的基礎指令,我們將以ROS的一個官方鏡像ros/kinetic-ros-core的Dockerfile爲例來進行介紹,地址爲:
https://github.com/osrf/docker_images/blob/b075c7dbe56055d862f331f19e1e74ba653e181a/ros/kinetic/ubuntu/xenial/ros-core/Dockerfile
該Dockerfile中所採用的指令並不是全部,但這些指令通常已經能夠替代“在container中操作再commit”的image構建過程,能夠滿足絕大多數需求。
事實上,如果你發現有操作無法在Dockerfile中完成,那一定是你還沒找到或者還沒理解某些指令。
FROM指令
FROM指令用來指定所要構建的image的基礎image。你可以在任意本地或者DockerHub的基礎上進行新image的構建,因此FROM指令可以指向本地或者DockerHub上任意可用的image。
在ros/kinetic-ros-core中,該指令的用法爲:
FROM ubuntu:xenial
這表示該image是以ubuntu的xenial標籤爲基礎image進行構建的。在後面的構建過程中,該指令會自動從DockerHub中pull下該基礎image。後續的其他指令則都基於該image執行。
在DockerFile中,每一條指令語句都構成一個layer,FROM語句一般構成所構建image的第一個layer。
RUN指令
RUN指令用來指明在上一layer基礎上要繼續進行的操作。它代替了我們進入container中執行各種終端命令來進行配置的過程。任何需要執行終端指令來構建新image的操作,都可以利用RUN來實現。
在ros/kinetic-ros-core中,使用了若干條RUN指令(受限於篇幅,我們只截取部分):
RUN apt-get update && apt-get install -q -y \
dirmngr \
gnupg2 \
&& rm -rf /var/lib/apt/lists/*
RUN apt-key adv ...
RUN echo ...
細心的同學們會發現,RUN後面跟的內容和我們在container的終端中執行的指令是一樣的。
上面的三條RUN指令,每一條形成一個layer。筆者的建議是,儘量將RUN指令模塊化,比如我們要裝某個軟件,那麼可以把所有與該軟件相關的依賴項以及該軟件的安裝都放在一條RUN語句中,這樣可提高Dockerfile的可讀性,同時也便於複用。不過一個image的layer數是有限制的,因此也要注意不要讓層數過多。
ENV指令
ENV指令用來設置環境變量,我們直接用ros/kinetic-ros-core中的例子來說明:
ENV ROS_DISTRO kinetic
RUN rosdep init && \
rosdep update --rosdistro $ROS_DISTRO
可以看到,通過ENV指令設置的環境變量ROS_DISTRO,在後面的RUN指令中被利用。這種用法的好處是,如果我們有某個參數的修改會影響到DockerFile中所有終端命令的執行,那麼我們可以設置一個環境變量,通過只修改一處環境變量,即可實現全部終端指令的調整。
同時ENV當然還具備其字面意義的功能,即爲image設置一些所需要的環境變量。
COPY指令
COPY指令是懶人福音。儘管RUN指令可以實現所有的終端命令,但有些操作我們可能還是會覺得利用終端來做比較麻煩,比如寫一個比較長的腳本。
COPY命令的基本作用是將外部文件複製到image中,我們可以利用這一點,先在宿主機中寫好一個腳本,然後直接COPY進去,避免寫一個又臭又長的RUN語句。
當然了,一旦採用這種用法,那麼如果要了解構建的所有細節,就無法單從Dockerfile中得知了,還需要去看一下外部的這個腳本到底寫的是什麼。
來看看ros/kinetic-ros-core中的用法:
COPY ./ros_entrypoint.sh /
這裏是將本地的一個已經寫好的ros_entrypoint.sh文件拷貝到新image的根目錄下。
COPY指令中的首個路徑可以是宿主機絕對路徑或者Dockerfile所在路徑的相對路徑。一般建議將所需要COPY的文件都放在和Dockerfile的同一級目錄。
ENTRYPOINT指令
ENTRYPOINT指令用來指定構建的image實例化時調用的程序。在ros/kinetic-ros-core中其用法爲:
ENTRYPOINT ["/ros_entrypoint.sh"]
這其實是將我們在之前COPY進來的腳本作爲container初始調用的程序。
CMD指令
CMD指令用來設置構建的image實例化時調用的默認命令,該命令會被docker run中傳遞的命令(如果有的話)覆蓋。在ros/kinetic-ros-core中其用法爲:
CMD [“bash”]
這即是說在創建container時會調用bash開啓一個終端。
小結
這部分以ros/kinetic-ros-core的Dockerfile爲例介紹了一些最基本和常用的Dockerfile指令的基本用法,更多指令和詳細用法請參考官方文檔:
利用Dockerfile構建image
當寫好一個Dockerfile之後,構建image就是一句話的事了,當然還需要注意把你想要COPY到image中去的文件準備好(如果有的話)。執行以下指令即可:
docker build -t IMG_NAME DOCKERFILE_PATH
這裏我們直接用本期提供的LARVIO鏡像作爲示例:
注意到該image共有15個layer,也就是說一共有15條語句,由於我之前已經構建過,因此這裏顯示的都是Using cache。
2、LARVIO項目鏡像
本期我們爲小夥伴們帶來一個單目視覺慣性里程計項目的image——LARVIO。
簡介:LARVIO是一款基於MSCKF的單目視覺慣性里程計,提供動/靜態場景的自動初始化、可選的在線傳感器標定(IMU-CAM外參、時標誤差、IMU內參)、hybrid MSCKF/純MSCKF可選、一維/三維逆深度SLAM features參數化可選、靜止檢測和零速矯正等功能。核心算法不依賴ROS,項目同時提供了單線程和ROS nodelet例程,分別採用Pangolin和Rviz兩種可視化方式。在計算開銷更低且無迴環的情況下,在EuRoC等數據集上的定位精度與VINS-MONO-LOOP相當。
DockerHub鏈接
GitHub鏈接:
LARVIO原始鏈接:
上手指南:
這裏提供一個簡易的上手指南。由於是SLAM類項目,因此需要一些可視化工具來展示運行時的pangolin或者rviz效果。
本次提供的鏡像中,已經配置好了VNC可視化的相關組件。以下是一套傻瓜教程:
(1)獲得鏡像
注意:下載速度慢的話建議把docker源配置爲阿里雲源
首先從DockerHub拉取鏡像(宿主終端中執行):
docker pull paopaorobot/larvio
或利用Dockerfile進行本地構建(宿主終端中執行):
git clone \
https://github.com/PaoPaoRobot/docker_larvio.git
cd ./docker_larvio
docker build -t paopaorobot/larvio .
注意後面.
號。
(2)VNC可視化準備
下載與你電腦操作系統匹配的VNC Viewer,地址是:
VNC 下載連接
如果是ubuntu系統,選擇DEB X64
,然後使用
sudo dpkg -i *.deb
安裝
(3)下載數據集
LARVIO的例程提供了EuRoC數據集的演示程序。其中pangolin例程需求asl格式,ros nodelet例程需求bag格式,如果網速比較慢,建議下載最小的V102序列。下載地址是:
https://projects.asl.ethz.ch/datasets/doku.php?id=kmavvisualinertialdatasets
下載不下來的話使用泡泡機器人的百度網盤
(4)創建container
我們假設你將V1_02的asl和bag都存放在宿主的YOUR_PATH_TO_EUROC/V1_02_medium路徑下,執行下述命令實例化container:
注意把bag包也放在V1_02_medium下。
docker run -itd -v \
YOUR_PATH_TO_EUROC/V1_02_medium:/root/Dataset/V1_02 \
-p 5900:5900 paopaorobot/larvio
該命令實例化了一個container並且將數據集掛載在container中的/root/Dataset路徑下。
然後打開VNC Viewer,輸入127.0.0.1:5900進行連接。如下圖:
連接後可觀察到如下界面:
(5)Pangolin例程
在VNC Viewer中,打開一個終端,執行下述命令:
cd /root/LARVIO/build
./larvio \
/root/Dataset/V1_02/mav0/imu0/data.csv \
/root/Dataset/V1_02/mav0/cam0/data.csv \
/root/Dataset/V1_02/mav0/cam0/data \
../config/euroc.yaml
即可直接運行LARVIO的pangolin例程,效果如下:
(6)ROS例程
在宿主機終端中,執行下述命令開啓LARVIO節點:
docker exec -itd \
`docker ps | grep paopaorobot/larvio | awk '{print $1}'` \
/bin/bash -c \
'cd /root/LARVIO/ros_wrapper && \
. devel/setup.bash && \
roslaunch larvio larvio_euroc.launch'
然後在VNC Viewer中,打開一個終端,執行下述命令打開rviz可視化:
cd /root/LARVIO/ros_wrapper
. devel/setup.bash
roslaunch larvio larvio_rviz.launch
回到宿主機終端,執行下命令播放數據集:
docker exec -it \
`docker ps | grep paopaorobot/larvio | awk '{print $1}'` \
/bin/bash -c \
'. /opt/ros/melodic/setup.bash && \
rosbag play \
/root/Dataset/V1_02/V1_02_medium.bag'
此時可以在VNC中看到如下效果:
點擊閱讀原文,即可獲取本文相關資源。
歡迎來到泡泡論壇,這裏有大牛爲你解答關於SLAM的任何疑惑。
有想問的問題,或者想刷帖回答問題,泡泡論壇歡迎你!
泡泡網站:www.paopaorobot.org
泡泡論壇:http://paopaorobot.org/bbs/
泡泡機器人SLAM的原創內容均由泡泡機器人的成員花費大量心血製作而成,希望大家珍惜我們的勞動成果,轉載請務必註明出自【泡泡機器人SLAM】微信公衆號,否則侵權必究!同時,我們也歡迎各位轉載到自己的朋友圈,讓更多的人能進入到SLAM這個領域中,讓我們共同爲推進中國的SLAM事業而努力!
微信掃一掃 關注該公衆號