做者| 阿里巴巴高級開發工程師 傅偉golang
在介紹容器的具體概念以前,先簡單回顧一下操做系統是如何管理進程的。docker
首先,當咱們登陸到操做系統以後,能夠經過 ps 等操做看到各式各樣的進程,這些進程包括系統自帶的服務和用戶的應用進程。那麼,這些進程都有什麼樣的特色?網絡
這樣的三個特色會帶來什麼問題呢?架構
針對上述的三個問題,如何爲進程提供一個獨立的運行環境呢?運維
那麼,應該如何定義這樣的進程集合呢?工具
其實,**容器就是一個視圖隔離、資源可限制、獨立文件系統的進程集合。**所謂「視圖隔離」就是可以看到部分進程以及具備獨立的主機名等;控制資源使用率則是能夠對於內存大小以及 CPU 使用個數等進行限制。容器就是一個進程集合,它將系統的其餘資源隔離開來,具備本身獨立的資源視圖。測試
容器具備一個獨立的文件系統,由於使用的是系統的資源,因此在獨立的文件系統內不須要具有內核相關的代碼或者工具,咱們只須要提供容器所需的二進制文件、配置文件以及依賴便可。只要容器運行時所需的文件集合都可以具有,那麼這個容器就可以運行起來。ui
綜上所述,咱們將這些容器運行時所須要的全部的文件集合稱之爲容器鏡像。spa
那麼,通常都是經過什麼樣的方式來構建鏡像的呢?一般狀況下,咱們會採用 Dockerfile 來構建鏡像,這是由於 Dockerfile 提供了很是便利的語法糖,可以幫助咱們很好地描述構建的每一個步驟。固然,每一個構建步驟都會對已有的文件系統進行操做,這樣就會帶來文件系統內容的變化,咱們將這些變化稱之爲 changeset。當咱們把構建步驟所產生的變化依次做用到一個空文件夾上,就可以獲得一個完整的鏡像。 changeset 的分層以及複用特色可以帶來幾點優點:操作系統
以下圖所示的 Dockerfile 適用於描述如何構建 golang 應用的。
如圖所示:
當有了 Dockerfile 以後,就能夠經過 docker build 命令構建出所須要的應用。構建出的結果存儲在本地,通常狀況下,鏡像構建會在打包機或者其餘的隔離環境下完成。
那麼,這些鏡像如何運行在生產環境或者測試環境上呢?這時候就須要一箇中轉站或者中心存儲,咱們稱之爲 docker registry,也就是鏡像倉庫,其負責存儲全部產生的鏡像數據。咱們只須要經過 docker push 就可以將本地鏡像推進到鏡像倉庫中,這樣一來,就可以在生產環境上或者測試環境上將相應的數據下載下來並運行了。
運行一個容器通常狀況下分爲三步:
簡單回顧一下,容器就是和系統其它部分隔離開來的進程集合,這裏的其餘部分包括進程、網絡資源以及文件系統等。而鏡像就是容器所須要的全部文件集合,其具有一次構建、處處運行的特色。
容器是一組具備隔離特性的進程集合,在使用 docker run 的時候會選擇一個鏡像來提供獨立的文件系統並指定相應的運行程序。這裏指定的運行程序稱之爲 initial 進程,這個 initial 進程啓動的時候,容器也會隨之啓動,當 initial 進程退出的時候,容器也會隨之退出。
所以,能夠認爲容器的生命週期和 initial 進程的生命週期是一致的。固然,由於容器內不僅有這樣的一個 initial 進程,initial 進程自己也能夠產生其餘的子進程或者經過 docker exec 產生出來的運維操做,也屬於 initial 進程管理的範圍內。當 initial 進程退出的時候,全部的子進程也會隨之退出,這樣也是爲了防止資源的泄漏。 可是這樣的作法也會存在一些問題,首先應用裏面的程序每每是有狀態的,其可能會產生一些重要的數據,當一個容器退出被刪除以後,數據也就會丟失了,這對於應用方而言是不能接受的,因此須要將容器所產生出來的重要數據持久化下來。容器可以直接將數據持久化到指定的目錄上,這個目錄就稱之爲數據卷。
數據卷有一些特色,其中很是明顯的就是數據卷的生命週期是獨立於容器的生命週期的,也就是說容器的建立、運行、中止、刪除等操做都和數據卷沒有任何關係,由於它是一個特殊的目錄,是用於幫助容器進行持久化的。簡單而言,咱們會將數據卷掛載到容器內,這樣一來容器就可以將數據寫入到相應的目錄裏面了,並且容器的退出並不會致使數據的丟失。
一般狀況下,數據卷管理主要有兩種方式:
moby 是目前最流行的容器管理引擎,moby daemon 會對上提供有關於容器、鏡像、網絡以及 Volume的管理。moby daemon 所依賴的最重要的組件就是 containerd,containerd 是一個容器運行時管理引擎,其獨立於 moby daemon ,能夠對上提供容器、鏡像的相關管理。
containerd 底層有 containerd shim 模塊,其相似於一個守護進程,這樣設計的緣由有幾點:
本節課程只是針對於 moby 進行一個大體的介紹,在後續的課程也會詳細介紹。
VM 利用 Hypervisor 虛擬化技術來模擬 CPU、內存等硬件資源,這樣就能夠在宿主機上創建一個 Guest OS,這是常說的安裝一個虛擬機。
每個 Guest OS 都有一個獨立的內核,好比 Ubuntu、CentOS 甚至是 Windows 等,在這樣的 Guest OS 之下,每一個應用都是相互獨立的,VM 能夠提供一個更好的隔離效果。但這樣的隔離效果須要付出必定的代價,由於須要把一部分的計算資源交給虛擬化,這樣就很難充分利用現有的計算資源,而且每一個 Guest OS 都須要佔用大量的磁盤空間,好比 Windows 操做系統的安裝須要 10~30G 的磁盤空間,Ubuntu 也須要 5~6G,同時這樣的方式啓動很慢。正是由於虛擬機技術的缺點,催生出了容器技術。 容器是針對於進程而言的,所以無需 Guest OS,只須要一個獨立的文件系統提供其所須要文件集合便可。全部的文件隔離都是進程級別的,所以啓動時間快於 VM,而且所需的磁盤空間也小於 VM。固然了,進程級別的隔離並無想象中的那麼好,隔離效果相比 VM 要差不少。
整體而言,容器和 VM 相比,各有優劣,所以容器技術也在向着強隔離方向發展。