jsp網(wǎng)站開(kāi)發(fā)教學(xué)上海培訓(xùn)機(jī)構(gòu)有哪些
前面我們知道了容器是通過(guò)對(duì)一個(gè)普通的linux進(jìn)程進(jìn)行隔離和限制實(shí)現(xiàn)的一種特殊視角下的進(jìn)程表現(xiàn)。而隔離和限制的實(shí)現(xiàn)技術(shù)分別是"Namespace"和“Cgroups”,在這兩種機(jī)制的控制下,我們需要知道容器的本質(zhì)是一種特殊的進(jìn)程。
我們現(xiàn)在有了這個(gè)認(rèn)知之后,我們?cè)賮?lái)思考一個(gè)問(wèn)題,容器在自己的進(jìn)程視角下看到了一堆自己控制下的資源,那么他看到的文件系統(tǒng)又是啥樣的呢?
我們很自然就想到,這其實(shí)和容器的Mount Namespace的問(wèn)題,我們理解中,在容器內(nèi)部,通過(guò)限制,容器進(jìn)程看到的是完全獨(dú)立的文件系統(tǒng),這樣它就能在自己的容器目錄下進(jìn)行操作,而不用受到宿主機(jī)或者其他容器進(jìn)程的影響。也就是說(shuō)他是不是實(shí)現(xiàn)了文件系統(tǒng)級(jí)別的限制。
一、限制之下文件系統(tǒng)的表現(xiàn)
實(shí)際上我們上面說(shuō)的不是對(duì)的,即便你開(kāi)啟了Mount Namespace,容器進(jìn)程看到的文件系統(tǒng)和宿主機(jī)的文件系統(tǒng)是一模一樣的。
這句話的意思就是實(shí)際上文件系統(tǒng)層面實(shí)際上沒(méi)發(fā)生任何隔離和限制,Mount Namespace修改的是容器進(jìn)程對(duì)于文件系統(tǒng)掛載點(diǎn)的認(rèn)知,也就是說(shuō)只有掛載這個(gè)操作發(fā)生之后,進(jìn)程的視圖才會(huì)改變,在這之前,新創(chuàng)建的容器只會(huì)直接繼承宿主機(jī)的各個(gè)掛載點(diǎn)。
換言之就是說(shuō)我們需要在容器進(jìn)程中先掛載對(duì)應(yīng)的文件目錄,然后你的Mount Namespace才有效果。
這就是Mount Namespace和其他Namespace的使用略有不同,他對(duì)于容器進(jìn)程視圖的改變,一定是伴隨掛載操作mount才能生效。
但是在用戶視角下,我們希望的是上手就操作,屏蔽后面多的這一步,我們就希望創(chuàng)建一個(gè)新的容器的時(shí)候,創(chuàng)建好了就完事了,不用我們自己去做掛載這一步。所以我們可以在容器進(jìn)程啟動(dòng)之前重新掛載容器的整個(gè)根目錄 / 即可,然后進(jìn)行Mount Namespace,那么這個(gè)掛載就對(duì)其他容器和宿主機(jī)都是不可見(jiàn)的了。
在Linux操作系統(tǒng)中,有一個(gè)名為chroot的命令就可以實(shí)現(xiàn)這個(gè)能力,他的全稱是"change root file system",翻譯過(guò)來(lái)就是改變進(jìn)程的根目錄到你指定的位置。
二、chroot
我們來(lái)實(shí)際操作一下來(lái)使用一下這個(gè)命令。
假設(shè)我們現(xiàn)在有一個(gè)$HOME/test目錄,也就是家目錄下的test目錄,我們想要把他作為一個(gè)/bin/bash進(jìn)程的根目錄。
1、首先,創(chuàng)建一個(gè)test目錄和幾個(gè)lib文件夾
T=$HOME/test
mkdir -p $HOME/test
mkdir -p $HOME/test/{bin,lib64,lib}
cd $T
2、然后,把 bash 命令拷貝到 test 目錄對(duì)應(yīng)的 bin 路徑下:
# 此時(shí)就把bin下面的bash 和 ls拷貝到了家目錄下的test下的bin下面,
# 后面我們進(jìn)程掛載到這個(gè)test/bin下面就能直接使用bash和ls了
cp -v /bin/{bash,ls} $HOME/test/bin
3、接下來(lái),把 bash 命令需要的所有 so 文件,也拷貝到 test 目錄對(duì)應(yīng)的 lib64 路徑下。找到 so 文件可以用 ldd 命令:
T=$HOME/test
list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
for i in $list; do cp -v "$i" "${T}${i}"; done
4、最后,執(zhí)行 chroot 命令,告訴操作系統(tǒng),我們將使用 $HOME/test 目錄作為 /bin/bash 進(jìn)程的根目錄:此時(shí)就實(shí)現(xiàn)了這個(gè)掛載
chroot $HOME/test /bin/bash
這時(shí),你如果執(zhí)行 “l(fā)s /”,就會(huì)看到,它返回的都是 $HOME/test 目錄下面的內(nèi)容,而不是宿主機(jī)的內(nèi)容。更重要的是,對(duì)于被 chroot 的進(jìn)程來(lái)說(shuō),它并不會(huì)感受到自己的根目錄已經(jīng)被“修改”成 $HOME/test 了。這種視圖被修改的原理,和之前介紹的 Linux Namespace 很類似,實(shí)際上,Mount Namespace 正是基于對(duì) chroot 的不斷改良才被發(fā)明出來(lái)的,它也是 Linux 操作系統(tǒng)里的第一個(gè) Namespace。
當(dāng)然,為了能夠讓容器的這個(gè)根目錄看起來(lái)更“真實(shí)”,我們一般會(huì)在這個(gè)容器的根目錄下掛載一個(gè)完整操作系統(tǒng)的文件系統(tǒng),比如 Ubuntu16.04 的 ISO。這樣,在容器啟動(dòng)之后,我們?cè)谌萜骼锿ㄟ^(guò)執(zhí)行 “l(fā)s /” 查看根目錄下的內(nèi)容,就是 Ubuntu 16.04 的所有目錄和文件。
而這個(gè)掛載在容器根目錄上、用來(lái)為容器進(jìn)程提供隔離后執(zhí)行環(huán)境的文件系統(tǒng),就是所謂的“容器鏡像”。它還有一個(gè)更為專業(yè)的名字,叫作:rootfs(根文件系統(tǒng))。所以,一個(gè)最常見(jiàn)的 rootfs,或者說(shuō)容器鏡像,會(huì)包括如下所示的一些目錄和文件,比如 /bin,/etc,/proc 等等:
$ ls /
bin dev etc home lib lib64 mnt opt proc root run sbin sys tmp usr var
而你進(jìn)入容器之后執(zhí)行的 /bin/bash,就是 /bin 目錄下的可執(zhí)行文件,與宿主機(jī)的 /bin/bash 完全不同。現(xiàn)在,你應(yīng)該可以理解,對(duì) Docker 項(xiàng)目來(lái)說(shuō),它最核心的原理實(shí)際上就是為待創(chuàng)建的用戶進(jìn)程:
1、啟用 Linux Namespace 配置;
2、設(shè)置指定的 Cgroups 參數(shù);
3、切換進(jìn)程的根目錄(Change Root)。
這樣,一個(gè)完整的容器就誕生了。不過(guò),Docker 項(xiàng)目在最后一步的切換上會(huì)優(yōu)先使用 pivot_root 系統(tǒng)調(diào)用,如果系統(tǒng)不支持,才會(huì)使用 chroot。這兩個(gè)系統(tǒng)調(diào)用雖然功能類似,但是也有細(xì)微的區(qū)別,這一部分小知識(shí)就交給你課后去探索了。另外,需要明確的是,rootfs 只是一個(gè)操作系統(tǒng)所包含的文件、配置和目錄,并不包括操作系統(tǒng)內(nèi)核。在 Linux 操作系統(tǒng)中,這兩部分是分開(kāi)存放的,操作系統(tǒng)只有在開(kāi)機(jī)啟動(dòng)時(shí)才會(huì)加載指定版本的內(nèi)核鏡像。
三、 rootfs
上面我們引出了rootfs的概念,但是我們也得知,他就是一個(gè)文件系統(tǒng),不包括內(nèi)核。
所以說(shuō),rootfs 只包括了操作系統(tǒng)的“軀殼”,并沒(méi)有包括操作系統(tǒng)的“靈魂”。那么,對(duì)于容器來(lái)說(shuō),這個(gè)操作系統(tǒng)的“靈魂”又在哪里呢?實(shí)際上,同一臺(tái)機(jī)器上的所有容器,都共享宿主機(jī)操作系統(tǒng)的內(nèi)核。這就意味著,如果你的應(yīng)用程序需要配置內(nèi)核參數(shù)、加載額外的內(nèi)核模塊,以及跟內(nèi)核進(jìn)行直接的交互,你就需要注意了:這些操作和依賴的對(duì)象,都是宿主機(jī)操作系統(tǒng)的內(nèi)核,它對(duì)于該機(jī)器上的所有容器來(lái)說(shuō)是一個(gè)“全局變量”,牽一發(fā)而動(dòng)全身。這也是容器相比于虛擬機(jī)的主要缺陷之一:畢竟后者不僅有模擬出來(lái)的硬件機(jī)器充當(dāng)沙盒,而且每個(gè)沙盒里還運(yùn)行著一個(gè)完整的 Guest OS 給應(yīng)用隨便折騰。不過(guò),正是由于 rootfs 的存在,容器才有了一個(gè)被反復(fù)宣傳至今的重要特性:一致性。什么是容器的“一致性”呢?
有了容器之后,更準(zhǔn)確地說(shuō),有了容器鏡像(即 rootfs)之后,這個(gè)問(wèn)題被非常優(yōu)雅地解決了。由于 rootfs 里打包的不只是應(yīng)用,而是整個(gè)操作系統(tǒng)的文件和目錄,也就意味著,應(yīng)用以及它運(yùn)行所需要的所有依賴,都被封裝在了一起。事實(shí)上,對(duì)于大多數(shù)開(kāi)發(fā)者而言,他們對(duì)應(yīng)用依賴的理解,一直局限在編程語(yǔ)言層面。比如 Golang 的 Godeps.json。但實(shí)際上,一個(gè)一直以來(lái)很容易被忽視的事實(shí)是,對(duì)一個(gè)應(yīng)用來(lái)說(shuō),操作系統(tǒng)本身才是它運(yùn)行所需要的最完整的“依賴庫(kù)”。有了容器鏡像“打包操作系統(tǒng)”的能力,這個(gè)最基礎(chǔ)的依賴環(huán)境也終于變成了應(yīng)用沙盒的一部分。這就賦予了容器所謂的一致性:無(wú)論在本地、云端,還是在一臺(tái)任何地方的機(jī)器上,用戶只需要解壓打包好的容器鏡像,那么這個(gè)應(yīng)用運(yùn)行所需要的完整的執(zhí)行環(huán)境就被重現(xiàn)出來(lái)了。這種深入到操作系統(tǒng)級(jí)別的運(yùn)行環(huán)境一致性,打通了應(yīng)用在本地開(kāi)發(fā)和遠(yuǎn)端執(zhí)行環(huán)境之間難以逾越的鴻溝。
四、關(guān)于增量rootfs和Union File System
不過(guò),這時(shí)引出另一個(gè)非常棘手的問(wèn)題:難道我每開(kāi)發(fā)一個(gè)應(yīng)用,或者升級(jí)一下現(xiàn)有的應(yīng)用,都要重復(fù)制作一次 rootfs 嗎?
比如,我現(xiàn)在用 Ubuntu 操作系統(tǒng)的 ISO 做了一個(gè) rootfs,然后又在里面安裝了 Java 環(huán)境,用來(lái)部署我的 Java 應(yīng)用。那么,我的另一個(gè)同事在發(fā)布他的 Java 應(yīng)用時(shí),顯然希望能夠直接使用我安裝過(guò) Java 環(huán)境的 rootfs,而不是重復(fù)這個(gè)流程。類似于實(shí)現(xiàn)一種共享公共鏡像的操作,不用每個(gè)人做重復(fù)性的工作。
一種比較直觀的解決辦法是,我在制作 rootfs 的時(shí)候,每做一步“有意義”的操作,就保存一個(gè) rootfs 出來(lái),這樣其他同事就可以按需求去用他需要的 rootfs 了。但是,這個(gè)解決辦法并不具備推廣性。原因在于,一旦你的同事們修改了這個(gè) rootfs,新舊兩個(gè) rootfs 之間就沒(méi)有任何關(guān)系了,因?yàn)楫a(chǎn)生了一個(gè)新的rootfs。這樣做的結(jié)果就是極度的碎片化。那么,既然這些修改都基于一個(gè)舊的 rootfs,我們能不能以增量的方式去做這些修改呢?這樣做的好處是,所有人都只需要維護(hù)相對(duì)于 base rootfs 修改的增量?jī)?nèi)容,而不是每次修改都制造一個(gè)“fork”。我們只保存一份基礎(chǔ)的,每個(gè)人不同內(nèi)容的自己維護(hù)一份增量就行了,這樣我們只每個(gè)人維護(hù)增量的內(nèi)容。
答案當(dāng)然是肯定的。這也正是為何,Docker 公司在實(shí)現(xiàn) Docker 鏡像時(shí)并沒(méi)有沿用以前制作 rootfs 的標(biāo)準(zhǔn)流程,而是做了一個(gè)小小的創(chuàng)新:Docker 在鏡像的設(shè)計(jì)中,引入了層(layer)的概念。也就是說(shuō),用戶制作鏡像的每一步操作,都會(huì)生成一個(gè)層,也就是一個(gè)增量 rootfs。當(dāng)然,這個(gè)想法不是憑空臆造出來(lái)的,而是用到了一種叫作聯(lián)合文件系統(tǒng)(Union File System)的能力。Union File System 也叫 UnionFS,最主要的功能是將多個(gè)不同位置的目錄聯(lián)合掛載(union mount)到同一個(gè)目錄下。比如,我現(xiàn)在有兩個(gè)目錄 A 和 B,它們分別有兩個(gè)文件:A目錄下面有a和x文件,B目錄下面有b和x兩個(gè)文件。
$ tree
.
├── A
│ ├── a
│ └── x
└── B├── b└── x
然后,使用聯(lián)合掛載的方式,將這兩個(gè)目錄掛載到一個(gè)公共的目錄 C 上:
$ mkdir C
$ mount -t aufs -o dirs=./A:./B none ./C
這時(shí),再查看目錄 C 的內(nèi)容,就能看到目錄 A 和 B 下的文件被合并到了一起:
$ tree ./C
./C
├── a
├── b
└── x
可以看到,在這個(gè)合并后的目錄 C 里,有 a、b、x 三個(gè)文件,并且 x 文件只有一份。這,就是“合并”的含義。此外,如果你在目錄 C 里對(duì) a、b、x 文件做修改,這些修改也會(huì)在對(duì)應(yīng)的目錄 A、B 中生效。那么,在 Docker 項(xiàng)目中,又是如何使用這種 Union File System 的呢?
我的環(huán)境是CentOS Linux release 7.8.2003和Docker Engine - Community 20.10.14,這對(duì)組合默認(rèn)使用的是 overlay2這個(gè)聯(lián)合文件系統(tǒng)的實(shí)現(xiàn)。你可以通過(guò) docker info 命令,查看到這個(gè)信息,其欄目就是docker info中的Storage Driver: overlay2。
對(duì)于 overlay2 來(lái)說(shuō),它最關(guān)鍵的目錄結(jié)構(gòu)在 /var/lib/docker 路徑下的overlay2 目錄:
/var/lib/docker/overlay2/<layer_id>
而這個(gè)目錄的作用,我們不妨通過(guò)一個(gè)具體例子來(lái)看一下?,F(xiàn)在,我們啟動(dòng)一個(gè)容器,比如:
$ docker run -d redis:latest sleep 3600
這時(shí)候,Docker 就會(huì)從 Docker Hub 上拉取一個(gè)redis鏡像到本地。這個(gè)所謂的“鏡像”,實(shí)際上就是一個(gè) redis的 rootfs,它的內(nèi)容是 Uredis的所有文件和目錄。不過(guò),與之前我們講述的 rootfs 稍微不同的是,Docker 鏡像使用的 rootfs,往往由多個(gè)“層”組成:
$ docker image inspect redis:latest
..."RootFS": {"Type": "layers","Layers": ["sha256:8553b91047dad45bedc292812586f1621e0a464a09a7a7c2ce6ac5f8ba2535d7","sha256:a29f3c086730b523ac2e1c55da793a9d63fc4c7167fa7196500011f4d0e5df05","sha256:bee68ae43a83b10c9f490448abb719304af02a834f3557fda199c6e408ae8cc7","sha256:df132c87bdb2ed2662fbcab6e9ecce353f6e8fe257797f442bc50bf70a78a089","sha256:c4afa995e3ec19959c6f9768d7ef6d8614717301ea4997b624de7aeaa2ff3690","sha256:47998e638469ca465758350e8f2a24675d6ae02600ac00baae447c3900ee337f"]},
可以看到,這個(gè) redis鏡像,實(shí)際上由六個(gè)層組成。這六個(gè)層就是六增量 rootfs,每一層都是redis文件與目錄的一部分;而在使用鏡像時(shí),Docker 會(huì)把這些增量聯(lián)合掛載在一個(gè)統(tǒng)一的掛載點(diǎn)上(等價(jià)于前面例子里的“/C”目錄)。這個(gè)掛載點(diǎn)就是 /var/lib/docker/overlay2/,比如:
/var/lib/docker/overlay2/8cfeca51edf8dab2e19ce574dbf1fc6d845ca38880b026bafdcc514c83d94e8b
那么,前面提到的五個(gè)鏡像層,又是如何被聯(lián)合掛載成這樣一個(gè)完整的 redis文件系統(tǒng)的呢?
五、三層劃分
我們說(shuō)容器鏡像是以多層劃分開(kāi)的,一共分為三層,從上到下分別是:
可讀寫(xiě)層(RW):
它是容器的 rootfs 最上面的一層,它的掛載方式為:rw,即 read write。
在沒(méi)有寫(xiě)入文件之前,這個(gè)目錄是空的。而一旦在容器里做了寫(xiě)操作,
你修改產(chǎn)生的內(nèi)容就會(huì)以增量的方式出現(xiàn)在這個(gè)層中??墒?#xff0c;你有沒(méi)有想到這樣一個(gè)問(wèn)題:
如果我現(xiàn)在要做的,是刪除只讀層里的一個(gè)文件呢?為了實(shí)現(xiàn)這樣的刪除操作,
AuFS 會(huì)在可讀寫(xiě)層創(chuàng)建一個(gè) whiteout 文件,把只讀層里的文件“遮擋”起來(lái)。比如,
你要?jiǎng)h除只讀層里一個(gè)名叫 foo 的文件,那么這個(gè)刪除操作實(shí)際上是在可讀寫(xiě)層創(chuàng)建了一個(gè)名叫.wh.foo 的文件。
這樣,當(dāng)這兩個(gè)層被聯(lián)合掛載之后,foo 文件就會(huì)被.wh.foo 文件“遮擋”起來(lái),“消失”了。
這個(gè)功能,就是“ro+wh”的掛載方式,即只讀 +whiteout 的含義,稱之為隔檔。
所以,最上面這個(gè)可讀寫(xiě)層的作用,就是專門用來(lái)存放你修改 rootfs 后產(chǎn)生的增量,
無(wú)論是增、刪、改,都發(fā)生在這里。而當(dāng)我們使用完了這個(gè)被修改過(guò)的容器之后,
還可以使用 docker commit 和 push 指令,保存這個(gè)被修改過(guò)的可讀寫(xiě)層,并上傳到 Docker Hub 上,
供其他人使用;而與此同時(shí),原先的只讀層里的內(nèi)容則不會(huì)有任何變化。這,就是增量 rootfs 的好處。
說(shuō)白了就是下面的基礎(chǔ)層是不變的,假如A用戶做了修改,變得只是A用戶操作的部分以增量的方式寫(xiě)入可讀寫(xiě)層,
這樣就其他用戶的基礎(chǔ)的只讀層還是不變的。只有A自己的鏡像發(fā)生了可讀寫(xiě)層的改變,
A自己維護(hù)就好了,大家共享的只讀層是不變的。
問(wèn)題1、而且被whiteout遮擋的文件需要清除,否則鏡像就膨脹了。這個(gè)需要對(duì)鏡像做壓縮。網(wǎng)上很多方案。
問(wèn)題2、如果對(duì)docker原始鏡像進(jìn)行修改 比如在ubuntu鏡像上安裝Java 那么修改的是可讀寫(xiě)層。提交后變成只讀層的最上面一層。原本已有的只讀層不會(huì)變,并再此基礎(chǔ)上新增層, 而不是整個(gè)只讀層不會(huì)變,即commit后就會(huì)將讀寫(xiě)層的內(nèi)容合并到只讀層的最上層。init層(RO+WH):
他的掛載方式是RO只讀和WH隔檔,也就是這里的修改是會(huì)產(chǎn)生隔檔的,但是我們知道隔檔是放在讀寫(xiě)層的。
它是一個(gè)以“-init”結(jié)尾的層,夾在只讀層和讀寫(xiě)層之間。Init 層是 Docker 項(xiàng)目單獨(dú)生成的一個(gè)內(nèi)部層,
專門用來(lái)存放 /etc/hosts、/etc/resolv.conf 等信息。需要這樣一層的原因是,
這些文件本來(lái)屬于只讀的鏡像的一部分,但是用戶往往需要在啟動(dòng)容器時(shí)寫(xiě)入一些指定的值比如 hostname,
所以就需要在可讀寫(xiě)層對(duì)它們進(jìn)行修改。可是,這些修改往往只對(duì)當(dāng)前的容器有效,
我們并不希望執(zhí)行 docker commit 時(shí),把這些信息連同可讀寫(xiě)層一起提交掉。
所以,Docker 做法是,在修改了這些文件之后,以一個(gè)單獨(dú)的層掛載了出來(lái)。
而用戶執(zhí)行 docker commit 只會(huì)提交可讀寫(xiě)層,所以是不包含這些內(nèi)容的。
修改只對(duì)當(dāng)前容器生效,鏡像提交只有可讀寫(xiě)層,沒(méi)有這一層。換了容器這個(gè)修改就廢了。
問(wèn)題1、這一層中的文件的修改到底由誰(shuí)以及什么時(shí)候觸發(fā)的,如果是在容器啟動(dòng)階段,修改的結(jié)果不是應(yīng)該放到容器讀寫(xiě)層嗎?是docker引擎做的,在容器啟動(dòng)之前就做好這個(gè)層,和其他層一起掛載好。然后容器才會(huì)創(chuàng)建。只讀層(RO+WH):
他的掛載方式是RO只讀和WH隔檔,也就是這里的修改是會(huì)產(chǎn)生隔檔的,但是我們知道隔檔是放在讀寫(xiě)層的。
它是這個(gè)容器的 rootfs 最下面的五層,對(duì)應(yīng)的正是 鏡像的五層。
它們的掛載方式都是只讀的(ro+wh,即 readonly+whiteout)。
可以看到,這些層,都以增量的方式分別包含了應(yīng)用的一部分。
最終,這 7 個(gè)層(可讀寫(xiě)五層,加上init和只讀層)都被聯(lián)合掛載到 /var/lib/docker/overlay2/mnt 目錄下,表現(xiàn)為一個(gè)完整的應(yīng)用供容器使用。
六、總結(jié)
Linux 容器文件系統(tǒng)的實(shí)現(xiàn)機(jī)制,正是我們經(jīng)常提到的容器鏡像,也叫作:rootfs。它只是一個(gè)操作系統(tǒng)的所有文件和目錄,并不包含內(nèi)核,最多也就幾百兆。
而相比之下,傳統(tǒng)虛擬機(jī)的鏡像大多是一個(gè)磁盤的“快照”,磁盤有多大,鏡像就至少有多大。通過(guò)結(jié)合使用 Mount Namespace 和 rootfs,容器就能夠?yàn)檫M(jìn)程構(gòu)建出一個(gè)完善的文件系統(tǒng)隔離環(huán)境。當(dāng)然,這個(gè)功能的實(shí)現(xiàn)還必須感謝 chroot 和 pivot_root 這兩個(gè)系統(tǒng)調(diào)用切換進(jìn)程根目錄的能力。
而在 rootfs 的基礎(chǔ)上,Docker 公司創(chuàng)新性地提出了使用多個(gè)增量 rootfs 聯(lián)合掛載一個(gè)完整 rootfs 的方案,這就是容器鏡像中“層”的概念。通過(guò)“分層鏡像”的設(shè)計(jì),以 Docker 鏡像為核心,來(lái)自不同公司、不同團(tuán)隊(duì)的技術(shù)人員被緊密地聯(lián)系在了一起。而且,由于容器鏡像的操作是增量式的,這樣每次鏡像拉取、推送的內(nèi)容,比原本多個(gè)完整的操作系統(tǒng)的大小要小得多;而共享層的存在,可以使得所有這些容器鏡像需要的總空間,也比每個(gè)鏡像的總和要小。這樣就使得基于容器鏡像的團(tuán)隊(duì)協(xié)作,要比基于動(dòng)則幾個(gè) GB 的虛擬機(jī)磁盤鏡像的協(xié)作要敏捷得多。
更重要的是,一旦這個(gè)鏡像被發(fā)布,那么你在全世界的任何一個(gè)地方下載這個(gè)鏡像,得到的內(nèi)容都完全一致,可以完全復(fù)現(xiàn)這個(gè)鏡像制作者當(dāng)初的完整環(huán)境。這,就是容器技術(shù)“強(qiáng)一致性”的重要體現(xiàn)。
本文有些問(wèn)題,因?yàn)榄h(huán)境切換導(dǎo)致不太正確,但是基本理論的學(xué)習(xí)本文主要是,實(shí)際操作下篇開(kāi)始。
現(xiàn)在docker新版本存儲(chǔ)驅(qū)動(dòng)都是layerfs的overlay2,我看官方文檔也沒(méi)說(shuō)明怎么切換到aufs,要想切換在啟動(dòng)參數(shù)里指定即可,因?yàn)槲覜](méi)指定,所以其實(shí)是overlay2,導(dǎo)致有些結(jié)果不一樣??梢詤⒖歼@篇文章https://blog.csdn.net/u010566813/article/details/117783220