在第一章的容器化架構中,我們已經了解到了 docker 是一個容器化技術,本章將詳細介紹什么是虛擬化、容器化技術,以及什么是 docker。
一、物理機 VS 虛擬化 VS 容器化
物理機:
實際的服務器或者計算機。是相對于虛擬機而言的對實體計算機的稱呼。物理機負責給虛擬機提供硬件環境,有時也稱為“寄主”或“宿主”。
虛擬化:
指通過虛擬化技術將一臺計算機虛擬為多臺邏輯計算機。在一臺計算機上同時運行多個虛擬機,每個虛擬機可運行不同的操作系統(每一個虛擬機都可以視作有自己的 CPU、內存、操作系統等),并且應用程序都可以在相互獨立的空間內運行而互不影響,從而顯著提高計算機的工作效率。
容器化:
容器化是虛擬化技術的一種,又稱操作系統層虛擬化,只虛擬化了OS層面而沒有虛擬化硬件層面,硬件仍是共享。docker 是現今容器化技術的事實標準。
容器化技術實際上是讓一個操作系統上的用戶空間被分割成多個獨立的部分,每個部分都可以運行自己的應用和服務。這就好像在同一臺服務器上同時運行多個虛擬的“小服務器”,每個“小服務器”就是一個容器。對于使用這些容器的人來說,他們操作的程序就像是在自己專用的服務器上運行一樣,彼此之間不會干擾。這樣做的好處是可以更高效地利用資源,并且讓應用程序的部署和管理變得更加簡單。
生活化的小例子?
物理機:就像一個莊園,獨立占用了一塊土地,莊園都是自己的,其他人無法共享使用。
虛擬機:相當于開發商的一個樓盤,一棟樓一套房子一戶人家,共享一塊宅基地,共享小區的花園,共享小區的游樂設施等。
容器:相當于在 1 個房子里面,開辟出來一個又一個的膠囊公寓,共享這套房子的衛生間、共享廚房、共享 WiFi,只有衣服、電腦等私人物品是你自己的
為什么要存在虛擬化和容器化?
虛擬化和容器化最開始的目的就是實現資源隔離,但是隨著資源隔離的實現,同時也帶來了其它更大的收益。?
1、資源利用率高
可以對原本利用率較低的服務器資源進行整合,用更少硬件資源運行更多的業務,降低 IT 支出和
運維管理成本。
就類似對土地直接復用,使用這塊土地的人多了,但是成本還是莊園那塊地。
2、環境標準化
一次構建,隨處執行。實現執行環境的標準化發布,部署和運維。
開發過程中一個常見的問題是環境一致性問題。由于開發環境、測試環境、生產環境不一致,導致有些 bug 可能并未在開發過程中被發現。而 Docker 的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性,從而不會再出現 「這段代碼在我機器上沒問題啊」 這類問題。
3、實現資源彈性伸縮
可以根據業務情況,動態調整計算、存儲、網絡等硬件及軟件資源。比如遇到雙 11 了,可以把服務擴容 100 個,雙 11 過去了, 把擴容的 100 個收回去。
4、提供差異化環境
可以同時提供多套差異化的執行環境,并限制環境使用資源。
比如我的服務一個以來 Ubuntu 操作系統,一個服務依賴 CentOS 操作系統,但是沒有預算購買兩個物理機,這個時候容器化就能很好的提供多種不同的環境。
5、沙箱安全
為了避免不安全或不穩定軟件對系統安全性和穩定性造成影響,可使用虛擬化技術構建虛擬執行環境。
比如我在容器里面執行 rm -rf /* 不會把整個服務器搞死,也不會影響其他人部署的程序使用。
6、相比于虛擬機,容器更輕量,啟動更快
傳統的虛擬機技術啟動應用服務往往需要數分鐘,而 Docker 不需要為每個容器創建一個完整的操作系統實例,直接使用宿主機(即運行 Docker 的那臺機器)的操作系統內核,在同一個內核上運行多個隔離的用戶空間實例(即容器)。
由于容器共享宿主機的內核,它們比虛擬機啟動更快、占用資源更少,因為虛擬機需要運行一整個操作系統,包括內核在內的所有組件。
通過這種方式,Docker 實現了應用的高效部署和運行,同時保持了不同容器之間的隔離性;因此可以做到秒級、甚至毫秒級的啟動時間。大大的節約了開發、測試、部署的時間。
docker 不需要虛擬內核,所以啟動可以更快,相當于省去了 windows 的開機時間。
7、更易于維護和擴展
Docker 使用的分層存儲以及鏡像的技術(后文都會介紹),使得應用重復部分的復用更為容易,也使得應用的維護更新更加簡單,基于基礎鏡像進一步擴展鏡像也變得非常簡單。
此外,Docker 團隊還和各個開源項目團隊一起維護了一大批高質量的官方鏡像,既可以直接在生產環境使用,又可以作為基礎進一步定制,大大的降低了應用服務的鏡像制作成本。
比如 docker hub 提供了很多鏡像,各個系統的一個命令就可以拿到了,研發也可以自己定制鏡像分享給各個產品。
虛擬化技術的常見類別
1、虛擬機
存在于硬件層和操作系統層間的虛擬化技術。虛擬機通過“偽造”一個硬件抽象接口,將一個操作系統以及操作系統層以上的層嫁接到硬件上,實現和真實物理機幾乎一樣的功能。
比如我們在一臺 Windows 系統的電腦上使用 Android 虛擬機,就能夠用這臺電腦打開 Android 系統上的應用。
2、容器
存在于操作系統層和函數庫層之間的虛擬化技術。容器通過“偽造”操作系統的接口,將函數庫層以上的功能置于操作系統上。
以 Docker 為例,其就是一個基于 Linux 操作系統的 Namespace 和 Cgroup 功能實現的隔離容器,可以模擬操作系統的功能。
簡單來說,如果虛擬機是把整個操作系統封裝隔離,從而實現跨平臺應用的話,那么容器則是把一個個應用單獨封裝隔離,從而實現跨平臺應用。所以容器體積比虛擬機小很多,理論上占用資源更少。容器化就是應用程序級別的虛擬化技術。容器提供了將應用程序的代碼、運行時、系統工具、系統庫和配置打包到一個實例中的標準方法。容器共享一個內核(操作系統),它安裝在硬件上。
3、JVM 之類的虛擬機
存在于函數庫層和應用程序之間的虛擬化技術。Java 虛擬機同樣具有跨平臺特性,所謂跨平臺特性實際上也就是虛擬化的功勞。我們知道 Java 語言是調用操作系統函數庫的,JVM 就是在應用層與函數庫層之間建立一個抽象層,對下通過不同的版本適應不同的操作系統函數庫,對上提供統一的運行環境交給程序和開發者,使開發者能夠調用不同操作系統的函數庫。
二、什么是 docker?
docker 的本質
Docker 本質其實不是容器,而是容器的易用工具。容器是 linux 內核中的技術,Docker 只是把這種技術在使用上簡易普及了,調用 Linux 中的容器接口。
Docker 作為容器技術的一個實現,是容器技術普及開來的最成功的實現;其是基于 Go 語言實現的一個開源項目,它的主要目標是通過對組件的封裝、分發、部署、運行等生命周期的管理,使得用戶的應用及其運行環境能夠做到“一次封裝,到處運行”。
Docker在創建容器時,是通過鏡像技術(把一個操作系統用戶空間所需要使用到的組件事先編排好,并整體打包成一個 image 文件),把鏡像文件集中放在一個倉庫中。當需要創建容器時,Docker 調用 LXC 的工具 lxc-create,連接到鏡像服務器上下載匹配的鏡像文件,而后基于鏡像啟動容器。
所以,Docker 極大的簡化了容器的使用難度。以后我們創建啟動容器,只需要一個命令,docker-run,docker-stop 就可以啟動停止一個容器了。
docker 與虛擬機的區別
傳統虛擬機 | docker 容器 | |
磁盤占用 | 幾個 GB 到幾十個? GB?左右 | 幾十 MB 到幾百 MB 左右 |
CPU 內存占用 | 虛擬操作系統非常占 CPU 和內存,需要通過虛擬層調用,占用率高 | Docker 引擎占用資源極低,直接作用于硬件資源,占用率少 |
啟動速度 | (從開機到運行項目)幾分鐘 | (從開啟容器到運行項目)幾秒 |
安裝管理 | 需要專門的運維技術 | 安裝、管理方便 |
應用部署 | 手動部署,速度慢 | 體系化部署,可以自動化,速度快 |
隔離性 | 系統級別 | 進程級別 |
封裝程度 | 打包整個操作系統 | 僅打包項目代碼和依賴信息 |
重要問題:為什么 docker 比迅疾資源利用率更高,啟動更快?
?從上圖中我們可以看到:
1、docker 有比虛擬機更少的抽象層。docker 不需要 Hypervisor 實現硬件資源虛擬化,運行在 docker 容器上的程序直接使用的是實際物理機的硬件資源。因此在 cpu、內存利用率上 docker 將會在效率上有明顯的優勢。
2、docker 利用的是宿主機的內核,而不需要 Guest OS,節省了 Guest OS 占用的資源。
3、docker 不需要 Guest OS,其共享操作系統內核,創建一個容器時,也就不需要和虛擬機一樣重新加載一個操作系統內核,從而避免引尋、加載操作系統內核返回時耗時耗資源的過程。當新建一個虛擬機時,虛擬機軟件需要加載 Guest OS,返回新建過程是分鐘級別的。而新建一個 docker 容器只需要幾秒鐘。
三、docker 官方架構
Docker 使用客戶端-服務器 (C/S) 架構模式,使用遠程 API 來管理和創建 Docker 容器。
Docker 容器則通過 Docker 鏡像來創建。

Docker 倉庫(圖中的 Registry)
Docker 倉庫用來保存鏡像,可以理解為代碼控制中的代碼倉庫。Docker Hub 提供了龐大的鏡像集合以供使用。
Docker daemon
Docker daemon 是服務器組件,是 Docker 最核心的后臺進程,我們也把它稱為守護進程;有容器和鏡像管理能力、存儲管理能力(存儲卷包含在內)、網絡管理能力。
Docker 客戶端(圖中的?Client)
Docker 客戶端通過命令行或者其他工具,使用 Docker API 與 Docker 的守護進程通信。
Docker 主機(圖中的 Host)
一個物理或者虛擬的機器;用于執行 Docker 守護進程和容器。
Docker 鏡像(圖中的 Images)
用于創建 Docker 容器的模板,相同的鏡像可以初始化多個容器。
Docker 容器(圖中的Container)
獨立運行的一個或一組應用。
便于理解的生活案例
上面概念比較難以理解,我們以一家人去旅游入住酒店為例,便于理解:?
1、我們一家人和朋友一塊旅游去酒店,我們就是 Docker 客戶端。
2、到酒店辦理入住,辦理退房,繳費都需要酒店前臺提供各種服務,這個酒店前臺就是我們的 Docker Daemon,即Docker 的核心服務端。
3、酒店是建在美麗的海邊,酒店的宅基地和大樓就是我們實際的物理服務器或者虛擬服務器,也就是 Docker Host。
4、酒店就 1000 多個房間,不同種類房間里面不一樣,有標間、大床房、家庭房等,這就是 Docker 鏡像倉庫。
?4、酒店各個種類的房間,如豪華大床房、雙人標間等,這些個就是 Docker 鏡像,我們客戶是沒有辦法修改的。
5、當我們辦理完入住了一個豪華大床房,然后把行李,個人物品帶到了一個具體的房間,那么這個房間我們就可以使用了;朋友也開了一間豪華大床房,雖然豪華大床房一樣,但我們攜帶的物品,我們的洗漱時間,睡覺時間都不一樣,不同的客戶入住后的不同房間就是容器 Docker Container。
6、當我們一周后的旅游結束,搬出了酒店,酒店就會把我們的房間恢復成鏡像原來的樣子。這也就是容器的銷毀。
四、番外篇:大數據時代 docker 針對各種情況的解決方案。
如今大數據時代,有許多新的訴求,針對這些訴求,我們可以基于 docker 給出一些解決方案。?
1、面對海量數據,應該如何處理?
答:購買大量的服務器,并研發對應軟件
2、如果開發的需求需要頻繁的變更上線,如何才能將修改的代碼快速的分發到幾百或者幾千臺服務器?如何共享軟件?
答:搞一個中心倉庫,讓各個服務器基于各自的需要,去下載對應軟件包,進行安裝;因此?CentOS 搞了 yum 倉庫,docker 設計了鏡像倉庫,docker hub 就是公共的托管倉庫。
3、軟件設計好以后,怎么快速安裝啟動,有問題又該如何回滾?
答:可以將 docker 需要的所有信息設計一套軟件格式,把所有的依賴搞進去,并打上版本標簽,
這樣就不會導致換一個服務器就出現各種問題,Docker 也就基于此設計了鏡像。
4、面對不同的開發環境,應該如何搭建?比如一會 java,一會 c++?
docker 同樣是通過鏡像來應對,鏡像里面存放了需要運行的環境,就像我們的 iPhone 內置 ios,我們的華為 mate 50 內置鴻蒙一樣,一條命令就可以完成某個環境的搭建。