問題:我們通過docker下載centos的大小僅僅在200M左右唱矛,但下載一個tomcat就需要500M以上癣猾!這看著就很不合理。因為在window上通過虛擬機(jī)安裝一個centos大概需要4G以上,而下載最新的tomcat9也不超過20M使兔。
拋除centos的各種硬件模擬靶端,因為docker不需要Hypervisor實現(xiàn)硬件資源虛擬化谎势,centos的問題似乎可以得到解釋。但tomcat可沒辦法解釋了杨名,20M到500M的變化脏榆。
在查看相關(guān)資料后,為了說明這個問題镣煮,還是要解釋docker的鏡像到底是怎么生成的姐霍。
(UnionFS)文件聯(lián)合系統(tǒng)
UnionFS(聯(lián)合文件系統(tǒng)):Union文件系統(tǒng)(UnionFS)是一種分層、輕量級并且高性能的文件系統(tǒng)典唇,它支持對文件系統(tǒng)的修改作為一次提交來一層層的疊加镊折,同時可以將不同目錄掛載到同一個虛擬文件系統(tǒng)下(unite several directories into a single virtual filesystem)。Union 文件系統(tǒng)是 Docker 鏡像的基礎(chǔ)介衔。鏡像可以通過分層來進(jìn)行繼承恨胚,基于基礎(chǔ)鏡像(沒有父鏡像),可以制作各種具體的應(yīng)用鏡像炎咖。
特性:一次同時加載多個文件系統(tǒng)赃泡,但從外面看起來,只能看到一個文件系統(tǒng)乘盼,聯(lián)合加載會把各層文件系統(tǒng)疊加起來升熊,這樣最終的文件系統(tǒng)會包含所有底層的文件和目錄。就像是花卷一樣绸栅,一層套一層级野,但能看到的只有最外面那一層。
Docker鏡像加載原理
docker的鏡像實際上由一層一層的文件系統(tǒng)組成粹胯,這種層級的文件系統(tǒng)UnionFS蓖柔。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引導(dǎo)加載kernel, Linux剛啟動時會加載bootfs文件系統(tǒng)辰企,在Docker鏡像的最底層是bootfs。這一層與我們典型的Linux/Unix系統(tǒng)是一樣的况鸣,包含boot加載器和內(nèi)核牢贸。當(dāng)boot加載完成之后整個內(nèi)核就都在內(nèi)存中了,此時內(nèi)存的使用權(quán)已由bootfs轉(zhuǎn)交給內(nèi)核镐捧,此時系統(tǒng)也會卸載bootfs潜索。
rootfs (root file system) ,在bootfs之上愤估。包含的就是典型 Linux 系統(tǒng)中的 /dev, /proc, /bin, /etc 等標(biāo)準(zhǔn)目錄和文件帮辟。rootfs就是各種不同的操作系統(tǒng)發(fā)行版,比如Ubuntu玩焰,Centos等等由驹。
那為什么centos的鏡像只有200M?
對于一個精簡的OS昔园,rootfs可以很小蔓榄,只需要包括最基本的命令、工具和程序庫就可以了默刚,因為底層直接用Host的kernel甥郑,自己只需要提供 rootfs 就行了。由此可見對于不同的linux發(fā)行版, bootfs基本是一致的, rootfs會有差別, 因此不同的發(fā)行版可以公用bootfs荤西。
也就是說澜搅,安裝一個centos鏡像,只要下載一個kernel(linux核心)+centos rootfs(centos的命令行)邪锌,下載一個ubuntu勉躺,也只是下載一個kernel(linux核心)+rootfs(ubuntu的命令行)。
下載最新版centos
我們注意到只有一個complete
這個下載完成的就是centos的rootfs
而如果我們下載其他的比如mongo
這里下載會有很多的complete觅丰,是因為mongo要依賴很多東西饵溅,一層套一層,最終才能運(yùn)行起來妇萄。
回到我們的問題蜕企,為什么tomcat這么大?
因為tomcat運(yùn)行至少需要3層鋪墊冠句。第一層os內(nèi)核轻掩,也就是我們的kernel,第二層centos
懦底,第三層jdk放典,最外層才是我們的tomcat。
docker鏡像采用這種技術(shù)有什么好處?
最大的一個好處就是 - 共享資源
比如:有多個鏡像都從相同的 base 鏡像構(gòu)建而來奋构,那么宿主機(jī)只需在磁盤上保存一份base鏡像,同時內(nèi)存中也只需加載一份 base 鏡像拱层,就可以為所有容器服務(wù)了弥臼。而且鏡像的每一層都可以被共享。
docker鏡像這種分層結(jié)構(gòu)有什么特點
docker鏡像都是只讀的根灯,當(dāng)容器啟動時径缅,一個新的可寫層被加載到鏡像頂部。這一層通常稱為“容器層”烙肺,而容器層下面的都是鏡像層纳猪。
commit(將自定義的鏡像提交到本地)
類似于git commit嘛,沒啥好說的桃笙。比如我們運(yùn)行了一個mysql容器氏堤,通過navicat連接向mysql中建表,填數(shù)據(jù)搏明,我們想把這個鏡像保存了鼠锈,提供給其他人使用,這樣其他人拿到鏡像的時候就已經(jīng)有已經(jīng)寫好的表和數(shù)據(jù)了星著。
docker commit -m "提交你的描述信息" -a="作者" 容器id 要創(chuàng)建的目標(biāo)鏡像名:[標(biāo)簽名(版本號)]
至于怎么push到遠(yuǎn)程倉庫购笆,之后再寫。