第0036期•2016.03.21 發行
ISSN 2077-8813

首頁 > 技術論壇

淺談輕量化的虛擬技術 - Docker容器

作者:何宗諭 / 臺灣大學計算機及資訊網路中心程式設計組幹事

雲端時代的來臨,意味著我們不再需要追求高效能的家用主機,而傾向把複雜運算丟給雲端來處理,數據雲端化的趨勢,也加速雲端伺服器開發的需求。Docker從2013年發展出來,已成為當紅的虛擬化技術,其主要原因在於它輕量化的虛擬層級以及易於移植,有利於雲端系統的開發。虛擬的技術與虛擬主機,想必大家一定不陌生,至於什麼是Docker,什麼是虛擬容器,希望藉由本文能一探究竟,並期待將來能開發以Docker為平台的網路應用程式。


圖一 Docker官方標誌(https://www.docker.com/)

前言
想像小明是個資訊相關科系的大學生,為了維持生計,難免總是要去接一些外包的案子來過生活,假設來自客戶的需求是希望在Amazon Web Services (AWS)上用Ubuntu 14.04 開發一套網路伺服器,而他平常慣用的電腦是Windows系統(或者是Mac OS),難不成要去買一台新的電腦,然後安裝Ubuntu作業系統來開發案子?又或者有更簡單的方法,就是直接在他的Windows系統上安裝虛擬主機(Virtual Machine),有了虛擬化的技術,軟體相容性變得不再是問題。
假若小明又接了新的案子,這次是幫客戶修改既有的軟體,他看了看系統版本,環境是Ubuntu 10.04,雖然還是Ubuntu系統,但在10.04的軟體竟然無法在14.04上編譯,小明花費了大量工夫,才發現原來一些函式庫在新版的14.04上已更新並不支援舊版,於是他花了一周末重新編譯所需的函式庫,花了這麼多時間,卻還沒開始開發專案,所以知道下次遇到這種情形,直接安裝虛擬主機Ubuntu 10.04是最快的方法。然而隨著事業越作越大,他的電腦裡有著各式各樣不同的虛擬作業系統,Debian、Ubuntu、CentOS…等等幾十幾套不同版本的開發環境,很顯然他必需要去買一個新的硬碟來存放這些映像檔。而且遇到一個困難點,若要同時執行多個虛擬主機顯然會降低系統校能,難不成要在買一台新電腦嗎?
一台電腦最多可以執行十台虛擬主機就已經很勉強了,假若有人告訴小明,有一個新的虛擬技術,可以在一台主機上同時執行數百個不同的虛擬應用程式,而且彼此完全隔離,不就解決了現有的難題嗎? 傳統的虛擬主機技術是利用硬體的功能來模擬,而這套輕量的虛擬技術,一般習慣將它稱之為容器(Container),則是套透過作業系統(Linux為其原生),建立多個虛擬的實例(instances),有獨立的函式庫及獨立的shell,並彼此隔離。以下就以容器與虛擬主機作一個對照表。


表一 Docker容器與虛擬主機功能比較

Docker簡介
雲端時代的來臨,意味著我們不再需要追求高效能的家用主機,而傾向把複雜運算丟給雲端來處理,數據雲端化的趨勢,也加速雲端伺服器開發的需求。想像若一個開發者,在Amazon申請了AWS雲端服務,然後以LAMP(Linux、Apache、MySQL、PHP)建置其網路平台,即使是一個熟練的工程師,仍需花費不少時間在系統安裝與設定,才能讓手邊的原始碼在網路上執行。而當客戶需求改變時,有可能又要花時間將系統從AWS搬到微軟的Azure平台,這表示工程師又要花時間處理煩瑣的問題。假設在不同的平台上都安裝了Docker的應用程式,就可以將自己開發的程式用容器打包起來,快速移植到另一個平台。 如下圖所示,容器是一個映像檔(比如說CentOS 6.6)加上自己開發的應用程式,所組合成的架構,新的主機端只要安裝了相同的映像檔(CentOS 6.6)之後,就可以執行既有的應用程式。傳統上必需安裝幾GB大的虛擬主機,而在這個例子上,只要下載兩百多MB的映像檔即可以完成一樣的工作,這是傳統虛擬主機所無法比擬的地方。這邊出現了幾個關鍵字映像檔容器,之後會有更清楚的說明,這邊只要知道最重要的觀念就是,用Docker建置的軟體(又稱為容器),可以迅速的移植到不同平台,也就是Docker一直宣揚的精神 "Build, Ship, and Run Any App, Anywhere."


圖二 虛擬容器的搬移

Docker的支援與安裝
Docker是以Linux為其原生開發,所以在大部份的Linux系統上都可以安裝。但是Docker是在2013年發行初始版本,這意謂著若是要建構Docker開發平台,建議以較新的Linux系統為優先考量。而Windows 和Mac OS作業系統本身無法直接運行,所以要透過Boot2Docker來支援,有興趣的的讀者可以自行參考連結網址。不過對於Windows和Mac OS環境的開發者來說,建議還是先安裝Linux虛擬主機,再用此虛擬主機建置Docker平台,會簡化安裝流程(如下圖說明)。


圖三 虛擬容器的建議設置

以下簡述不同版本的安裝方式
1. Ubuntu 14.04系統:
 $ sudo apt-get update
 $ sudo apt-get install docker.io
 $ sudo ln –sf /usr/bin/docker.io /usr/local/bin/docker
2. Ubuntu 14.04以下的版本,要更新內核才能支援:
 $ sudo apt-get update
 $ sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
 $ sudo apt-get install docker.io
 $ sudo ln –sf /usr/bin/docker.io /usr/local/bin/docker
3. CentOS 7:
 $ sudo yum install docker
4. CentOS 6的版本以上的版本:
 $ sudo yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm
 $ sudo yum install docker-io
安裝好Docker後,用一個Hello World來測試是否安裝成功。
 $ docker run ubuntu:10.04 /bin/echo 'Hello world'


圖四 第一個Docker測試環境

其中docker run ubuntu:10.04 是指定一個特定版本的系統(10:04),然後執行其echo指令,這邊私人端的倉庫若沒有此10.04的映像檔,則會去公有倉庫抓這個版本的,並運行其指令,當然也可以試試看其它指令。
 $ docker run centos:6.6 /bin/ps


圖五 Docker執行程序(以PS指令)

使用ps 指令來觀察系統目前執行的程序,可見當安裝了Centos 6.6映像檔,僅載入最小的系統資源。
到目前為止,安裝了Docker系統後,就可以在平台上以最小資源運行其指令,不同版本的映像檔約幾百MB左右,當私有端沒有時,會從公有倉庫抓取所需的映像檔,當下次執行時,就可以重複使用。若想要觀察目前已安裝的映像檔(image),則可透過下列指令。如圖所示,可以看到已安裝映像檔,以及所佔的容量。
 $ sudo docker images


圖六 系統上的映像檔(image)

Docker的基本概念
剛剛筆者以一個簡單的安裝程序,瞭解Docker怎麼運行,但相信對大部份的讀者來說,其概念還是很模糊,所以接下來這節將介紹Docker的核心概念。主要有四個核心:
 Docker I/O
 倉庫Repository
 映像檔Image
 容器Container
在介紹這四個核心前,先花一點篇幅來介紹Docker與VM的差異性。如圖七所示:


圖七 Docker容器與虛擬機器的比較

Docker 僅載入所需要的函式庫與執行檔,而不像VM需要安裝大容量的作業系統。而這些函式庫與執行檔則被放在映像檔內,可以快速的從網上下載到私有端倉庫。
1. Docker I/O
任何系統要操作Docker的系統,就必需在作業系統上先安裝Docker,上一節筆者已簡單介紹如何安裝及使用。有了Docker I/O,就可以跟公有雲端進行互動,抓取所需的映像檔,跟VM不同的地方在於,VM是用硬體端的hypervisor技術來同時執行多個虛擬主機,一般可預見需要大量的運行資源。
Docker則是用軟體端的作業系統來實現虛擬分割的技術,由於僅載入核心的函式庫,所以跟VM不同的地方在於,可以同時執行數百個不同的應用容器,其原理不難理解,因為Linux平台本身就可以穩定的執行多個程序,而Docker則是套用Linux的技術,將每個容器當成一個實例(instance),彼此完全隔離,又可以依需求而互動。
2. 倉庫Repository
倉庫的概念就是發揮雲端的精神,將大量的資源存放在公有倉庫,而私有倉庫則存放常用的資源或者是自行開發的資源。這其實跟Linux的概念是很相似的,最大的不同點在於,Docker存放的是不同版本的作業系統映像檔。
舉例來說,開發者先在私人主機端利用Docker I/O安裝了映像檔Ubuntu 14.04,並在此環境上開發了應用軟體app1,而他預計將在雲端放上這套軟體app1。他所需要的工作就是在雲端上利用公有倉庫下載Ubuntu 14.04映像檔,接著就可以運行其app1,而不用在乎雲端伺服器是否與自己的主機相容。能精簡安裝的流程其關鍵就在於,映像檔本身是唯讀且不可更改,這樣才能確保在不同雲端平台,都有相同的系統環境,易於應用軟體的移植。目前最大的公有倉庫網址如下:https://hub.docker.com/
3. 映像檔Image
前面介紹了Docker與VM的不同,這邊的映像檔就可以想成是VM上的Guest OS,其差別在於映像檔僅包含最小可運行的系統,而且更重要的是映像檔本身是唯讀不可修改。
這邊可能會有疑惑,既然不能修改映像檔,那不就意味著不能修改環境?事實上還是可以,那是因為Docker本身提供了容器的架構讓使用者可以自行設定並修改,如果有需要,還可以自行建構成新的映像檔放在私有倉庫。而為了避免映像檔衝突,公有雲端為每個映像檔提供了獨有的ID(例如Ubuntu 14.04的ID = 8251da35e7a7),只有是同樣的ID就可以確保所下載的映像檔是官方所發行的,而不會跟私有的映像檔有所以衝突。
4. 容器Container
容器是利用映像檔所創造的實例(instance),一個映像檔可以創造出多個不同的容器,而且彼此隔離。容器就像是映像檔的可寫層,與維讀的映像檔組合成一個環境,便於開發所需的應用程式。因為容器是Docker最核心的技術,所以用以下的例子來說明:
新建一個容器,以ubuntu 14.04來建構
 $ sudo docker create –it ubuntu:14.04
查詢已建立的容器,初始會是停止狀態
 $ sudo docker ps –al
運行已建立的容器,輸入剛剛查詢的id,每台主機不一樣,請自行輸入
id可以輸入前幾碼即可
 $ sudo docker start -i “ID” 例如b6a0ac8b2ad1或者是b6a


圖八 利用標籤碼啟動Docker容器

停止容器
 $ sudo docker stop "ID"
匯出容器,就可以搬移到其它的主機上
 $ sudo docker export "ID" > test.tar
匯入容器成新的映像檔,即可儲存到本機倉庫中
 $ cat test.tar | sudo docker export - test/ubuntu:v1.0

結論
Docker從2013年發展出來,已成為當紅的虛擬化技術,其主要原因在於它輕量化的虛擬層級以及方便移植,有利於雲端系統的開發。尤其是現在的數位時代面臨了大數據的挑戰,虛擬化本身也面臨了系統資源的不夠問題,若能夠運用Docker的輕量化技術,在雲端實作大量的虛擬化主機,不在受限於成本的考量,這也是可以期待Docker未來的發展。

參考資料
[1] Docker 官網
https://www.docker.com/
[2] 10個Q&A快速認識Docker | iThome
http://www.ithome.com.tw/news/91847
[3] 門外漢的Docker 小試身手by caterpillar | CodeData
http://www.codedata.com.tw/social-coding/docker-layman-abc/
[4] Docker 入門與實戰
作者:楊保華, 戴王劍, 曹亞侖, ISBN:9789863476580