温故知新:Docker基础知识知多少?
【云原生】|?作者/Edison Zhou
這是恰童鞋騷年的第233篇原創(chuàng)文章
記得之前曾經(jīng)粗略的寫(xiě)過(guò)一篇Docker的基礎(chǔ)及ASP.NET Core部署Docker示例的入門(mén)文章,但那個(gè)時(shí)候剛剛學(xué)習(xí)對(duì)Docker的認(rèn)知還比較淺,現(xiàn)在重新來(lái)溫故知新一下。本文預(yù)計(jì)閱讀時(shí)間為10min。
1容器的用途
首先,我們來(lái)溫習(xí)一下Docker的幾個(gè)用途,亦或者說(shuō)Docker到底幫我們解決什么問(wèn)題?
1、標(biāo)準(zhǔn)化打包
記得在容器技術(shù)出來(lái)之前,我們開(kāi)發(fā)者進(jìn)行打包一般都依賴(lài)于各自開(kāi)發(fā)語(yǔ)言平臺(tái)獨(dú)有的打包機(jī)制,比如.NET和Java平臺(tái)下都會(huì)依賴(lài)于各自不同的發(fā)布部署技術(shù),但在容器技術(shù)出來(lái)之后,不管是.NET還是Java都會(huì)將其發(fā)布為容器鏡像推送到鏡像倉(cāng)庫(kù)中作來(lái)進(jìn)行部署。
2、隔離
每個(gè)容器在運(yùn)行時(shí)都會(huì)認(rèn)為自己是獨(dú)自占有了一臺(tái)機(jī)器,即一個(gè)獨(dú)立的環(huán)境互不干擾。其實(shí),容器的本質(zhì)是一個(gè)進(jìn)程,進(jìn)程與進(jìn)程之間相互隔離造就了容器與容器互不影響的特性。在啟動(dòng)一個(gè)容器(即創(chuàng)建一個(gè)進(jìn)程時(shí)),通過(guò) Namespace 技術(shù)實(shí)現(xiàn)容器的隔離、通過(guò) Cgroups 來(lái)實(shí)現(xiàn)容器的資源控制。
關(guān)于Namespace 和 Cgroups 可以繼續(xù)瀏覽本文3.3小節(jié)。
3、標(biāo)準(zhǔn)化部署
在容器技術(shù)出來(lái)之前,和打包機(jī)制一樣,我們都依賴(lài)于具體開(kāi)發(fā)語(yǔ)言平臺(tái)的部署機(jī)制,比如IIS、Tomcat等。但是,容器技術(shù)出來(lái)之后,即使我們使用不同的開(kāi)發(fā)語(yǔ)言都可以使用同樣的部署技術(shù),例如Mesos或Kubernetes。至此,之前的運(yùn)維人員也不在需要學(xué)習(xí)多套部署技術(shù),只需要了解如K8s一類(lèi)的標(biāo)準(zhǔn)化容器編排平臺(tái)即可。
2與集裝箱的關(guān)聯(lián)
提到容器要解決的問(wèn)題,就不得不提一下運(yùn)輸業(yè)以及集裝箱。幾十年前,運(yùn)輸業(yè)面臨著因貨物類(lèi)型不同而導(dǎo)致?lián)p失,又或者在運(yùn)輸過(guò)程中使用不同的交通工具也會(huì)讓整個(gè)過(guò)程痛苦不堪。幸運(yùn)的是,集裝箱的發(fā)明幫助運(yùn)輸業(yè)解決了這個(gè)問(wèn)題:
(1)任何貨物,無(wú)論是鋼琴還是瑪莎拉蒂,都被放到各自的集裝箱中。
(2)集裝箱在整個(gè)運(yùn)輸過(guò)程中都是密封的,只有到達(dá)最終目的地才被打開(kāi)。
(3)集裝箱可以被高效地裝卸、重疊和長(zhǎng)途運(yùn)輸。例如:現(xiàn)代化的起重機(jī)可以自動(dòng)在卡車(chē)、輪船和火車(chē)之間移動(dòng)集裝箱。
容器的核心思想其實(shí)也就是將集裝箱的思想應(yīng)用到了軟件的打包和部署上,為各類(lèi)不同的代碼提供了一個(gè)基于容器的標(biāo)準(zhǔn)化運(yùn)輸系統(tǒng)。換句話說(shuō),容器可以將任何應(yīng)用及其依賴(lài)環(huán)境打包為一個(gè)輕量級(jí)、可移植、自包含的獨(dú)立運(yùn)行環(huán)境,容器可以運(yùn)行在幾乎所有的操作系統(tǒng)之上。
不得不說(shuō),Docker的Logo就是一堆集裝箱放在海豚上,作為海豚的docker就是一個(gè)標(biāo)準(zhǔn)化的運(yùn)輸系統(tǒng):
3容器實(shí)現(xiàn)的核心技術(shù)
1、操作系統(tǒng)內(nèi)核(Linux)
為了進(jìn)一步理解Docker,我們先來(lái)看看Linux操作系統(tǒng)及其內(nèi)核,如下圖所示:
從上圖可知,最底層為硬件層,包含了內(nèi)存、磁盤(pán)、CPU、網(wǎng)卡等;往上一層是內(nèi)核空間,Kernel就是操作系統(tǒng)內(nèi)核,負(fù)責(zé)管理硬件層中的各種資源 以及 調(diào)度進(jìn)程 等工作;頂層是用戶(hù)空間,用戶(hù)程序就在此空間內(nèi)運(yùn)行,并調(diào)用內(nèi)核空間提供的服務(wù);
2、虛擬機(jī)和容器的差異
大概了解了操作系統(tǒng)的內(nèi)核之后,我們?cè)賮?lái)看看老生常談的容器和虛擬機(jī)的差異,如下圖所示:
虛擬機(jī):主要是由硬件虛擬化+內(nèi)核虛擬化技術(shù)來(lái)實(shí)現(xiàn),它在宿主機(jī)操作系統(tǒng)或硬件層的基礎(chǔ)之上引入一層Hypervisor來(lái)虛擬出磁盤(pán)、CPU等資源,然后在虛擬出來(lái)的資源的基礎(chǔ)之上運(yùn)行Guest OS進(jìn)而實(shí)現(xiàn)最終的虛擬機(jī)。
容器:直接在宿主機(jī)操作系統(tǒng)之上構(gòu)建一個(gè)Docker Engine,共享宿主機(jī)操作系統(tǒng)內(nèi)核,在此基礎(chǔ)之上只引入了少量的Guest OS來(lái)實(shí)現(xiàn)。
對(duì)比一下:
(1)虛擬機(jī)的隔離性比容器好,因?yàn)樘摂M機(jī)是一種強(qiáng)隔離機(jī)制;
(2)虛擬機(jī)比較重量級(jí),啟動(dòng)時(shí)速度比較慢,消耗資源也比較多;
(3)容器的隔離性不如虛擬機(jī),它是一種軟件隔離機(jī)制,但它比較輕量級(jí),引入的東西較少,所以速度快消耗資源少;因此,在同一個(gè)物理機(jī)上能夠啟動(dòng)的容器的數(shù)量遠(yuǎn)遠(yuǎn)多于虛擬機(jī)的數(shù)量;
3、容器的核心技術(shù)
了解了操作系統(tǒng)的內(nèi)核以及和虛擬機(jī)的差異,現(xiàn)在我們可以正式了解一下基于Linux內(nèi)核的Docker容器核心技術(shù)到底有哪些(當(dāng)然,本文只是粗略的介紹一下,更詳細(xì)的部分請(qǐng)瀏覽本文的參考資料文章),如下圖所示:
(1)CGroups:
容器進(jìn)程創(chuàng)建好后,若不進(jìn)行其他處理,該進(jìn)程運(yùn)行時(shí)所消耗及占用的資源(如 CPU、內(nèi)存)等,是可以被其他宿主機(jī)進(jìn)程或其他容器進(jìn)程享用的。為了解決這個(gè)問(wèn)題,Linux 容器設(shè)計(jì)中引入了 Cgroups 的概念。
Linux CGroups 的全稱(chēng)是 Linux Control Group,它的主要作用就是限制一個(gè)進(jìn)程(這里也可以指容器)能夠使用的資源上限(如 Cpu、內(nèi)存、網(wǎng)絡(luò)等等)。關(guān)于Docker的資源限制,可以閱讀我這一篇《Docker資源限制學(xué)習(xí)與驗(yàn)證》文章。
(2)Namespaces:
剛剛提到,容器的本質(zhì)是一個(gè)進(jìn)程,進(jìn)程與進(jìn)程之間相互隔離造就了容器與容器互不影響的特性。在啟動(dòng)一個(gè)容器(即創(chuàng)建一個(gè)進(jìn)程時(shí)),通過(guò) Namespaces 技術(shù)實(shí)現(xiàn)容器的隔離。
容器進(jìn)程的創(chuàng)建通過(guò) Linux 平臺(tái)下的 Clone 方法創(chuàng)建,在調(diào)用該方法創(chuàng)建進(jìn)程時(shí),通過(guò)指定額外的 Namespace 參數(shù),使得剛創(chuàng)建的進(jìn)程屬于一個(gè)獨(dú)立的空間。
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL) 指定額外參數(shù) CLONE_NEWPID 創(chuàng)建的新進(jìn)程,有一個(gè)自己的?獨(dú)立進(jìn)程空間,在這個(gè)空間里,它的進(jìn)程 ID 為 1。它既看不到其在宿主機(jī)的真正進(jìn)程、也看不到其他容器的進(jìn)程。(3)Networking
容器的創(chuàng)建還需要網(wǎng)絡(luò)的支持,Networking這一塊主要是虛擬網(wǎng)卡、網(wǎng)橋及iptables為容器提供組網(wǎng)支持;
(4)Storage
最后,容器的創(chuàng)建還需要存儲(chǔ)的支持,Storage這一塊提供了容器支持的一些文件系統(tǒng),如Device Mapper、Btrfs 及 Aufs 等等;
4、容器的鏡像
剛剛提到,容器鏡像為標(biāo)準(zhǔn)化打包提供了基礎(chǔ)。容器鏡像采用的是分層的方式來(lái)組織的,如下圖所示:
可以看到,底層的是基礎(chǔ)鏡像,稱(chēng)為Base Image,例如Ubuntu、CentOS等,它可以和宿主機(jī)的OS是不一樣的,但是它會(huì)共享宿主機(jī)操作系統(tǒng)的內(nèi)核;在基礎(chǔ)鏡像之上,可以有多層鏡像,例如Java JDK的依賴(lài),.NET Core Runtime依賴(lài)等;依賴(lài)層之上呢,可以是具體的應(yīng)用程序的Release。
綜上所述,容器鏡像采用分層的方式進(jìn)行組織,可以很方便地實(shí)現(xiàn)鏡像層的復(fù)用。如果兩個(gè)容器所依賴(lài)的底層鏡像層是相同的,可以共同應(yīng)用同一個(gè)Hash值的底層鏡像,進(jìn)而也可以節(jié)省傳輸和網(wǎng)絡(luò)的開(kāi)銷(xiāo)。例如,圖中Image1和Image2的就實(shí)現(xiàn)了基礎(chǔ)鏡像層的復(fù)用。
4容器的架構(gòu)一覽
有了之前的基礎(chǔ)知識(shí),最后我們?cè)賮?lái)看看Docker的架構(gòu),如下圖所示:
從上圖可以看出,一個(gè)典型的Docker架構(gòu)包含了三塊內(nèi)容:
(1)Docker Registry:鏡像倉(cāng)庫(kù),主要負(fù)責(zé)存儲(chǔ)鏡像,官方的倉(cāng)庫(kù)是Docker Hub,你也可以基于開(kāi)源項(xiàng)目Harbor或者使用阿里云等云服務(wù)廠商提供的鏡像倉(cāng)庫(kù)服務(wù)來(lái)搭建私有鏡像倉(cāng)庫(kù),如果有興趣可以參考我的這一篇《Docker常用流行鏡像倉(cāng)庫(kù)搭建》。
(2)Docker Host:Docker宿主,首先它會(huì)運(yùn)行一個(gè)Docker daemon,會(huì)接收Docker Client發(fā)送的指令來(lái)執(zhí)行拉取鏡像、緩存、啟動(dòng)等操作;其次,Docker daemon執(zhí)行完Docker Client發(fā)送過(guò)來(lái)的指令后,所有的容器都會(huì)在Docker Host上運(yùn)行;
(3)Docker Client:客戶(hù)端操作,主要負(fù)責(zé)通過(guò)docker命令行對(duì)容器進(jìn)行基本操作,如拉取鏡像,構(gòu)建鏡像,運(yùn)行容器等等;
更多關(guān)于Docker架構(gòu)的內(nèi)容請(qǐng)參考(也可以直接點(diǎn)擊本文底部“閱讀原文”):https://docs.docker.com/get-started/overview/
5關(guān)于Docker Compose
Docker主要用來(lái)運(yùn)行單容器應(yīng)用,而Docker Compose則是一個(gè)用來(lái)定義和應(yīng)用多容器應(yīng)用的工具,如下圖所示:
使用Docker Compose,我們可以將多容器的定義和部署方式定義在一個(gè)yml文件中,這種方式特別是微服務(wù)這種架構(gòu)風(fēng)格,可以將多個(gè)微服務(wù)的定義及部署都規(guī)范在一個(gè)yml文件中,然后一鍵部署、啟動(dòng)或銷(xiāo)毀整個(gè)微服務(wù)應(yīng)用。所有的一切操作,只需要下面的一句話:
$docker-compose up 很多人建議在本地測(cè)試環(huán)境,使用Docker Compose來(lái)快速的部署和測(cè)試微服務(wù)應(yīng)用,在生產(chǎn)環(huán)境則建議使用Kubernetes這種生產(chǎn)級(jí)的容器云平臺(tái)。如果對(duì)Docker Compose感興趣,我之前也有寫(xiě)一篇使用Docker Compose來(lái)編排Spring Cloud微服務(wù)的示例文章,有興趣可以看看。
6小結(jié)
本文從Docker容器要解決的幾個(gè)問(wèn)題入手,介紹了容器與集裝箱的關(guān)聯(lián)、容器的核心實(shí)現(xiàn)技術(shù)、容器的架構(gòu),最后簡(jiǎn)單介紹了一個(gè)Docker Compose這個(gè)多容器應(yīng)用工具,相信能夠從背景知識(shí)上幫你了解容器到底要幫助我們解決的問(wèn)題。
7參考資料
楊波,《Spring Boot與Kubernetes云原生應(yīng)用實(shí)踐》(強(qiáng)力推薦訂閱學(xué)習(xí))
EdisonZhou,《ASP.NET Core on Docker入門(mén)》
EdisonZhou,《Docker資源限制學(xué)習(xí)與驗(yàn)證》
godruoyi,《容器的工作原理和隔離機(jī)制》
CloudMan,《每天5分鐘玩轉(zhuǎn)Docker容器技術(shù)》
往期精彩回顧
.NET Core on K8s學(xué)習(xí)系列文章目錄
基于Jenkins的開(kāi)發(fā)測(cè)試全流程持續(xù)集成實(shí)踐
基于Jenkins的ASP.NET Core持續(xù)集成實(shí)踐
如果本文對(duì)你有用,
不妨點(diǎn)個(gè)“在看”/轉(zhuǎn)發(fā)朋友圈
????點(diǎn)擊了解Docker更多
總結(jié)
以上是生活随笔為你收集整理的温故知新:Docker基础知识知多少?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Blazor WebAssembly 3
- 下一篇: 我们为什么推荐在Json中使用strin