很多時候,當大家談論起docker,經常會提到docker作為容器解決方案,在虛擬化資源方面存在不小優勢。輕量級虛擬化技術的優點暫且不談,從軟體生命週期來看,docker在打包軟體、分發軟體方面的能力同樣出眾。而後者很大程度上依賴於docker的映象技術。
docker映象技術提供了一套標準,創造性地使用dockerfile來規範化docker化應用的製作流程,結果產生的docker映象便於傳輸與管理,最終通過docker映象執行docker容器,完成容器化應用的交付。
經過本系列對於docker映象的映象,大家應該已經清楚docker映象的儲存、以及docker映象的內容。docker映象的內容,應該說包含兩部分,除了映象層中的檔案之外,還包括一層映象的json檔案。映象層檔案的理解較為簡單,但是docker映象的json檔案理解起來就會稍顯複雜。本文就帶大家深入理解docker映象的json檔案。
我們一直提到「通過docker映象執行docker容器」,如果仔細思考這句話,可能依然會存在一些疑惑。不難的理解是:docker映象層中的檔案全部屬於靜態的磁碟檔案,而docker容器屬於乙個動態的產物,可以認為是乙個或者多個執行中的程序。那麼,靜態的docker映象轉換為動態的docker容器背後肯定會有一些不為人知的秘密。我們不妨帶著以下幾個問題來思考docker映象的json檔案:
1.如何判定乙個docker映象應該執行哪個程序,這部分資訊存在哪?
2.有了以上資訊,將docker映象執行成docker容器的行為是誰在主導?
這一次,我們依舊從動態
和靜態
這兩個詞來看docker映象的前世今生。首先,docker映象的映象層檔案屬於靜態檔案,當容器執行起來之後這部分內容將作為docker容器的檔案系統內容,提供docker容器的檔案系統視角。我們帶著這樣的觀點,再來看dockerfile的概念。
在dockerfile的原語中,大家肯定對env、volume、expose以及cmd等命令非常熟悉。
env mypath=/root
:env命令在構建docker映象時,為映象新增乙個環境變數,以便該環境變數在啟動docker容器時作用於容器內的程序;這部分資訊不應該以靜態檔案的形式被打入docker的映象層檔案。
volume /data
:volume命令在構建docker映象時,為映象新增乙個資料卷標識,以便通過該映象執行容器時為容器掛載乙個資料卷;由於構建時真實的資料卷還不存在,所以這部分資訊不應該以靜態檔案的形式被打入docker的映象層檔案。
expose 80
:expose命令在構建docker映象時,記錄容器內部實際監聽的埠,以便在通過bridge模式配置docker容器網路時,將該埠與宿主機進行一次dnat轉換;這部分資訊屬於docker容器執行時所需要的資訊,也不應該以靜態檔案的形式被打入docker的映象層檔案。
cmd ["./run.sh"]
:cmd命令在構建docker映象時,記錄啟動docker容器的執行命令入口,一般用以指定使用者的應用程式;這部分配置資訊更不應該以靜態檔案的形式被打入docker的映象層檔案。
dockerfile中以上舉例的4類命令,通過分析,我們得出初步的結論:dockerfile的部分命令各自包含一類動態資訊,這類資訊不屬於docker映象層中的檔案內容。
高移植性保障了docker映象的一次構建,多處執行
,那麼使得docker容器可以順利執行,docker自然不會拋棄構建docker映象時的動態內容。因此,動態內容的儲存就顯得尤為重要。
此時就是docker映象json檔案
登場的時機。構建docker映象時,所有動態的資訊都會會記錄進相應docker映象的json檔案中。
需要注意的是,雖然映象的動態資訊會被儲存於docker映象的json檔案中,但是並不代表json檔案中僅儲存動態資訊,dockerfile構建過程中,機會所有的操作都會會記錄在json檔案中
.
有了docker映象json檔案來描述docker容器的動態資訊,那麼json檔案作為docker映象的一部分,在docker體系中,由哪一模組來完成json檔案中動態資訊的解析與執行呢?
如果大家清楚「每乙個docker容器都是docker daemon的子程序」的話,肯定會聯想到docker daemon。答案正是docker daemon。站在啟動容器的角度上,docker daemon的作用就是以下兩點:
1.將docker映象的映象層檔案作為docker容器的rootfs。
2.提取docker映象json檔案中的動態檔案,確定啟動程序,並為之配置動態執行環境。
docker daemon、docker映象以及docker容器三者的簡單示意圖如下:
通過上圖,我們可以使用ubuntu:14.04映象執行docker容器時,前者的映象層layer內容將作為容器的rootfs;而前者的json檔案,會由docker daemon解析,並提取出其中的容器執行入口cmd資訊,以及容器程序的環境變數env資訊,最終初始化容器程序。當然,容器程序的執行入口**於映象提供的rootfs。假如此時ubuntu 14.04映象的json檔案中又含有volume資訊,那麼docker daemon將會為docker容器在宿主機上建立乙個檔案目錄,並掛載到容器內部,實現映象中volume動態資訊的運用,其他動態資訊的運用也大同小異。
全文分析至此,還是更多的從理論的角度闡述docker映象的json檔案,那麼現實情況中,此類json檔案到底存的內容是什麼呢?我們依然以ubuntu:14.04為例,揭開docker映象json檔案的這面目。
乙個含有標籤的docker映象一般會有乙個或者多個層級映象組合而成,而每個映象層都會含有乙個json檔案。上圖中,我們展現了ubuntu:14.04映象中4個映象層的具體情況,特別分析了映象8251da35e7a7
和e5855facec0b
。通過檢視這兩個映象的json檔案,我們可以發現,兩個json檔案中的config屬性中,除了理所應當不同的映象id之外,只有cmd屬性不同。由於映象e5855facec0b
是映象8251da35e7a7
的父映象,同時構建子映象的時候使用的dockerfile命令為cmd ["/bin/bash"]
,因此子映象在父映象json檔案的基礎上,更新config屬性中的cmd屬性,完成自身json檔案的生成。docker映象中父子映象的json檔案有很大的相似性,子映象僅在父映象json檔案的基礎上,修改執行自身對應的dockerfile命令後造成的差異。
映象構建完畢,docker映象的映象層layer檔案以及json檔案均準備完畢,那麼當docker daemon通過此ubuntu:14.04映象執行docker容器時,首先提取最上層映象的json檔案,找到config屬性中的cmd命令,並在映象層檔案構成的容器rootfs中找到相應的執行程式,最終執行,完成容器的啟動。(實際情況要更複雜,會涉及entrypoint以及cmd兩部分的內容,本系列後續會深入深入兩者的作用與區別)
當然,除了cmd之外,json檔案的config 屬性中同時還存在user、exposedports、entrypoint、networkdisabled等一系列啟動容器時所需的動態資訊。
docker映象的json檔案扮演極其重要的角色,提供了靜態映象向動態容器的轉化依據,同時清晰地記錄了父子映象之間的差異,基於此差異,後續docker構建的cache機制才得以實現。
深入理解docker的link機制
同乙個宿主機上的多個docker容器之間如果想進行通訊,可以通過使用容器的ip位址來通訊,也可以通過宿主機的ip加上容器暴露出的埠號來通訊,前者會導致ip位址的硬編碼,不方便遷移,並且容器重啟後ip位址會改變,除非使用固定的ip,後者的通訊方式比較單一,只能依靠監聽在暴露出的埠的程序來進行有限的通訊...
深入理解docker的link機制
摘要 什麼是docker的link機制 同乙個宿主機上的多個docker容器之間如果想進行通訊,可以通過使用容器的ip位址來通訊,也可以通過宿主機的ip加上容器暴露出的埠號來通訊,前者會導致ip位址的硬編碼,不方便遷移,並且容器重啟後ip位址會改變,除非使用固定的ip,後者的通訊方式比較單一,只能依...
深入理解C語言 深入理解指標
關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...