一篇不一樣的docker原理解析
0 引言
在學習docker的過程中,我發現目前docker學習最大的障礙,不是網上的資源太少,而是網上的資源太多,資源太多帶來的雜訊讓學習效率降低不少。而在講解docker原理上,所有的講解都是關於cgroups,namespace,aufs以及deviceMapper,這對於一個初學者來說,就是用一堆名詞替換另一堆名詞,所以我打算寫一篇不涉及太多api的原理解析,在這篇解析中,將不會討論:
- 一堆堆砌在一起的專有名詞,讓閱讀者雲里霧裡
- 一大堆寫滿了專有名詞的圖,但是不給太多解釋
- 虛擬機的實現原理
- 虛擬機和容器的區別
在開始討論前,先拋出一些問題,可先別急著查看答案,討論的過程可以讓答案更有趣,問題如下:
- Docker 容器有自己的kernel嗎
- docker的kernel version由鏡像確定還是由宿主機確定
1 虛擬機
先來理解一下虛擬機概念,廣義來說,虛擬機是一種模擬系統,即在軟體層面上通過模擬硬體的輸入和輸出,讓虛擬機的操作系統得以運行在沒有物理硬體的環境中(也就是宿主機的操作系統上),其中能夠模擬出硬體輸入輸出,讓虛擬機的操作系統可以啟動起來的程序,被叫做hypervisor。用一張圖來說明這個關係就是:
在這張圖中:
- 物理機被稱為宿主機
- 虛擬機也被稱為guest OS
- 而被hypervisor虛擬出來的硬體被稱為虛擬硬體
比如,舉一個大家都很熟悉的例子,在編寫android程序時,調試和測試運行都可以在X86架構的台式機或筆記本進行,這就是一個典型的虛擬機例子,在這之中:
- 宿主機就是台式機或筆記本
- 虛擬機就是虛擬出來的android
- 而模擬android的軟體就是android box
當然android模擬機一個大問題就是:啟動速度非常慢,最長可達10分鐘或以上,這是因為單純模擬硬體的輸入輸出,效率是很差的,所以這樣的虛擬機如果真部署在伺服器上,速度是感人的。
這個時候,就有計算機科學家提出了非常偷懶的想法:假如我們不模擬硬體輸入輸出,只是做下真實硬體輸入輸出的搬運工,那麼虛擬機的指令執行速度,就可以和宿主機一致了。當然這前提是宿主機的硬體架構必須和虛擬硬體架構一致。比如,
- 我們可以在linux的台式機上輕鬆模擬windows,而且這個windows的運行速度基本上和原生裝一個windows速度差不多,因為windows也能被直接安裝在這台台式機上。
- 這個思路對於在windows系統中運行android系統不管用,因為android系統的運行硬體一般是手機(arm系統,可以理解為不同的硬體架構體系和cpu指令集),所以android模擬機還是一樣的慢。
由於本篇並不是主要關於虛擬機的內容,所以這些點就點到而止,更多詳細內容可以參閱:Hypervisor
2 容器的概念
一般來說,虛擬機都會有自己的kernel,自己的硬體,這樣虛擬機啟動的時候需要先做開機自檢,啟動kernel,啟動用戶進程等一系列行為,雖然現在電腦運行速度挺快,但是這一系列檢查做下來,也要幾十秒,也就是虛擬機需要幾十秒來啟動。
- 重新來理解虛擬機的概念,計算機科學家發現其實我們創建虛擬機也不一定需要模擬硬體的輸入和輸出,假如宿主機和虛擬機他們的kernel是一致的,就不用做硬體輸入輸出的搬運工了,只需要做kernel輸入輸出的搬運工即可,為了有別於硬體層面的虛擬機,這種虛擬機被命名為 操作系統層虛擬化:Operating-system-level virtualization 也被叫做容器
- 讓我們來回顧虛擬機的概念,在虛擬機的系統中,虛擬機認為自己有獨立的文件系統,進程系統,內存系統,等等一系列,所以為了讓容器接近虛擬機,也需要有獨立的文件系統,進程系統,內存系統,等等一系列,為了達成這一目的,主機系統採用的辦法是:只要隔離容器不讓它看到主機的文件系統,進程系統,內存系統,等等一系列,那麼容器系統就是一個接近虛擬機的玩意了
更多關於容器的內容可以看這份課件:https://courses.engr.illinois.edu/cs423/lectures/VirtOS.pdf
至此就可以回答引言提到的兩個問題:
3 how to learn more
- 關於操作系統層的虛擬化的概念:Operating-system-level virtualization 以及包括freebsd jail有關的一系列其他的操作系統上相似的實現
- 想要了解更多,docker具體做了什麼,可以參考:一篇不一樣的docker原理解析 提高篇 - uncle creepy的文章 - 知乎專欄
- 關於namespace,cgroups,aufs,deviceMapper 可以了解官方文檔
- 在mac os和windows上運行docker的秘密:Boot2docker by boot2docker 就是通過這個叫做boot2docker的玩意啟動了一個虛擬linux kernel,所有的docker容器都跑在這個kernel上
推薦閱讀:
※開始學習 Linux 用什麼發行版比較好?
※Linux 大爆炸:一個內核,無數發行版
※同樣的代碼在windows平台和在Linux平台上運行結果不同?
※RancherOS架構分析
※龔神給微軟 Linux 子系統寫的支持 DirectX 9、11的代碼到底屬不屬於「驅動」?