容器是應用走向云端之后必然的發(fā)展趨勢,因此筆者非常樂于和大家分享我們這段時間對容器的理解、心得和實踐。
本篇教程持續(xù)編寫了2個星期左右,只是為了大家更好地了解、理解和消化這個技術,能夠搭上這波車。
你可以和我們一起討論,我們希望能夠多多交流,多多分享。
如果覺得不錯,請多多點贊,你們的支持是我們前進的最大動力!
目錄


前言
隨著生產(chǎn)力的發(fā)展尤其是彈性架構的廣泛應用(比如微服務),許多一流開發(fā)者都將應用托管到了應用容器上,比如Google、微軟、亞馬遜、騰訊、阿里、京東和新浪。





從未來的發(fā)展方向來看,容器引擎將會越來越成為主流,哪怕不是彈性架構,托管到應用容器也將是一種趨勢——因為更低的開發(fā)運維和托管成本以及對服務器的資源的優(yōu)化配置。而且未來一個很大的趨勢是——無服務器計算服務。
因為相對于軟件、硬件在本地設備中的分裂,云計算的一大特性就是將服務構建在云上,供多種設備同時無縫調用。但事實上,云服務在發(fā)展的過程中還沒能實現(xiàn)共融共通的理想——比如,各家的云服務是相對割裂的,開發(fā)者基于Google云服務構建的軟件拿到亞馬遜的AWS上也許就不能用了,阿里云的應用遷移到騰訊云可能就存在問題了;在任務執(zhí)行層面,為防止互相干擾,云服務廠商在同一臺服務器上執(zhí)行多個任務時也會將它們隔離進行。很明顯,這樣的實際情況和云服務的初始理念相去甚遠。而利用容器技術,軟件可以快速在各類云服務和基礎設施上轉換。而且,當割裂問題被解決之后,軟件也有望在瞬間獲取大量的計算能力。

而Docker,就是容器引擎中的佼佼者,并且已經(jīng)得到了廣泛的實踐和應用。有了Docker之后,軟件的開發(fā)工作將會變得更加容易。比如,開發(fā)者們在筆記本電腦上寫完一個軟件后,可以將它轉移到云服務上運行而無需做出更改;無論是自己的服務器、數(shù)據(jù)中心還是Google、微軟、阿里云的云計算服務器,開發(fā)人員都可以按自己的想法在任何基礎設施之間轉移自己的軟件。這也是未來的一個愿景——機器和基礎設施是可以互相替代的,整個互聯(lián)網(wǎng)就是一個巨大的計算機。
Docker是如此令人向往和引人深入,但是在國內,開發(fā)者普遍遷移到云端基本上也都是只用到了虛擬機等基礎設施,其實大家都聽說過Docker,但是總是有一道門檻擋在大家面前導致大家無法逾越或者產(chǎn)生了一些偏見:
缺乏完整的系統(tǒng)的教程和實踐,開發(fā)者普遍認為使用Docker很麻煩,只有大公司能用,門檻很高;
云端容器服務產(chǎn)品用戶體驗不夠,對于初學者門檻太高——這個太高指的是消化這些概念和理念,并且能夠掌握和可控;
對容器服務的認知還不夠,對它的好處以及吸引之處還不太了解;
認為對現(xiàn)有系統(tǒng)、架構改造太大,成本太高;
認為Docker只是一種單純的相對先進的技術,并不能給現(xiàn)有的開發(fā)帶來什么改變;
什么是Docker
Docker 是一個開源的應用容器引擎,可以輕松的為任何應用創(chuàng)建一個輕量級的、可移植的、自給自足的容器。開發(fā)者在本地編譯測試通過的容器可以批量地在生產(chǎn)環(huán)境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集群和其他的基礎應用平臺。
簡單的理解,Docker類似于集裝箱,各式各樣的貨物,經(jīng)過集裝箱的標準化進行托管,而集裝箱和集裝箱之間沒有影響。也就是說,Docker平臺就是一個軟件集裝箱化平臺,這就意味著我們自己可以構建應用程序,將其依賴關系一起打包到一個容器中,然后這容器就很容易運送到其他的機器上進行運行,而且非常易于裝載、復制、移除,非常適合軟件彈性架構。

因此,就像船只、火車或卡車運輸集裝箱而不論其內部的貨物一樣,軟件容器充當軟件部署的標準單元,其中可以包含不同的代碼和依賴項。 按照這種方式容器化軟件,開發(fā)人員和 IT 專業(yè)人員只需進行極少修改或不修改,即可將其部署到不同的環(huán)境。
總而言之,Docker 是一個開放平臺,使開發(fā)人員和管理員可以在稱為容器的松散隔離的環(huán)境中構建鏡像、交付和運行分布式應用程序。以便在開發(fā)、QA 和生產(chǎn)環(huán)境之間進行高效的應用程序生命周期管理。
Docker和虛擬機的區(qū)別


如上圖所示,由于容器所需的資源要少得多(例如,它們不需要一個完整的 OS),所以它們易于部署且可快速啟動。這使你能夠具有更高的密度,也就是說,這允許你在同一硬件單元上運行更多服務,從而降低了成本。
在同一內核上運行的副作用是,你獲得的隔離比 VM 要少。
鏡像的主要目標是使環(huán)境(依賴項)在不同的部署中保持不變。 也就是說,可以在計算機上調試它,然后將其部署到保證具有相同環(huán)境的另一臺計算機上。
借助容器鏡像,可打包應用或服務并采用可靠且可重現(xiàn)的方式對其進行部署??梢哉f Docker 不只是一種技術,還是一種原理和過程。
在使用Docker之前,我們經(jīng)常會聽到,“這個問題在開發(fā)環(huán)境是正常的!”。而在使用 Docker 后,你不會聽到開發(fā)人員說:“為什么它能在我的計算機上使用卻不能用在生產(chǎn)中?”。開發(fā)人員只需說“它在 Docker 上運行”,因為打包的 Docker 應用程序可在任何支持的 Docker 環(huán)境上執(zhí)行,而且它在所有部署目標(例如,開發(fā)、QA、暫存和生產(chǎn))上都按預期運行。
基本概念
鏡像:一個特殊的文件系統(tǒng)
操作系統(tǒng)分為內核和用戶空間。對于 Linux 而言,內核啟動后,會掛載 root 文件系統(tǒng)為其提供用戶空間支持。而 Docker 鏡像(Image),就相當于是一個 root 文件系統(tǒng)。
Docker 鏡像是一個特殊的文件系統(tǒng),除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶等)。
鏡像不包含任何動態(tài)數(shù)據(jù),其內容在構建之后也不會被改變。
Docker 設計時,就充分利用 Union FS 的技術,將其設計為分層存儲的架構。 鏡像實際是由多層文件系統(tǒng)聯(lián)合組成。
鏡像構建時,會一層層構建,前一層是后一層的基礎。每一層構建完就不會再發(fā)生改變,后一層上的任何改變只發(fā)生在自己這一層。
比如,刪除前一層文件的操作,實際不是真的刪除前一層的文件,而是僅在當前層標記為該文件已刪除。
在最終容器運行的時候,雖然不會看到這個文件,但是實際上該文件會一直跟隨鏡像。
因此,在構建鏡像的時候,需要額外小心,每一層盡量只包含該層需要添加的東西,任何額外的東西應該在該層構建結束前清理掉。
分層存儲的特征還使得鏡像的復用、定制變的更為容易。甚至可以用之前構建好的鏡像作為基礎層,然后進一步添加新的層,以定制自己所需的內容,構建新的鏡像。
容器:鏡像運行時的實體
鏡像(Image)和容器(Container)的關系,就像是面向對象程序設計中的類和實例一樣,鏡像是靜態(tài)的定義,容器是鏡像運行時的實體。容器可以被創(chuàng)建、啟動、停止、刪除、暫停等 。
容器的實質是進程,但與直接在宿主執(zhí)行的進程不同,容器進程運行于屬于自己的獨立的命名空間。前面講過鏡像使用的是分層存儲,容器也是如此。
容器存儲層的生存周期和容器一樣,容器消亡時,容器存儲層也隨之消亡。因此,任何保存于容器存儲層的信息都會隨容器刪除而丟失。
按照 Docker 最佳實踐的要求,容器不應該向其存儲層內寫入任何數(shù)據(jù) ,容器存儲層要保持無狀態(tài)化。
所有的文件寫入操作,都應該使用數(shù)據(jù)卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網(wǎng)絡存儲)發(fā)生讀寫,其性能和穩(wěn)定性更高。
數(shù)據(jù)卷的生存周期獨立于容器,容器消亡,數(shù)據(jù)卷不會消亡。因此, 使用數(shù)據(jù)卷后,容器可以隨意刪除、重新 run,數(shù)據(jù)卻不會丟失。

注意:
容器在整個應用程序生命周期工作流中提供以下優(yōu)點:隔離性、可移植性、靈活性、可伸縮性和可控性。 最重要的優(yōu)點是可在開發(fā)和運營之間提供隔離。
倉庫:集中存放鏡像文件的地方
鏡像構建完成后,可以很容易的在當前宿主上運行,但是, 如果需要在其他服務器上使用這個鏡像,我們就需要一個集中的存儲、分發(fā)鏡像的服務,Docker Registry 就是這樣的服務。
一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標簽(Tag);每個標簽對應一個鏡像。
所以說,鏡像倉庫是 Docker 用來集中存放鏡像文件的地方,類似于我們之前常用的代碼倉庫。
通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標簽就常用于對應該軟件的各個版本 。
我們可以通過<倉庫名>:<標簽>的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標簽,將以 latest 作為默認標簽。
這里補充一下 Docker Registry 公開服務和私有 Docker Registry 的概念:
Docker Registry 公開服務是開放給用戶使用、允許用戶管理鏡像的 Registry 服務。
一般這類公開服務允許用戶免費上傳、下載公開的鏡像,并可能提供收費服務供用戶管理私有鏡像。
最常使用的 Registry 公開服務是官方的 Docker Hub ,這也是默認的 Registry,并擁有大量的高質量的官方鏡像,網(wǎng)址為:hub.docker.com/ 。
在國內訪問 Docker Hub 可能會比較慢,國內也有一些云服務商提供類似于 Docker Hub 的公開服務。
除了使用公開服務外,用戶還可以在本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry 鏡像,可以直接使用做為私有 Registry 服務。
開源的 Docker Registry 鏡像只提供了 Docker Registry API 的服務端實現(xiàn),足以支持 Docker 命令,不影響使用。但不包含圖形界面,以及鏡像維護、用戶管理、訪問控制等高級功能。
Docker的主要應用場景
簡化配置
虛擬機的最大好處是能在你的硬件設施上運行各種配置不一樣的平臺(軟件、系統(tǒng)),Docker在降低額外開銷的情況下提供了同樣的功能。它能讓你將運行環(huán)境和配置放在代碼中然后部署,同一個Docker的配置可以在不同的環(huán)境中使用,這樣就降低了硬件要求和應用環(huán)境之間耦合度。
簡單的來說,容器鏡像打包完成后,它就是個獨立的個體了,丟到哪里都能跑,而無需針對各個平臺去獨立配置。

代碼流水線(Code Pipeline)管理
前一個場景對于管理代碼的流水線起到了很大的幫助。代碼從開發(fā)者的機器到最終在生產(chǎn)環(huán)境上的部署,需要經(jīng)過很多的中間環(huán)境。而每一個中間環(huán)境都有自己微小的差別,Docker給應用提供了一個從開發(fā)到上線均一致的環(huán)境,讓代碼的流水線變得簡單不少。

提高開發(fā)效率
不同的開發(fā)環(huán)境中,我們都想把兩件事做好。一是我們想讓開發(fā)環(huán)境盡量貼近生產(chǎn)環(huán)境,二是我們想快速搭建開發(fā)環(huán)境。
使用Docker非常簡單的就能夠實現(xiàn)這兩點,而且哪怕是開發(fā)環(huán)境的機器配置一般的情況下搭建多個生成服務應用。一臺一般配置服務器或開發(fā)機也能輕松的跑起多個Docker應用,而無需額外增加機器配置。因為Docker有個非常NB的特性,擁有虛擬化的特性,而幾乎沒有額外的開銷。

隔離應用
很多情況下,我們需要在一臺服務器上運行多個不同的應用,比如上面提到的提高開發(fā)效率的場景等。
我們經(jīng)常需要考慮三點,一是因為要降低成本而進行服務器整合,二是將一個整體式的應用拆分成松耦合的單個服務(比如微服務架構),三是還需要考慮應用之間的兼容性。而對于Docker來說,支持起來就非常簡單了。同一臺機器,我可以同時運行N個Docker web應用,托管到不同的Web服務器(Kestrel、Ngnix、Tomcat),而無需擔心他們會搞起3Q大戰(zhàn),也無需擔心我的開發(fā)機器會跑不起來。

整合服務器
?
正如通過虛擬機來整合多個應用,Docker隔離應用的能力使得Docker可以整合多個服務器以降低成本。由于沒有多個操作系統(tǒng)的內存占用,以及能在多個實例之間共享沒有使用的內存,Docker可以比虛擬機提供更好的服務器整合解決方案。
這就意味著資源得到更有效的利用——可以做更多衣服,而且還沒有邊角料,成本還更低。

調試能力
Docker提供了很多的工具,這些工具不一定只是針對容器,但是卻適用于容器。它們提供了很多的功能,包括可以為容器設置檢查點、設置版本和查看兩個容器之間的差別,這些特性可以幫助調試Bug。

多租戶環(huán)境
在多租戶的應用中,它可以避免關鍵應用的重寫。比如IoT(物聯(lián)網(wǎng))的應用中,開發(fā)一個快速、易用的多租戶環(huán)境。這種多租戶的基本代碼非常復雜,很難處理,重新規(guī)劃這樣一個應用不但消耗時間,也浪費金錢。
使用Docker,可以為每一個租戶的應用層的多個實例創(chuàng)建隔離的環(huán)境,這不僅簡單而且成本低廉,當然這一切得益于Docker環(huán)境的啟動速度和其高效的diff命令。
就如同我們現(xiàn)在寫了一個不支持多租戶的業(yè)務程序,而實際的業(yè)務中經(jīng)常會出現(xiàn)需要支持多租戶或者有新客戶需要使用的場景,這是我們通常的簡單做法是——部署一套新的代碼。當站點達到一定量的適合,要么重寫程序,要么維護人員Game over。
快速部署
在虛擬機之前,引入新的硬件資源需要消耗幾天的時間。虛擬化技術(Virtualization)將這個時間縮短到了分鐘級別。而Docker通過為進程僅僅創(chuàng)建一個容器而無需啟動一個操作系統(tǒng),再次將這個過程縮短到了秒級。
你可以在服務器中或云端創(chuàng)建銷毀資源而無需擔心重新啟動帶來的開銷。通常情況下,服務器的資源利用率只有30%,而通過使用Docker并進行有效的資源分配可以提高資源的利用率。

市場實際反饋和調查
我們來看一份2016年用戶調查結果。
Docker為軟件供應鏈提供了應用程序開發(fā)的敏捷性,可控性和可移值性
- 用戶如何使用 Docker?
90% 的用戶使用 Docker 進行應用開發(fā)
65%?的用戶使用 Docker 進行敏捷開發(fā)
58%?的用戶將 Docker 用于生產(chǎn)
48%?的用戶使用 Docker 控制應用環(huán)境
41%?的用戶使用 Docker 實現(xiàn)應用的可移植性?
?- Docker?的業(yè)務覆蓋:
78%:網(wǎng)頁應用
75%:網(wǎng)頁?API
70%:應用服務端
42%:傳統(tǒng)數(shù)據(jù)庫
27%:分布式數(shù)據(jù)庫
13%:大數(shù)據(jù)
Docker 帶來的敏捷性(響應速度和靈活性)吸引了越來越多的開發(fā)者。他們不僅能知道容器內部到底跑了什么,也能進一步理解 Docker 如何加速了軟件開發(fā)進程。另外,41% 的用戶表示應用的可移植性是他們決定使用 Docker 的關鍵因素。
通過?DevOps?的實踐,Docker?正在給應用交付帶來很多可以量化的提升
如圖所示:
93% 的?Docker 用戶已經(jīng)在開發(fā)過程中獲得了益處
85% 的?Docker?用戶已經(jīng)在運維過程中獲得了益處
57% 的 Docker 用戶見證了運維環(huán)境管理的提升
45% 的?Docker 用戶已經(jīng)提高了軟件發(fā)布的頻率
大約一半的受訪者表示已經(jīng)采用了持續(xù)集成(CI)和 DevOps,并且希望把這些實戰(zhàn)經(jīng)驗應用到生產(chǎn)環(huán)境的持續(xù)交付中。剩下的受訪者則準備盡快跟上步伐,盡快嘗試 DevOps 和持續(xù)集成。另外,據(jù)調查顯示,用戶使用?Docker 發(fā)布應用的頻率平均提升了 13 倍。
Docker 對混合云策略至關重要,它使得用戶可以根據(jù)需求自由選擇私有和公有環(huán)境
如圖所示:
80%?的用戶表示?Docker 已經(jīng)是云策略的一部分
60%?的用戶則正在計劃使用?Docker?將業(yè)務遷移到云端。
41%?的用戶希望實現(xiàn)跨環(huán)境的應用移植
35+%?的用戶希望避免被云供應商綁定
通過容器來交付的應用可以在任何基礎設施之上靈活遷移,同時這些基礎設施又可以提供不同層次的應用管理方式,而當業(yè)務在多個服務供應商之中尋求混合云或全云模式時,又可以完美避免被平臺捆綁。
對于按需部署或部署到云環(huán)境,Docker 提供了獨一無二的選擇。 80% 的用戶表示 Docker 已經(jīng)成為他們云策略的一部分,超過 35% 的用戶使用 Docker 來避免被云服務供應商綁定。
Docker 實現(xiàn)了微服務架構,也讓遺留的單體應用轉變?yōu)楝F(xiàn)代應用
如圖所示:
65%?的組織面對遺留應用這一難題
59%?的組織受到遺留應用和基礎設施僵化的影響
44%?的組織正在使用微服務架構
39%?的組織讓遺留應用煥發(fā)新生
Docker 使得微服務架構的快速發(fā)展成為可能,同時它也將傳統(tǒng)的業(yè)務遷移到容器環(huán)境中,以此使得應用程序變得更加可移植。使用微服務架構進行交付是 Docker 的關鍵優(yōu)勢!
Docker改變了什么?
綜上所述,Docker到底改變了什么?筆者是這么理解的:
Docker改變了云服務,使云服務的共融共通的理想逐步成為了可能。并且Docker 已經(jīng)是云策略的一部分,許多開發(fā)者正在計劃使用 Docker 將業(yè)務遷移到云端。另外,為了避免被云服務供應商綁定,Docker成為很多開發(fā)者的首選。
Docker改變了產(chǎn)品交付,為產(chǎn)品的整個生命周期提供了一整套的解決方案和流程。
Docker改變了開發(fā)方式,提供了簡化的環(huán)境配置、封裝的運行環(huán)境以及統(tǒng)一的環(huán)境。并且提供了快速部署的方式。
Docker改變了測試,多版本測試變得極為方便,快速構建測試環(huán)境也變得更加簡單并且無需開發(fā)人員干預或者搭建。
Docker改變了運維,環(huán)境的一致性讓運維變得更加簡單,同時熱更新的支持讓運維不再需要半夜加班部署更新,更新可以隨時進行。當出現(xiàn)重大問題時,還能快速回滾到指定版本。
Docker改變了架構,自動化擴容支持讓架構變得更加簡單,分布式系統(tǒng)也更加易于搭建和支持。同時遺留的單體應用也很易于轉變?yōu)楝F(xiàn)代應用。
總之,在某種程度上,Docker改變了產(chǎn)品開發(fā)中的一些游戲規(guī)則。雖然Docker是一項技術,但是它也帶來了新的思維,新的流程和工作方法,Docker在推動行業(yè)的發(fā)展,Docker已經(jīng)在改變世界,并且在逐步的變?yōu)槭聦崱?/p>

在這里還是要推薦下我自己建的大數(shù)據(jù)學習交流扣扣群:378144993,群里都是學大數(shù)據(jù)開發(fā)的,如果你正在學習大數(shù)據(jù)?,小編歡迎你加入,大家都是軟件開發(fā)黨,不定期分享干貨(只有大數(shù)據(jù)軟件開發(fā)相關的),包括我自己整理的一份最新的大數(shù)據(jù)進階資料和高級開發(fā)教程,歡迎進階中和進想深入大數(shù)據(jù)的小伙伴加入。