1.1 什么是Docker?
Docker開源項(xiàng)目
Docker是基于Go語言實(shí)現(xiàn)的云開源項(xiàng)目遂庄,誕生于2013年寥院。Docker項(xiàng)目目前已加入Linux基金會,遵循Apache2.0協(xié)議涛目,全部開源代碼均在https://github.com/docker/docker上進(jìn)行維護(hù)秸谢。
Docker的主要目標(biāo)是“Build,Ship and Run Any App霹肝,Anywhere”,即通過對應(yīng)用組件的封裝(Packaging)估蹄,分發(fā)(Distribution),部署(Deployment)沫换,運(yùn)行(Runtime)等生命周期的管理贷屎,達(dá)到應(yīng)用組件級別的“一次封裝请唱,到處運(yùn)行”肛跌。這里的應(yīng)用組件,既可以是一個web應(yīng)用炭晒,也可以是一套數(shù)據(jù)庫服務(wù)待逞,甚至是一個操作系統(tǒng)或編譯器甥角。
Linux容器技術(shù)
Docker引擎的基礎(chǔ)是Linux容器(Linux Containers,LXC)技術(shù)识樱。IBM DeveloperWorks上給出了關(guān)于容器技術(shù)的準(zhǔn)確描述:
容器有效地將由單個操作系統(tǒng)管理的資源劃分到孤立的組中嗤无,以便更好地在孤立的組之間平衡有沖突的資源使用需求。與虛擬化相比怜庸,這樣既不需要指令級模擬当犯,也不需要即時編譯。容器可以在核心cpu本地運(yùn)行命令割疾,而不需要任何專門的解釋機(jī)制嚎卫。此外,也避免了準(zhǔn)虛擬化(paravirtualizationd)和系統(tǒng)調(diào)用替換中的復(fù)雜性宏榕。
從Linux容器到Docker
在LXC的基礎(chǔ)上拓诸,Docker進(jìn)一步優(yōu)化了容器的使用體驗(yàn)。Docker提供了各種容器管理工具(如分發(fā)麻昼,版本奠支,移植等)讓用戶無需關(guān)注底層的操作,可以簡單明了的管理和使用容器抚芦。用戶操作Docker容器就像操作一個輕量級的虛擬機(jī)那樣簡單倍谜。
我們也可以簡單的將Docker容器理解為一種沙盒(Sandbox)。每個容器內(nèi)運(yùn)行一個應(yīng)用叉抡,不同的容器相互隔離尔崔,容器之間也可以建立通信機(jī)制。容器的創(chuàng)建和停止都十分迅速褥民,容器對自身資源的需求也十分有限季春,遠(yuǎn)遠(yuǎn)低于虛擬機(jī)。很多時候轴捎,甚至直接把容器當(dāng)作應(yīng)用本身也沒有任何問題鹤盒。
1.2 為什么要使用Docker
Docker容器虛擬化的好處
Docker項(xiàng)目的發(fā)起人和Docker.Inc.的CTO Solomon Hykes認(rèn)為,Docker在正確的地點(diǎn)侦副,正確的時間順應(yīng)了正確的趨勢---即高效地構(gòu)建應(yīng)用≌炀猓現(xiàn)在開發(fā)者需要能方便的創(chuàng)建運(yùn)行在云平臺上的應(yīng)用,也即是說應(yīng)用必須能夠脫離底層機(jī)器秦驯,而且同時必須是“任何時間任何地點(diǎn)”可獲取的尺碰。因此,開發(fā)者們需要一種創(chuàng)建分布式應(yīng)用程序的方式,這也是Docker所能夠提供的亲桥。
舉個簡單的應(yīng)用場景的例子洛心。假設(shè)用戶試圖基于最常見的LA(N)MP組合來運(yùn)維一個網(wǎng)站。按照傳統(tǒng)的做法题篷,首先词身,需要安裝nginx,mysql,php以及它們各自的運(yùn)行所依賴的環(huán)境;之后分別對它們進(jìn)行配置(包括創(chuàng)建合適的用戶番枚,配置參數(shù)等)法严;經(jīng)過大量的操作后,還需要進(jìn)行功能測試葫笼,看是否正常工作深啤;如果不正常,則意味著更多的時間代價可不可控的風(fēng)險路星∷萁郑可以想象,如果再加上更多的應(yīng)用洋丐,事情會變得更加難以處理呈昔。
更為可怕的是,一旦需要服務(wù)器遷移(如從阿里云遷移到騰訊云)垫挨,往往需要重新部署和調(diào)試韩肝。這些繁重而瑣碎無趣的“體力活”,極大的降低了工作效率九榔。
而Docker提供了一種更為聰明的方式哀峻,通過容器來打包應(yīng)用,意味著遷移只需要再新的服務(wù)器上啟動需要的容器就可以了哲泊。這無疑將節(jié)約大量的寶貴的時間剩蟀,并降低部署過程出現(xiàn)的風(fēng)險。
Docker在開發(fā)和運(yùn)維中的優(yōu)勢
對開發(fā)和運(yùn)維(DevOps)人員來說切威,可能最夢寐以求的就是一次性的創(chuàng)建或配置育特,可以在任意環(huán)境,任意時間讓應(yīng)用正常的運(yùn)行先朦。而Docker恰恰是可以實(shí)現(xiàn)這一終極目標(biāo)的瑞士軍刀缰冤。
1.更快速的交付和部署。使用Docker喳魏,開發(fā)人員可以使用鏡像來快速構(gòu)建一套標(biāo)準(zhǔn)的開發(fā)環(huán)境;開發(fā)完成之后枝恋,測試和運(yùn)維人員可以直接使用相同環(huán)境來部署代碼嗡害。Docker可以快速創(chuàng)建可刪除容器焚碌,實(shí)現(xiàn)快速迭代,大量節(jié)約開發(fā)霸妹,測試十电,部署的時間。并且抑堡,各個步驟都有明確的配置和操作摆出,整個過程全程可見,使團(tuán)隊(duì)更容易理解應(yīng)用的創(chuàng)建和工作過程爷恳。
2.更高效的資源利用有缆。Docker容器運(yùn)行不需要額外的虛擬化管理程序(Virtual Machine,VMM,以及Hypervisor)支持温亲。它是內(nèi)核級的虛擬化棚壁,可以實(shí)現(xiàn)更高的性能,同時對資源的額外需求很低魂务。
3.更輕松的遷移和擴(kuò)展曼验。Docker容器幾乎可以在任意的平臺上運(yùn)行,包括物理機(jī)粘姜,虛擬機(jī)鬓照,公有云,私有云孤紧,個人電腦豺裆,服務(wù)器等。這種兼容性讓用戶可以在不同平臺之間輕松地遷移應(yīng)用号显。
4.更簡單的更新管理臭猜。使用Dockerfile,只需要小小的配置修改押蚤,就可以替代以往大量的更新工作蔑歌。并且所有修改都以增量的方式進(jìn)行分發(fā)和更新,從而實(shí)現(xiàn)自動化并且高效的容器管理活喊。
Docker與虛擬機(jī)比較
作為一種輕量級的虛擬化方式丐膝,Docker在運(yùn)行應(yīng)用上跟傳統(tǒng)的虛擬機(jī)方式相比具有顯著的優(yōu)勢量愧。
1.Docker容器很快,啟動和停止可以在秒級實(shí)現(xiàn)帅矗,這相比傳統(tǒng)的虛擬機(jī)方式要快的多偎肃。
2.Docker容器對系統(tǒng)資源需求很少,一臺主機(jī)上可以同時運(yùn)行上千個Docker容器浑此。
3.Docker通過類似Git的操作來方便用戶獲取累颂,分發(fā),和更新應(yīng)用鏡像凛俱,指令簡單紊馏,學(xué)習(xí)成本低。
4.Docker通過Dockerfile配置文件來支持靈活的自動化創(chuàng)建和部署機(jī)制蒲犬,提高工作效率朱监。
Docker除了運(yùn)行其中的應(yīng)用之外,基本不消耗額外的系統(tǒng)資源原叮,保證應(yīng)用性能的同時赫编,盡量減小系統(tǒng)的開銷。傳統(tǒng)虛擬機(jī)方式運(yùn)行N個不同的應(yīng)用(操作系統(tǒng)級別奋隶,如windows環(huán)境擂送,centos環(huán)境,kali環(huán)境)就要啟動N個虛擬機(jī)(每個虛擬機(jī)需要單獨(dú)的分配獨(dú)占內(nèi)存唯欣,磁盤嘹吨,CPU等資源),而Docker只需要啟動N個隔離的容器境氢,并將應(yīng)用放到容器內(nèi)即可蟀拷。
當(dāng)然,在隔離性放面产还,傳統(tǒng)的虛擬機(jī)方式多了一層額外的隔離匹厘。但這并不意味著Docker就不安全。Docker利用linux系統(tǒng)上的多種防護(hù)機(jī)制實(shí)現(xiàn)了嚴(yán)格可靠的隔離脐区。從1.3版本開始愈诚,Docker引入了安全選項(xiàng)和鏡像簽名機(jī)制,極大地提高了使用Docker的安全性牛隅。
下表總結(jié)了使用Docker容器技術(shù)與傳統(tǒng)虛擬機(jī)技術(shù)的特性比較炕柔。
1.3 虛擬化與Docker
虛擬化技術(shù)是一個通用的概念,在不同的領(lǐng)域有不同的理解媒佣。在計(jì)算領(lǐng)域匕累,一般指的是計(jì)算虛擬化(Computing Virtualization),或通常說的服務(wù)器虛擬化。維基百科上定義如下:
在計(jì)算機(jī)技術(shù)中默伍,虛擬化(Vritualization)是一種資源管理技術(shù)欢嘿,是將計(jì)算機(jī)的各種實(shí)體資源衰琐,如服務(wù)器,網(wǎng)絡(luò)炼蹦,內(nèi)存及存儲等羡宙,予以抽象,轉(zhuǎn)換后呈現(xiàn)出來掐隐,打破實(shí)體結(jié)構(gòu)間的不可切割的障礙狗热,使用戶可以用比原本的組態(tài)更好的方式來應(yīng)用這些資源。
可見虑省,虛擬化的核心是對資源進(jìn)行抽象匿刮,目標(biāo)往往是為了在同一個主機(jī)上運(yùn)行多個系統(tǒng)或應(yīng)用,從而提高系統(tǒng)資源的利用率探颈,同事帶來降低成本熟丸,方便管理和容錯容災(zāi)等好處。
從大類上分膝擂,虛擬化技術(shù)可分為基于硬件的虛擬化和基于軟件的虛擬化虑啤。其中,真正意義上的基于硬件的虛擬化技術(shù)不多見架馋,少數(shù)如網(wǎng)卡中的單根多IO虛擬化(Single Root I/O Virtualization and Sharing Specification,SR-IOV)等技術(shù),此處不討論全闷,暫做了解叉寂。
基于軟件的虛擬化從對象所在層次,又可以分為應(yīng)用虛擬化和平臺虛擬化(通常說的虛擬技術(shù)即屬于這個范疇)总珠。其中屏鳍,前者一般指的是一些模擬設(shè)備或Wine這樣的軟件。后者又可以分為如下幾個子類:
完全虛擬化局服。虛擬機(jī)模擬完整的底層硬件環(huán)境和特權(quán)指令的執(zhí)行過程钓瞭,客戶操作系統(tǒng)無需進(jìn)行修改。如:VMware Workstation淫奔,Virtual Box山涡,QEMU等。
硬件輔助虛擬化唆迁。利用硬件(主要是CPU)輔助支持(目前X86體系結(jié)構(gòu)上可用的硬件虛擬化技術(shù)報錯Intel-VT和AMD-V)處理敏感指令來實(shí)現(xiàn)完全虛擬化的功能鸭丛。客戶操作系統(tǒng)無需修改唐责,例如:KVM鳞溉,Xen,VMware Workstation鼠哥。
部分虛擬化熟菲。只針對部分硬件資源進(jìn)行虛擬化看政,客戶操作系統(tǒng)需要進(jìn)行修改。現(xiàn)在 有些虛擬化技術(shù)的早期版本僅支持部分虛擬化抄罕。
超虛擬化(Paravirtualization)允蚣。部分硬件接口以軟件的形式提供給客戶機(jī)操作系統(tǒng),客戶操作系統(tǒng)需要進(jìn)行修改贞绵,例如早期的Xen厉萝。
操作系統(tǒng)級虛擬化。內(nèi)核通過創(chuàng)建多個虛擬的操作系統(tǒng)實(shí)例(內(nèi)核和庫)來隔離不同的進(jìn)程榨崩。容器相關(guān)技術(shù)即在這個范疇谴垫。
可見,Docker以及其他容器技術(shù)都屬于操作系統(tǒng)的虛擬化這個范疇母蛛。
Docker虛擬化方式之所以擁有眾多優(yōu)勢翩剪,這跟操作系統(tǒng)的虛擬化自身的特點(diǎn)是分不開的。下圖比較了Docker和常見的虛擬機(jī)方式的不同之處彩郊。
傳統(tǒng)方式是在硬件層面實(shí)現(xiàn)虛擬化前弯,需要額外的虛擬機(jī)管理應(yīng)用(以后學(xué)習(xí)KVM虛擬化的時候有用到)和虛擬機(jī)操作系統(tǒng)層。
Docker容器是在操作系統(tǒng)層面上實(shí)現(xiàn)虛擬化秫逝,直接復(fù)用本地主機(jī)的操作系統(tǒng)恕出,因此更加輕量級。
支持Docker的底層技術(shù)
Docker本質(zhì)就是宿主機(jī)的一個進(jìn)程违帆,Docker是通過namespace
實(shí)現(xiàn)資源隔離
浙巫,通過cgroup
實(shí)現(xiàn)資源限制
。通過寫時復(fù)制技術(shù)(copy-on-write)實(shí)現(xiàn)了高效的文件操作(類似虛擬機(jī)的磁盤刷后,比如分配500g并不是實(shí)際占用物理磁盤500g)
Namespace
命名空間(Namespace)是Linux為我們提供的用于分離進(jìn)程樹的畴、網(wǎng)絡(luò)接口、掛載點(diǎn)以及進(jìn)程間通信等資源的方法尝胆。在日常使用個人PC時丧裁,我們并沒有運(yùn)行多個完全分離的服務(wù)器的需求,但是如果我們在服務(wù)器上啟動多個服務(wù)含衔,這些服務(wù)其實(shí)會相互影響的煎娇,每一個服務(wù)都能看到其他服務(wù)的進(jìn)程,也可以訪問宿主機(jī)器上的任意文件抱慌,一旦服務(wù)器上的某一個服務(wù)被入侵逊桦,那么入侵者就能夠訪問當(dāng)前機(jī)器上的所有服務(wù)和文件,這是我們不愿意看到的抑进,我們更希望運(yùn)行在同一臺機(jī)器上的不同服務(wù)能做到完全隔離强经,就像運(yùn)行在多臺不同的機(jī)器上一樣。而Docker其實(shí)就通過Linux的Namespace技術(shù)來實(shí)現(xiàn)的對不同的容器進(jìn)行隔離寺渗。
當(dāng)我們運(yùn)行(docker run或者docker start)一個Docker容器時匿情,Docker會為該容器設(shè)置一系列的namespace兰迫,這些namespace提供了一層隔離,容器的各個方面都在單獨(dú)的namespace中運(yùn)行炬称,并且對其的訪問僅限于該namespace汁果。
Docker在Linux上使用以下幾個命名空間(上面說的各個方面):
- pid namespace: 用于進(jìn)程隔離(PID: 進(jìn)程ID)
- net namespace: 管理網(wǎng)絡(luò)接口(NET: 網(wǎng)絡(luò))
- ipc namespace: 管理對IPC資源的訪問(IPC: 進(jìn)程間通信(信號量、消息隊(duì)列和共享內(nèi)存))
- mnt namespace: 管理文件系統(tǒng)掛載點(diǎn)(MNT: 掛載)
- uts namespace: 隔離主機(jī)名和域名
- user namespace: 隔離用戶和用戶組(3.8以后的內(nèi)核才支持)
CGroups
我們通過Linux的namespace技術(shù)為新創(chuàng)建的進(jìn)程隔離了文件系統(tǒng)玲躯、網(wǎng)絡(luò)据德、進(jìn)程等資源,但是namespace并不能為我們提供物理資源上的隔離跷车,比如CPU棘利、內(nèi)存、IO或者網(wǎng)絡(luò)帶寬等朽缴,所以如果我們運(yùn)行多個容器的話善玫,則容器之間就會搶占資源互相影響了,所以對容器資源的使用進(jìn)行限制就非常重要了密强,而Control Groups(CGroups)技術(shù)就能夠隔離宿主機(jī)上的物理資源茅郎。CGroups由7個子系統(tǒng)組成:分別是cpuset、cpu或渤、cpuacct系冗、blkio、devices薪鹦、freezer毕谴、memory,不同類型資源的分配和管理是由各個CGroups子系統(tǒng)負(fù)責(zé)完成的距芬。
在 CGroup 中,所有的任務(wù)就是一個系統(tǒng)的一個進(jìn)程循帐,而 CGroup 就是一組按照某種標(biāo)準(zhǔn)劃分的進(jìn)程框仔,在 CGroup 這種機(jī)制中,所有的資源控制都是以 CGroup 作為單位實(shí)現(xiàn)的拄养,每一個進(jìn)程都可以隨時加入一個 CGroup 也可以隨時退出一個 CGroup离斩。