一探 Docker 鏡像的究竟

一. 引入

咱們常常拿 Docker 容器與虛擬機做對比,Dokcer 容器跟虛擬機的不一樣之處在於,在使用 Docker 的時候,實質上並無生成一個真實存在的「容器」。Docker 幫助用戶啓動的,其實就是應用自己,只不過在建立這些進程時,Docker 爲它們加上重重限制。包括啓用 Namespace 配置對容器之間進行隔離,以及設置指定的 Cgroups 參數來爲進程設置資源限制等。框架

固然,僅僅是這樣還不夠,既然一個宿主機能夠存在多個容器且它們之間又是隔離的,那它們的文件系統是怎麼樣的呢,這就關乎到一個重要角色,使 Docker 被大衆接受的關鍵——Docker 鏡像。spa

二. 文件系統的隔離

首先,咱們天然會想到,容器裏的應用進程,看到的理應是一份徹底獨立的文件系統。由於只有這樣,容器在操做本身的文件目錄時纔不會影響到宿主機以及其餘的容器。操作系統

在 Linux 中,有一個概念叫作 Mount Namespace,它提供了文件系統的隔離,經過隔離文件系統掛載點來實現。而 Dokcer 正是利用了這個爲各個容器提供了文件系統隔離。Docker 在容器進程啓動以前,就會對它整個根目錄 「/」 從新掛載,所以對於容器來講,本身使用的就是一個徹底獨立的文件系統。進程

固然,僅僅是這樣還不夠,總不能讓容器的文件系統都空空蕩蕩的吧。所以除了隔離各個容器自己的文件系統,Docker 還會在容器的根目錄下掛載一個完整的操做系統的文件系統,好比 Ubuntu。這樣該容器根目錄下的內容,就是 Ubuntu 的全部目錄和文件了,也就是咱們無比熟悉的 /bin, /etc, /data, /usr 等資源

而這個掛載在容器根目錄、用來爲容器進程提供隔離後執行環境的文件系統,就是所謂的容器鏡像。開發

鏡像與操做系統

既然一個鏡像包含了一個操做系統的文件,配置,目錄等,那它是否是就是一個操做系統了呢?部署

答案爲否,由於鏡像不包含操做系統的內核,而一臺宿主機上的全部容器,其實都是共享當前所在機器的操做系統內核。這也是容器相比虛擬機,所呈現出來的一個缺點,當咱們在操做容器內的應用的時候,特別是與內核進行交互的時候,須要注意咱們是直接地影響了宿主機的操做系統內核,所以須要格外當心。虛擬機

三. 爲何咱們須要鏡像

咱們都知道鏡像是 Docker 一個很是重要的特性,那麼咱們爲何須要鏡像呢?class

1. 解決環境一致性問題

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

而 Docker 鏡像的出現,完全改變了這種情況,正如前面所說的,鏡像不僅是包含了應用所需的語言,框架等環境,而是直接囊括了整個操做系統的文件系統,達到了本地環境和雲端環境的高度一致的目的。而開發者們要作的,只是建立一個容器,並讓鏡像在這個容器中運行便可。

也就是說,鏡像達成了操做系統級別的運行環境一致性,化解了本地開發與遠端環境之間的差別問題。

2. 分層機制

在實際的開發中,若是咱們每開發一個應用或者在現有應用中作一些改動,都須要從新去構建一個鏡像,那麼這也是一個比較麻煩的事情。

所以 Docker 鏡像採用了一種比較創新的方式,就是引入層的概念。既然咱們但願避免每作一些改動都保存一個鏡像,那就利用一種增量的思想,去維護增量的內容。也就是說,用戶製做鏡像的每一步操做,都會生成一個層。

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

分層機制帶來的好處也影響了 Docker 後面的發展,在 17.05 版本以後,Docker 引入 Dockerfile 多階段構建機制,使得鏡像的體積可以大幅度下降。

相關文章
相關標籤/搜索