容器是應用走向雲端之后必然的發展趨勢,因此筆者非常樂於和大家分享我們這段時間對容器的理解、心得和實踐。
本篇教程持續編寫了2個星期左右,只是為了大家更好地了解、理解和消化這個技術,能夠搭上這波車。
你可以和我們一起討論,我們希望能夠多多交流,多多分享。
如果覺得不錯,請多多點贊,你們的支持是我們前進的最大動力!
目錄
前言
隨着生產力的發展尤其是彈性架構的廣泛應用(比如微服務),許多一流開發者都將應用托管到了應用容器上,比如Google、微軟、亞馬遜、騰訊、阿里、京東和新浪。
從未來的發展方向來看,容器引擎將會越來越成為主流,哪怕不是彈性架構,托管到應用容器也將是一種趨勢——因為更低的開發運維和托管成本以及對服務器的資源的優化配置。而且未來一個很大的趨勢是——無服務器計算服務。
因為相對於軟件、硬件在本地設備中的分裂,雲計算的一大特性就是將服務構建在雲上,供多種設備同時無縫調用。但事實上,雲服務在發展的過程中還沒能實現共融共通的理想——比如,各家的雲服務是相對割裂的,開發者基於Google雲服務構建的軟件拿到亞馬遜的AWS上也許就不能用了,阿里雲的應用遷移到騰訊雲可能就存在問題了;在任務執行層面,為防止互相干擾,雲服務廠商在同一台服務器上執行多個任務時也會將它們隔離進行。很明顯,這樣的實際情況和雲服務的初始理念相去甚遠。而利用容器技術,軟件可以快速在各類雲服務和基礎設施上轉換。而且,當割裂問題被解決之后,軟件也有望在瞬間獲取大量的計算能力。
而Docker,就是容器引擎中的佼佼者,並且已經得到了廣泛的實踐和應用。有了Docker之后,軟件的開發工作將會變得更加容易。比如,開發者們在筆記本電腦上寫完一個軟件后,可以將它轉移到雲服務上運行而無需做出更改;無論是自己的服務器、數據中心還是Google、微軟、阿里雲的雲計算服務器,開發人員都可以按自己的想法在任何基礎設施之間轉移自己的軟件。這也是未來的一個願景——機器和基礎設施是可以互相替代的,整個互聯網就是一個巨大的計算機。
Docker是如此令人向往和引人深入,但是在國內,開發者普遍遷移到雲端基本上也都是只用到了虛擬機等基礎設施,其實大家都聽說過Docker,但是總是有一道門檻擋在大家面前導致大家無法逾越或者產生了一些偏見:
-
缺乏完整的系統的教程和實踐,開發者普遍認為使用Docker很麻煩,只有大公司能用,門檻很高;
-
雲端容器服務產品用戶體驗不夠,對於初學者門檻太高——這個太高指的是消化這些概念和理念,並且能夠掌握和可控;
-
對容器服務的認知還不夠,對它的好處以及吸引之處還不太了解;
-
認為對現有系統、架構改造太大,成本太高;
-
認為Docker只是一種單純的相對先進的技術,並不能給現有的開發帶來什么改變;
什么是Docker
Docker 是一個開源的應用容器引擎,可以輕松的為任何應用創建一個輕量級的、可移植的、自給自足的容器。開發者在本地編譯測試通過的容器可以批量地在生產環境中部署,包括VMs(虛擬機)、bare metal、OpenStack 集群和其他的基礎應用平台。
簡單的理解,Docker類似於集裝箱,各式各樣的貨物,經過集裝箱的標准化進行托管,而集裝箱和集裝箱之間沒有影響。也就是說,Docker平台就是一個軟件集裝箱化平台,這就意味着我們自己可以構建應用程序,將其依賴關系一起打包到一個容器中,然后這容器就很容易運送到其他的機器上進行運行,而且非常易於裝載、復制、移除,非常適合軟件彈性架構。
因此,就像船只、火車或卡車運輸集裝箱而不論其內部的貨物一樣,軟件容器充當軟件部署的標准單元,其中可以包含不同的代碼和依賴項。 按照這種方式容器化軟件,開發人員和 IT 專業人員只需進行極少修改或不修改,即可將其部署到不同的環境。
總而言之,Docker 是一個開放平台,使開發人員和管理員可以在稱為容器的松散隔離的環境中構建鏡像、交付和運行分布式應用程序。以便在開發、QA 和生產環境之間進行高效的應用程序生命周期管理。
Docker和虛擬機的區別
如上圖所示,由於容器所需的資源要少得多(例如,它們不需要一個完整的 OS),所以它們易於部署且可快速啟動。這使你能夠具有更高的密度,也就是說,這允許你在同一硬件單元上運行更多服務,從而降低了成本。
在同一內核上運行的副作用是,你獲得的隔離比 VM 要少。
鏡像的主要目標是使環境(依賴項)在不同的部署中保持不變。 也就是說,可以在計算機上調試它,然后將其部署到保證具有相同環境的另一台計算機上。
借助容器鏡像,可打包應用或服務並采用可靠且可重現的方式對其進行部署。可以說 Docker 不只是一種技術,還是一種原理和過程。
在使用Docker之前,我們經常會聽到,“這個問題在開發環境是正常的!”。而在使用 Docker 后,你不會聽到開發人員說:“為什么它能在我的計算機上使用卻不能用在生產中?”。開發人員只需說“它在 Docker 上運行”,因為打包的 Docker 應用程序可在任何支持的 Docker 環境上執行,而且它在所有部署目標(例如,開發、QA、暫存和生產)上都按預期運行。
基本概念
鏡像:一個特殊的文件系統
操作系統分為內核和用戶空間。對於 Linux 而言,內核啟動后,會掛載 root 文件系統為其提供用戶空間支持。而 Docker 鏡像(Image),就相當於是一個 root 文件系統。
Docker 鏡像是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時准備的一些配置參數(如匿名卷、環境變量、用戶等)。
鏡像不包含任何動態數據,其內容在構建之后也不會被改變。
Docker 設計時,就充分利用 Union FS 的技術,將其設計為分層存儲的架構。 鏡像實際是由多層文件系統聯合組成。
鏡像構建時,會一層層構建,前一層是后一層的基礎。每一層構建完就不會再發生改變,后一層上的任何改變只發生在自己這一層。
比如,刪除前一層文件的操作,實際不是真的刪除前一層的文件,而是僅在當前層標記為該文件已刪除。
在最終容器運行的時候,雖然不會看到這個文件,但是實際上該文件會一直跟隨鏡像。
因此,在構建鏡像的時候,需要額外小心,每一層盡量只包含該層需要添加的東西,任何額外的東西應該在該層構建結束前清理掉。
分層存儲的特征還使得鏡像的復用、定制變的更為容易。甚至可以用之前構建好的鏡像作為基礎層,然后進一步添加新的層,以定制自己所需的內容,構建新的鏡像。
容器:鏡像運行時的實體
鏡像(Image)和容器(Container)的關系,就像是面向對象程序設計中的類和實例一樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器可以被創建、啟動、停止、刪除、暫停等 。
容器的實質是進程,但與直接在宿主執行的進程不同,容器進程運行於屬於自己的獨立的命名空間。前面講過鏡像使用的是分層存儲,容器也是如此。
容器存儲層的生存周期和容器一樣,容器消亡時,容器存儲層也隨之消亡。因此,任何保存於容器存儲層的信息都會隨容器刪除而丟失。
按照 Docker 最佳實踐的要求,容器不應該向其存儲層內寫入任何數據 ,容器存儲層要保持無狀態化。
所有的文件寫入操作,都應該使用數據卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網絡存儲)發生讀寫,其性能和穩定性更高。
數據卷的生存周期獨立於容器,容器消亡,數據卷不會消亡。因此, 使用數據卷后,容器可以隨意刪除、重新 run,數據卻不會丟失。
注意:
容器在整個應用程序生命周期工作流中提供以下優點:隔離性、可移植性、靈活性、可伸縮性和可控性。 最重要的優點是可在開發和運營之間提供隔離。
倉庫:集中存放鏡像文件的地方
鏡像構建完成后,可以很容易的在當前宿主上運行,但是, 如果需要在其他服務器上使用這個鏡像,我們就需要一個集中的存儲、分發鏡像的服務,Docker Registry 就是這樣的服務。
一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標簽(Tag);每個標簽對應一個鏡像。
所以說,鏡像倉庫是 Docker 用來集中存放鏡像文件的地方,類似於我們之前常用的代碼倉庫。
通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標簽就常用於對應該軟件的各個版本 。
我們可以通過<倉庫名>:<標簽>的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標簽,將以 latest 作為默認標簽。
這里補充一下 Docker Registry 公開服務和私有 Docker Registry 的概念:
Docker Registry 公開服務是開放給用戶使用、允許用戶管理鏡像的 Registry 服務。
一般這類公開服務允許用戶免費上傳、下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。
最常使用的 Registry 公開服務是官方的 Docker Hub ,這也是默認的 Registry,並擁有大量的高質量的官方鏡像,網址為:hub.docker.com/ 。
在國內訪問 Docker Hub 可能會比較慢,國內也有一些雲服務商提供類似於 Docker Hub 的公開服務。
除了使用公開服務外,用戶還可以在本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry 鏡像,可以直接使用做為私有 Registry 服務。
開源的 Docker Registry 鏡像只提供了 Docker Registry API 的服務端實現,足以支持 Docker 命令,不影響使用。但不包含圖形界面,以及鏡像維護、用戶管理、訪問控制等高級功能。
Docker的主要應用場景
簡化配置
虛擬機的最大好處是能在你的硬件設施上運行各種配置不一樣的平台(軟件、系統),Docker在降低額外開銷的情況下提供了同樣的功能。它能讓你將運行環境和配置放在代碼中然后部署,同一個Docker的配置可以在不同的環境中使用,這樣就降低了硬件要求和應用環境之間耦合度。
簡單的來說,容器鏡像打包完成后,它就是個獨立的個體了,丟到哪里都能跑,而無需針對各個平台去獨立配置。
代碼流水線(Code Pipeline)管理
前一個場景對於管理代碼的流水線起到了很大的幫助。代碼從開發者的機器到最終在生產環境上的部署,需要經過很多的中間環境。而每一個中間環境都有自己微小的差別,Docker給應用提供了一個從開發到上線均一致的環境,讓代碼的流水線變得簡單不少。
提高開發效率
不同的開發環境中,我們都想把兩件事做好。一是我們想讓開發環境盡量貼近生產環境,二是我們想快速搭建開發環境。
使用Docker非常簡單的就能夠實現這兩點,而且哪怕是開發環境的機器配置一般的情況下搭建多個生成服務應用。一台一般配置服務器或開發機也能輕松的跑起多個Docker應用,而無需額外增加機器配置。因為Docker有個非常NB的特性,擁有虛擬化的特性,而幾乎沒有額外的開銷。
隔離應用
很多情況下,我們需要在一台服務器上運行多個不同的應用,比如上面提到的提高開發效率的場景等。
我們經常需要考慮三點,一是因為要降低成本而進行服務器整合,二是將一個整體式的應用拆分成松耦合的單個服務(比如微服務架構),三是還需要考慮應用之間的兼容性。而對於Docker來說,支持起來就非常簡單了。同一台機器,我可以同時運行N個Docker web應用,托管到不同的Web服務器(Kestrel、Ngnix、Tomcat),而無需擔心他們會搞起3Q大戰,也無需擔心我的開發機器會跑不起來。
整合服務器
正如通過虛擬機來整合多個應用,Docker隔離應用的能力使得Docker可以整合多個服務器以降低成本。由於沒有多個操作系統的內存占用,以及能在多個實例之間共享沒有使用的內存,Docker可以比虛擬機提供更好的服務器整合解決方案。
這就意味着資源得到更有效的利用——可以做更多衣服,而且還沒有邊角料,成本還更低。
調試能力
Docker提供了很多的工具,這些工具不一定只是針對容器,但是卻適用於容器。它們提供了很多的功能,包括可以為容器設置檢查點、設置版本和查看兩個容器之間的差別,這些特性可以幫助調試Bug。
多租戶環境
在多租戶的應用中,它可以避免關鍵應用的重寫。比如IoT(物聯網)的應用中,開發一個快速、易用的多租戶環境。這種多租戶的基本代碼非常復雜,很難處理,重新規划這樣一個應用不但消耗時間,也浪費金錢。
使用Docker,可以為每一個租戶的應用層的多個實例創建隔離的環境,這不僅簡單而且成本低廉,當然這一切得益於Docker環境的啟動速度和其高效的diff命令。
就如同我們現在寫了一個不支持多租戶的業務程序,而實際的業務中經常會出現需要支持多租戶或者有新客戶需要使用的場景,這是我們通常的簡單做法是——部署一套新的代碼。當站點達到一定量的適合,要么重寫程序,要么維護人員Game over。
快速部署
在虛擬機之前,引入新的硬件資源需要消耗幾天的時間。虛擬化技術(Virtualization)將這個時間縮短到了分鍾級別。而Docker通過為進程僅僅創建一個容器而無需啟動一個操作系統,再次將這個過程縮短到了秒級。
你可以在服務器中或雲端創建銷毀資源而無需擔心重新啟動帶來的開銷。通常情況下,服務器的資源利用率只有30%,而通過使用Docker並進行有效的資源分配可以提高資源的利用率。
市場實際反饋和調查
我們來看一份2016年用戶調查結果。
Docker為軟件供應鏈提供了應用程序開發的敏捷性,可控性和可移值性
- 用戶如何使用 Docker?
-
90% 的用戶使用 Docker 進行應用開發
-
65% 的用戶使用 Docker 進行敏捷開發
-
58% 的用戶將 Docker 用於生產
-
48% 的用戶使用 Docker 控制應用環境
-
41% 的用戶使用 Docker 實現應用的可移植性
- Docker 的業務覆蓋:
-
78%:網頁應用
-
75%:網頁 API
-
70%:應用服務端
-
42%:傳統數據庫
-
27%:分布式數據庫
-
13%:大數據
Docker 帶來的敏捷性(響應速度和靈活性)吸引了越來越多的開發者。他們不僅能知道容器內部到底跑了什么,也能進一步理解 Docker 如何加速了軟件開發進程。另外,41% 的用戶表示應用的可移植性是他們決定使用 Docker 的關鍵因素。
通過 DevOps 的實踐,Docker 正在給應用交付帶來很多可以量化的提升
如圖所示:
-
93% 的 Docker 用戶已經在開發過程中獲得了益處
-
85% 的 Docker 用戶已經在運維過程中獲得了益處
-
57% 的 Docker 用戶見證了運維環境管理的提升
-
45% 的 Docker 用戶已經提高了軟件發布的頻率
大約一半的受訪者表示已經采用了持續集成(CI)和 DevOps,並且希望把這些實戰經驗應用到生產環境的持續交付中。剩下的受訪者則准備盡快跟上步伐,盡快嘗試 DevOps 和持續集成。另外,據調查顯示,用戶使用 Docker 發布應用的頻率平均提升了 13 倍。
Docker 對混合雲策略至關重要,它使得用戶可以根據需求自由選擇私有和公有環境
如圖所示:
-
80% 的用戶表示 Docker 已經是雲策略的一部分
-
60% 的用戶則正在計划使用 Docker 將業務遷移到雲端。
-
41% 的用戶希望實現跨環境的應用移植
-
35+% 的用戶希望避免被雲供應商綁定
通過容器來交付的應用可以在任何基礎設施之上靈活遷移,同時這些基礎設施又可以提供不同層次的應用管理方式,而當業務在多個服務供應商之中尋求混合雲或全雲模式時,又可以完美避免被平台捆綁。
對於按需部署或部署到雲環境,Docker 提供了獨一無二的選擇。 80% 的用戶表示 Docker 已經成為他們雲策略的一部分,超過 35% 的用戶使用 Docker 來避免被雲服務供應商綁定。
Docker 實現了微服務架構,也讓遺留的單體應用轉變為現代應用
如圖所示:
-
65% 的組織面對遺留應用這一難題
-
59% 的組織受到遺留應用和基礎設施僵化的影響
-
44% 的組織正在使用微服務架構
-
39% 的組織讓遺留應用煥發新生
Docker 使得微服務架構的快速發展成為可能,同時它也將傳統的業務遷移到容器環境中,以此使得應用程序變得更加可移植。使用微服務架構進行交付是 Docker 的關鍵優勢!
Docker改變了什么?
綜上所述,Docker到底改變了什么?筆者是這么理解的:
-
Docker改變了雲服務,使雲服務的共融共通的理想逐步成為了可能。並且Docker 已經是雲策略的一部分,許多開發者正在計划使用 Docker 將業務遷移到雲端。另外,為了避免被雲服務供應商綁定,Docker成為很多開發者的首選。
-
Docker改變了產品交付,為產品的整個生命周期提供了一整套的解決方案和流程。
-
Docker改變了開發方式,提供了簡化的環境配置、封裝的運行環境以及統一的環境。並且提供了快速部署的方式。
-
Docker改變了測試,多版本測試變得極為方便,快速構建測試環境也變得更加簡單並且無需開發人員干預或者搭建。
-
Docker改變了運維,環境的一致性讓運維變得更加簡單,同時熱更新的支持讓運維不再需要半夜加班部署更新,更新可以隨時進行。當出現重大問題時,還能快速回滾到指定版本。
-
Docker改變了架構,自動化擴容支持讓架構變得更加簡單,分布式系統也更加易於搭建和支持。同時遺留的單體應用也很易於轉變為現代應用。
總之,在某種程度上,Docker改變了產品開發中的一些游戲規則。雖然Docker是一項技術,但是它也帶來了新的思維,新的流程和工作方法,Docker在推動行業的發展,Docker已經在改變世界,並且在逐步的變為事實……