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