前言

根據5月11號AgileX的消息,LIMO的ROS2將採用Docker的方式部署環境,官方給出的幾個原因如下:

  1. Jetson Nano仍未提供官方的Ubuntu20.04版本,這代表以比較新的ROS2版本開發的LIMO難以直接部署環境
  2. LIMO原生安裝的ROS若和ROS2共存,可能產生開發環境混亂的狀況,更可能發生非預期的錯誤
  3. 備份相較使用映像檔方式方便

 

而由於近期NVidia主板缺貨,大量的替代板出現的狀況下產生了其他可能適用的理由:

  1. 替代板大多使用emmc,在emmc空間不足的狀況下,Docker可以透過改變容器位置來利用外接硬碟空間
  2. emmc主板環境備份麻煩(需要Linux系統),備份一個container相較簡單
  3. 發佈只需要一個文件檔,用戶可以透過Docker載入文件檔自動重新建立出container,而不需傳送幾GB的映像檔

 

因此,本篇文章將來說明,這個未來不只LIMO,可能很多地方都會使用到的技術:Docker

 

Docker是什麼?

Docker 是一個開放原始碼軟體,是一個開放平台,用於開發應用、交付應用、執行應用。 Docker允許使用者將基礎設施中的應用單獨分割出來,形成更小的顆粒(容器),從而提高交付軟體的速度。

Docker容器與虛擬機器類似,但二者在原理上不同。容器是將作業系統層虛擬化,虛擬機器則是虛擬化硬體,因此容器更具有可攜式性、高效地利用伺服器。 容器更多的用於表示 軟體的一個標準化單元。由於容器的標準化,因此它可以無視基礎設施的差異,部署到任何一個地方。另外,Docker也為容器提供更強的業界的隔離相容。

Docker 利用Linux核心中的資源分離機制,例如cgroups,以及Linux核心命名空間,來建立獨立的容器(containers)。這可以在單一Linux實體下運作,避免啟動一個虛擬機器造成的額外負擔。

 

上面的文字為wiki的Docker敘述--說實話,第一眼確實不太容易看懂這在說什麼,因此我們用簡單的方式重新試著說明。

 

不知道大家有沒有使用過VMWare,或者Visual Box這類虛擬機軟體?

虛擬機無疑為我們帶來很多便利,由於大多數人的電腦都是windows,需要執行其他系統才支援的程式時就會使用到虛擬機,最常使用到的可能就是Ubuntu系統虛擬機和手機的Android虛擬機了。但使用虛擬機會有個問題--當我們大量啟動虛擬機後,對電腦運算能力和資源的需求會越堆越高,甚至到了會影響原生系統安定性的程度。

Docker可以說是一種更輕便的虛擬機。相較於一般的虛擬機需要安裝整個系統,Docker只將必要的東西打包起來執行,換個說法就是虛擬機包含作業系統,而Docker不包含。我們可以看一下底下這張圖來了解兩者的包含關係:

圖中右邊為VM,可以看到VM包含OS,並且在和硬體之間有一個虛擬層,VM透過虛擬層和硬體溝通(因此常常聽到VM使用了硬體虛擬化技術)

左邊的Docker不包含OS,而是在OS之上架構了一個Docker層,透過Docker層和OS溝通(因此有人說Docker使用的是系統虛擬化技術)

兩者包含層級的不同使得在效能上有巨大的差異。根據實驗,Docker中執行程式的速度幾乎和原生系統完全相同,且大多數情況而言,一個安裝完整資源的容器大小遠小於VM的大小,這使得Docker在執行效率和發布效率上都遠勝於VM--Docker綁定在系統上是個小小的缺點,但大多數的機器人和嵌入式裝置都使用Ubuntu作為主系統,因此這問題並不嚴重。

 

當然,不在Ubuntu上還是可以使用的,代價就是需要額外安裝Linux核心--但這調整不見得常常會成功:

(去年本鳥試圖在windows上使用Docker時撞出的隕石坑,就是硬體虛擬化跟系統虛擬化的設定衝突了……)

 

而在機器人上之所以需要使用Docker,最大的原因就是希望開發環境獨立了。

相較於另外一個技術--Visual Env而言,Docker支援的語言不限於python,也不限於該語言需要的函式庫,而是任何語言和任何你在系統會安裝的東西都可以一併獨立打包。比方說,ROS(2)會使用apt方法安裝,若使用Visual Env則沒辦法讓主系統和開發環境分離,使用Docker則可以。除了容易發佈和使用別人提供的ROS2環境,要還原自己的錯誤動作也可以利用Docker的版本機制救回。而使用ROS2開發的用戶,也可能因為ROS2改版而躊躇是否需要跟進新版的ROS2,這時候使用Docker,在一台機器人上面共存多個不同版本的ROS2就不是問題了。

另外一個好處是解決了emmc版本主板的問題。

目前市面上比較常見的emmc主板,幾乎都是使用16GB作為標準規格--這個尺寸在RPi上可能還好,但在NV Jetson Nano上就有點嚴重了。NVidia Jetson Nano本身的原生映像檔就高達12GB, 扣除掉常常用來彌補顯示卡記憶體不足的swap部分,實際上能使用的空間可能不到1GB,這幾乎是裝完ROS後就卡死的程度,更別提想裝ROS2了。雖然一般這種emmc板都會另外配備外接的擴充儲存空間(通常是SD卡),但很遺憾的,Ubuntu要變更apt的安裝位置相當的麻煩,因此大多數情況下都只能乖乖裝回原來root的位置,這意味著非常容易遇到空間不足的問題。

但變更Docker的儲存位置卻很簡單,因此利用將容器的儲存位置移動到外接空間,可以一定程度上解決這個問題。

 

如何開始使用Docker?

註:一般而言,LIMO本身有預先安裝好Docker,僅需做最底下解決sudo問題的部分即可--除非啟動時遇到異常狀況再行重裝。

 

在Ubuntu上使用Docker相對簡單,只需要注意原生裝的Docker常常是舊版的,重新裝一次比較好的這件事情就好……

以下步驟參考自Docker官方指南:在Ubuntu上安裝Docker

第一步:我們要先移除掉原本舊版的docker。

sudo apt-get remove docker docker-engine docker.io containerd runc

 

第二步:更新一下apt的列表:

sudo apt-get update

 

第三步:安裝必要的程式:

 sudo apt-get install ca-certificates curl gnupg lsb-release

 

第四步:添加官方的安裝金鑰:

 sudo mkdir -p /etc/apt/keyrings
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

 

第五步:添加Docker的安裝源:

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 

第六步:更新安裝列表並安裝:

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

 

上面步驟完成之後,我們大概就完成了Docker的安裝。要確認有沒有安裝完成,可以使用這個指令確認一下:

sudo docker run hello-world

若安裝皆正常,應該會看到以下這個畫面:

 

當然,我們現在只是安裝好他,實際上目前關鍵的容器並沒有任何我們需要的東西。

下一篇文,我們將來尋找適合的容器並解說如何安裝它。


我們前面可以注意到,我們每一行Docker指令都需要sudo執行,說真的打起來有點煩。

一個偷懶的解決方法是,將使用者直接加入可以存取Docker的群組,讓他不需要額外權限即可執行。此方法參考自官方網站

sudo groupadd docker
sudo usermod -aG docker $USER

這兩行執行完後,關閉命令列,接著使用docker命令就不需要輸入sudo了。根據官網的說法,如果有打算將Docker使用到公開的port上讓外部網路可以存取,則不太建議這樣設置(有可能有安全性上的危險)。

但因為我們後續打算搭配VSCode進行開發,因此設置不用sudo的權限有其便利性,若和我們一樣使用VSCode作為IDE,那可能還是做這個設置好一點。

 

畢竟LIMO上也沒有什麼機密資訊(?)