1. 程式人生 > 程式設計 >一探 Docker 映象的究竟

一探 Docker 映象的究竟

一. 引入

我們經常拿 Docker 容器與虛擬機器器作對比,Dokcer 容器跟虛擬機器器的不同之處在於,在使用 Docker 的時候,實質上並沒有生成一個真實存在的“容器”。Docker 幫助使用者啟動的,其實就是應用本身,只不過在建立這些程式時,Docker 為它們加上重重限制。包括啟用 Namespace 配置對容器之間進行隔離,以及設定指定的 Cgroups 引數來為程式設定資源限制等。

當然,僅僅是這樣還不夠,既然一個宿主機可以存在多個容器且它們之間又是隔離的,那它們的檔案系統是怎麼樣的呢,這就關乎到一個重要角色,使 Docker 被大眾接受的關鍵——Docker 映象。

二. 檔案系統的隔離

首先,我們自然會想到,容器裡的應用程式,看到的理應是一份完全獨立的檔案系統。因為只有這樣,容器在操作自己的檔案目錄時才不會影響到宿主機以及其他的容器。

在 Linux 中,有一個概念叫做 Mount Namespace,它提供了檔案系統的隔離,通過隔離檔案系統掛載點來實現。而 Dokcer 正是利用了這個為各個容器提供了檔案系統隔離。Docker 在容器程式啟動之前,就會對它整個根目錄 “/” 重新掛載,因此對於容器來說,自己使用的就是一個完全獨立的檔案系統。

當然,僅僅是這樣還不夠,總不能讓容器的檔案系統都空空蕩蕩的吧。因此除了隔離各個容器本身的檔案系統,Docker 還會在容器的根目錄下掛載一個完整的作業系統的檔案系統,比如 Ubuntu。這樣該容器根目錄下的內容,就是 Ubuntu 的所有目錄和檔案了,也就是我們無比熟悉的 /bin,/etc,/data,/usr 等

而這個掛載在容器根目錄、用來為容器程式提供隔離後執行環境的檔案系統,就是所謂的容器映象。

映象與作業系統

既然一個映象包含了一個作業系統的檔案,配置,目錄等,那它是不是就是一個作業系統了呢?

答案為否,因為映象不包含作業系統的核心,而一臺宿主機上的所有容器,其實都是共享當前所在機器的作業系統核心。這也是容器相比虛擬機器器,所呈現出來的一個缺點,當我們在操作容器內的應用的時候,特別是與核心進行互動的時候,需要注意我們是直接地影響了宿主機的作業系統核心,因此需要格外小心。

三. 為什麼我們需要映象

我們都知道映象是 Docker 一個非常重要的特性,那麼我們為什麼需要映象呢?

1. 解決環境一致性問題

在容器發展初期,使用者在使用容器平臺向叢集部署應用的時候,通常需要進行一個打包的操作,不同於 Docker 簡單的映象構建操作,在那個時候,開發者們必須為每種語言、每種框架,甚至每個版本的應用都維護一個打好的包,同時由於上雲後環境的不同,還需要做許多配置工作。

而 Docker 映象的出現,徹底改變了這種狀況,正如前面所說的,映象不只是包含了應用所需的語言,框架等環境,而是直接囊括了整個作業系統的檔案系統,達到了本地環境和雲端環境的高度一致的目的。而開發者們要做的,只是建立一個容器,並讓映象在這個容器中執行即可。

也就是說,映象達成了作業系統級別的執行環境一致性,化解了本地開發與遠端環境之間的差異問題。

2. 分層機制

在實際的開發中,如果我們每開發一個應用或者在現有應用中做一些改動,都需要重新去構建一個映象,那麼這也是一個比較麻煩的事情。

因此 Docker 映象採用了一種比較創新的方式,就是引入層的概念。既然我們希望避免每做一些改動都儲存一個映象,那就利用一種增量的思想,去維護增量的內容。也就是說,使用者製作映象的每一步操作,都會生成一個層。

比方說在 Dockerfile 中,大多數指令都會生成一個層,最終完成的映象實際上是一層一層地疊加起來的。與此同時,層之間又是可以共享的,假設本地擁有一個五層的映象 A,而 A 映象和 B 映象共享了前面的五層,則當我們從映象倉庫中拉取 B 映象時,只拉取本地所沒有的最後一層就可以了,而不需要把整個 B 映象連根拉一遍。

分層機制帶來的好處也影響了 Docker 後面的發展,在 17.05 版本之後,Docker 引入 Dockerfile 多階段構建機制,使得映象的體積能夠大幅度降低。