Docker 鏡像原理

聯合文件系統

鏡像是什麼

鏡像是一種輕量級、可執行的獨立軟件包,用來打包軟件運行環境和基於運行環境開發的軟件,它包含 運行某個軟件所需的所有內容,包括代碼、運行時、庫、環境變量和配置文件

鏡像加載的原理

UnionFS (聯合文件系統)

UnionFS(聯合文件系統):Union文件系統(UnionFS)是一種分層、輕量級並且高性能的文件系統, 它支持對文件系統的修改作爲一次提交來一層層的疊加,同時可以將不同目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)。Union 文件系統是 Docker 鏡像的基 礎。鏡像可以通過分層來進行繼承,基於基礎鏡像(沒有父鏡像),可以製作各種具體的應用鏡像。 特性:一次同時加載多個文件系統,但從外面看起來,只能看到一個文件系統,聯合加載會把各層文件 系統疊加起來,這樣最終的文件系統會包含所有底層的文件和目錄

Docker鏡像加載原理

docker的鏡像實際上由一層一層的文件系統組成,這種層級的文件系統UnionFS。

bootfs(boot file system 引導加載)主要包含bootloader 和 kernel,bootloader主要是引導加載kernel,Linux剛啓動時會加載bootfs文件系統,在Docker鏡像的最底層是bootfs。這一層與我們典型的Linux/Unix系統是 一樣的,包含boot加載器和內核。當boot加載完成之後整個內核就都在內存中了,此時內存的使用權已由bootfs轉交給內核,此時系統也會卸載bootfs。

rootfs (root file system ) ,在bootfs之上。包含的就是典型 Linux 系統中的 /dev,/proc, /bin, /etc 等標準目錄和文件。rootfs就是各種不同的操作系統發行版,比如Ubuntu,Centos等等。

平時我們安裝進虛擬機的CentOS都是好幾個G,爲什麼Docker這裏才200M?

對於一個精簡的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序庫就可以了,因爲底層直 接用Host的kernel(內核使用主機的,命令使用容器的),自己只需要提供rootfs就可以了。由此可見對於不同的linux發行版, bootfs基本是一 致的, rootfs會有差別, 因此不同的發行版可以公用bootfs。

分層理解

分層的鏡像

我們可以去下載一個鏡像,注意觀察下載的日誌輸出,可以看到是一層一層的在下載!

思考:爲什麼Docker鏡像要採用這種分層的結構呢?

最大的好處,我覺得莫過於是資源共享了!比如有多個鏡像都從相同的Base鏡像構建而來,那麼宿主機只需在磁盤上保留一份base鏡像,同時內存中也只需要加載一份base鏡像,這樣就可以爲所有的容器服務了,而且鏡像的每一層都可以被共享

查看鏡像分層的方式可以通過 docker image inspect 命令

[root@xiaoyequ ~]# docker image inspect redis:latest
[
    #......
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:13cb14c2acd34e45446a50af25cb05095a17624678dbafbcc9e26086547c1d74",
                "sha256:e6b49c7dcaac7a2ec2acc379da5f5b1bcc6a5d3badd72814fe945296216557bd",
                "sha256:cdaf0fb0082b74223a224c39c2d2ea886c32f53b7e1d5b872d5354aae0df56b8",
                "sha256:72d3a7e6fe022824ee2f852ca132030e22c644fbaf8287f4ea8044268abe40b7",
                "sha256:67c707dbd847d8310d3b988c3e3d9d9eb53387ede0de472e36a15abbcb6c719c",
                "sha256:7b9c5be81844318508f57a5b0574822dabaaed3dc25ee35d960feec3a9e941c4"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解 

所有的 Docker 鏡像都起始於一個基礎鏡像層,當進行修改或增加新的內容時,就會在當前鏡像層之 上,創建新的鏡像層。 舉一個簡單的例子,假如基於 Ubuntu Linux 16.04 創建一個新的鏡像,這就是新鏡像的第一層;如果 在該鏡像中添加 Python包,就會在基礎鏡像層之上創建第二個鏡像層;如果繼續添加一個安全補丁,就 會創建第三個鏡像層。 該鏡像當前已經包含 3 個鏡像層,如下圖所示(這只是一個用於演示的很簡單的例子)。

在添加額外的鏡像層的同時,鏡像始終保持是當前所有鏡像的組合,理解這一點非常重要。下圖中舉了 一個簡單的例子,每個鏡像層包含 3 個文件,而鏡像包含了來自兩個鏡像層的 6 個文件。

上圖中的鏡像層跟之前圖中的略有區別,主要目的是便於展示文件。 下圖中展示了一個稍微複雜的三層鏡像,在外部看來整個鏡像只有 6 個文件,這是因爲最上層中的文件 7 是文件 5 的一個更新版本。

這種情況下,上層鏡像層中的文件覆蓋了底層鏡像層中的文件。這樣就使得文件的更新版本作爲一個新 鏡像層添加到鏡像當中。

Docker 通過存儲引擎(新版本採用快照機制)的方式來實現鏡像層堆棧,並保證多鏡像層對外展示爲統 一的文件系統。

Linux 上可用的存儲引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顧名思義,每種存儲 引擎都基於 Linux 中對應的文件系統或者塊設備技術,並且每種存儲引擎都有其獨有的性能特點。

Docker 在 Windows 上僅支持 windowsfilter 一種存儲引擎,該引擎基於 NTFS 文件系統之上實現了分 層和 CoW[1]。

下圖展示了與系統顯示相同的三層鏡像。所有鏡像層堆疊併合並,對外提供統一的視圖。

特點

Docker鏡像都是隻讀的,當容器啓動時,一個新的可寫層被加載到鏡像的頂部! 這一層就是我們通常說的容器層,容器之下的都叫鏡像層!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章