Docker最全教程——從理論到實戰(一)

雪雁發表於2018-11-28

容器是應用走向雲端之後必然的發展趨勢,因此筆者非常樂於和大家分享我們這段時間對容器的理解、心得和實踐。

本篇教程持續編寫了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已經在改變世界,並且在逐步的變為事實……

 

相關文章