Dockerfile 是軟件的原材料,Docker 鏡像是軟件的交付品,而 Docker 容器則能夠認爲是軟件的運行態。從應用軟件的角度來看,Dockerfile、Docker 鏡像與 Docker 容器分別表明軟件的三個不一樣階段,Dockerfile 面向開發,Docker 鏡像成爲交付標準,Docker 容器則涉及部署與運維,三者缺一不可,協力充當 Docker 體系的基石。json
簡單來說,Dockerfile構建出Docker鏡像,經過Docker鏡像運行Docker容器。ubuntu
咱們能夠從Docker容器的角度,來反推三者的關係。首先能夠來看下圖:網絡
咱們假設這個容器的鏡像經過如下Dockerfile構建而得:運維
FROM ubuntu:14.04 ADD run.sh / VOLUME /data CMD ["./run.sh"]
首先,咱們結合上圖來看看Dockerfile與Docker鏡像之間的關係。spa
FROM ubuntu:14.04:設置基礎鏡像,此時會使用基礎鏡像 ubuntu:14.04 的全部鏡像層,爲簡單起見,圖中將其做爲一個總體展現。設計
ADD run.sh /:將 Dockerfile 所在目錄的文件 run.sh 加至鏡像的根目錄,此時新一層的鏡像只有一項內容,即根目錄下的 run.sh。code
VOLUME /data:設定鏡像的 VOLUME,此 VOLUME 在容器內部的路徑爲 /data。須要注意的是,此時並未在新一層的鏡像中添加任何文件,即構建出的磁層鏡像中文件爲空,但更新了鏡像的 json 文件,以便經過此鏡像啓動容器時獲取這方面的信息。orm
CMD ["./run.sh"]:設置鏡像的默認執行入口,此命令一樣不會在新建鏡像中添加任何文件,僅僅在上一層鏡像 json 文件的基礎上更新新建鏡像的 json 文件。進程
所以,經過以上分析,以上的Dockerfile能夠構建出一個新的鏡像,包含4個鏡像層,每一條命令會和一個鏡像層對應,鏡像之間會存在父子關係。圖中很清楚的代表了這些關係。內存
Docker鏡像是Docker容器運行的基礎,沒有Docker鏡像,就不可能有Docker容器,這也是Docker的設計原則之一。
能夠理解的是:Docker鏡像畢竟是鏡像,屬於靜態的內容;而Docker容器就不同了,容器屬於動態的內容。動態的內容,你們很容易聯想到進程,內存,CPU等之類的東西。的確,Docker容器做爲動態的內容,都會包含這些。
爲了便於理解,你們能夠把Docker容器,理解爲一個或多個運行進程,而這些運行進程將佔有相應的內存,相應的CPU計算資源,相應的虛擬網絡設備以及相應的文件系統資源。而Docker容器所佔用的文件系統資源,則經過Docker鏡像的鏡像層文件來提供。
那麼做爲靜態的鏡像,如何纔有能力轉化爲一個動態的Docker容器呢?此時,咱們能夠想象:第一,轉化的依據是什麼;第二,由誰來執行這個轉化操做。
其實,轉化的依據是每一個鏡像的json文件,Docker能夠經過解析Docker鏡像的json的文件,獲知應該在這個鏡像之上運行什麼樣的進程,應該爲進程配置怎麼樣的環境變量,此時也就實現了靜態向動態的轉變。
誰來執行這個轉化工做?答案是Docker守護進程。也許你們早就理解這樣一句 話:Docker容器實質上就是一個或者多個進程,而容器的父進程就是Docker守護進程。這樣的,轉化工做的執行就不難理解了:Docker守護進程 手握Docker鏡像的json文件,爲容器配置相應的環境,並真正運行Docker鏡像所指定的進程,完成Docker容器的真正建立。
Docker容器運行起來以後,Docker鏡像json文件就失去做用了。此時Docker鏡像的絕大部分做用就是:爲Docker容器提供一個文件系統的視角,供容器內部的進程訪問文件資源。
再次回到上圖,咱們再來看看容器和鏡像之間的一些特殊關係。首先,以前已經說起Docker鏡像是分層管理的,管理Docker容器的時候,Docker鏡像仍然是分層管理的。因爲此時動態的容器中已經存在進程,進程就會對文件系統視角內的文件進行讀寫操做,所以,就會涉及一個問題:容器是否會篡改Docker鏡像的內容?
答案天然是不會的。統一來說,正如上圖,全部的Docker鏡像層對於容器來講,都是隻讀的,容器對於文件的寫操做絕對不會做用在鏡像中。
既然如此,實現的原理就很重要,究其根本:Docker守護進程會在Docker鏡像的 最上層之上,再添加一個可讀寫層,容器全部的寫操做都會做用到這一層中。而若是Docker容器須要寫底層Docker鏡像中的文件,那麼此時就會涉及一 個叫Copy-on-Write的機制,即aufs等聯合文件系統保證:首先將此文件從Docker鏡像層中拷貝至最上層的可讀寫層,而後容器進程再對讀 寫層中的副本進行寫操縱。對於容器進程來說,它只能看到最上層的文件。
那最後咱們再來講說:Docker容器的文件系統視角中,究竟是不是存在一些內容,不是存儲於Docker鏡像中的?
此次的答案依舊是確定的。
再次重申一點,Docker鏡像中存儲的都是一些靜態文件。這些文件原則上應該和容器具體信息以及主機信息徹底解藕。那麼Docker容器中不存在Docker鏡像中的內容主要有如下幾點:
1./proc以及/sys等虛擬文件系統的內容
2.容器的hosts文件,hostname文件以及resolv.conf文件,這些事具體環境的信息,原則上的確不該該被打入鏡像。
3.容器的Volume路徑,這部分的視角來源於從宿主機上掛載到容器內部的路徑
4.部分的設備文件