文章目錄
- 前言
- 一、docker歷史
- 二、docker系統
- 三、docker容器與鏡像
前言
??從過去以物理機和虛擬機為主體的開發運維環境,向以容器為核心的基礎設施的轉變程序,并不是一次溫和的改革,而是涵蓋了對網路、存盤、調度、作業系統、分布式原理等各個方面的容器化理解和改造,2013 年的后端技術領域,已經太久沒有出現過令人興奮的東西了,曾經被人們寄予厚望的云計算技術,也已經從當初虛無縹緲的概念蛻變成了實實在在的虛擬機和賬單,而相比于如日中天 AWS 和盛極一時的 OpenStack,以 Cloud Foundry 為代表的開源 PaaS 專案,卻成為了當時云計算技術中的一股清流, 當時,Cloud Foundry 專案已經基本度過了最艱難的概念普及和用戶教育階段,吸引了包括百度、京東、華為、IBM 等一大批國內外技術廠商,開啟了以開源 PaaS 為核心構建平臺層服務能力的變革,如果你有機會問問當時的云計算從業者們,他們十有八九都會告訴你:PaaS 的時代就要來了!這個說法其實一點兒沒錯,如果不是后來一個叫 Docker 的開源專案突然冒出來的話,
一、docker歷史
??事實上,當時還名叫 dotCloud 的 Docker 公司,也是這股 PaaS 熱潮中的一份子,只不過相比于 Heroku、Pivotal、Red Hat 等 PaaS 弄潮兒們,dotCloud 公司實在是太微不足道了,而它的主打產品由于跟主流的 Cloud Foundry 社區脫節,長期以來也無人問津,眼看就要被如火如荼的 PaaS 風潮拋棄,dotCloud 公司卻做出了這樣一個決定:開源自己的容器專案 Docker,顯然,這個決定在當時根本沒人在乎,
??PaaS 專案被大家接納的一個主要原因,就是它提供了一種名叫"應用托管"的能力, 在當時,虛擬機和云計算已經是比較普遍的技術和服務了,那時主流用戶的普遍用法,就是租一批 AWS 或者 OpenStack 的虛擬機,然后像以前管理物理服務器那樣,用腳本或者手工的方式在這些機器上部署應用,當然,這個部署程序難免會碰到云端虛擬機和本地環境不一致的問題,所以當時的云計算服務,比的就是誰能更好地模擬本地服務器環境,能帶來更好的"上云"體驗,而 PaaS 開源專案的出現,就是當時解決這個問題的一個最佳方案,
??舉個例子,虛擬機創建好之后,運維人員只需要在這些機器上部署一個 Cloud Foundry 專案,然后開發者只要執行一條命令就能把本地的應用部署到云上,這條命令就是:
??$ cf push " 我的應用 "
??是不是很神奇?
??事實上,像 Cloud Foundry 這樣的 PaaS 專案,最核心的組件就是一套應用的打包和分發機制, Cloud Foundry 為每種主流編程語言都定義了一種打包格式,而"cf push"的作用,基本上等同于用戶把應用的可執行檔案和啟動腳本打進一個壓縮包內,上傳到云上 Cloud Foundry 的存盤中,接著,Cloud Foundry 會通過調度器選擇一個可以運行這個應用的虛擬機,然后通知這個機器上的 Agent 把應用壓縮包下載下來啟動, 這時候關鍵來了,由于需要在一個虛擬機上啟動很多個來自不同用戶的應用,Cloud Foundry 會呼叫作業系統的 Cgroups 和 Namespace 機制為每一個應用單獨創建一個稱作"沙盒"的隔離環境,然后在"沙盒"中啟動這些應用行程,這樣,就實作了把多個用戶的應用互不干涉地在虛擬機里批量地、自動地運行起來的目的, 這正是 PaaS 專案最核心的能力, 而這些 Cloud Foundry 用來運行應用的隔離環境,或者說"沙盒",就是所謂的"容器",
??而 Docker 專案,實際上跟 Cloud Foundry 的容器并沒有太大不同,所以在它發布后不久,Cloud Foundry 的首席產品經理 James Bayer 就在社區里做了一次詳細對比,告訴用戶 Docker 實際上只是一個同樣使用 Cgroups 和 Namespace 實作的"沙盒"而已,沒有什么特別的黑科技,也不需要特別關注, 然而,短短幾個月,Docker 專案就迅速崛起了,它的崛起速度如此之快,以至于 Cloud Foundry 以及所有的 PaaS 社區還沒來得及成為它的競爭對手,就直接被宣告出局了,那時候,一位多年的 PaaS 從業者曾經如此感慨道:這簡直就是一場"降維打擊"啊, 事實上,Docker 專案確實與 Cloud Foundry 的容器在大部分功能和實作原理上都是一樣的,可偏偏就是這剩下的一小部分不一樣的功能,成了 Docker 專案接下來"呼風喚雨"的不二法寶,這個功能,就是 Docker 鏡像,
??恐怕連 Docker 專案的作者 Solomon Hykes 自己當時都沒想到,這個小小的創新,在短短幾年內就如此迅速地改變了整個云計算領域的發展歷程,最后結局就是,"cf push"確實是能一鍵部署了,但是為了實作這個一鍵部署,用戶為每個應用打包的作業可謂一波三折,費盡心機,而Docker 鏡像解決的,恰恰就是打包這個根本性的問題, 所謂 Docker 鏡像,其實就是一個壓縮包,但是這個壓縮包里的內容,比 PaaS 的應用可執行檔案 + 啟停腳本的組合就要豐富多了,實際上,大多數 Docker 鏡像是直接由一個完整作業系統的所有檔案和目錄構成的,所以這個壓縮包里的內容跟你本地開發和測驗環境用的作業系統是完全一樣的,
??這就有意思了:假設你的應用在本地運行時,能看見的環境是 CentOS 7.2 作業系統的所有檔案和目錄,那么只要用 CentOS 7.2 的 ISO 做一個壓縮包,再把你的應用可執行檔案也壓縮進去,那么無論在哪里解壓這個壓縮包,都可以得到與你本地測驗時一樣的環境,當然,你的應用也在里面!這就是 Docker 鏡像最厲害的地方: 只要有這個壓縮包在手,你就可以使用某種技術創建一個"沙盒",在"沙盒"中解壓這個壓縮包,然后就可以運行你的程式了,更重要的是,這個壓縮包包含了完整的作業系統檔案和目錄,也就是包含了這個應用運行所需要的所有依賴,所以你可以先用這個壓縮包在本地進行開發和測驗,完成之后,再把這個壓縮包上傳到云端運行, 在這個程序中,你完全不需要進行任何配置或者修改,因為這個壓縮包賦予了你一種極其寶貴的能力:本地環境和云端環境的高度一致!這正是 Docker 鏡像的精髓,
??那么,有了 Docker 鏡像這個利器,PaaS 里最核心的打包系統一下子就沒了用武之地,最讓用戶抓狂的打包程序也隨之消失了,相比之下,在當今的互聯網里,Docker 鏡像需要的作業系統檔案和目錄,可謂唾手可得,所以,你只需要提供一個下載好的作業系統檔案與目錄,然后使用它制作一個壓縮包即可,這個命令就是:
??$ docker build " 我的鏡像 "
??一旦鏡像制作完成,用戶就可以讓 Docker 創建一個"沙盒"來解壓這個鏡像,然后在"沙盒"中運行自己的應用,這個命令就是:
??$ docker run " 我的鏡像 "
??當然,docker run 創建的"沙盒",也是使用 Cgroups 和 Namespace 機制創建出來的隔離環境,
??不過,Docker 專案固然解決了應用打包的難題,但正如前面所介紹的那樣,它并不能代替 PaaS 完成大規模部署應用的職責,遺憾的是,考慮到 Docker 公司是一個與自己有潛在競爭關系的商業物體,再加上對 Docker 專案普及程度的錯誤判斷,Cloud Foundry 專案并沒有第一時間使用 Docker 作為自己的核心依賴,去替換自己那套飽受詬病的打包流程,反倒是一些機敏的創業公司,紛紛在第一時間推出了 Docker 容器集群管理的開源專案(比如 Deis 和 Flynn),它們一般稱自己為 CaaS,即 Container-as-a-Service,用來跟"過時"的 PaaS 們劃清界限,而在 2014 年底的 DockerCon 上,Docker 公司雄心勃勃地對外發布了自家研發的"Docker 原生"容器集群管理專案 Swarm,不僅將這波"CaaS"熱推向了一個前所未有的高潮,更是寄托了整個 Docker 公司重新定義 PaaS 的宏偉愿望,
在 2014 年的這段巔峰歲月里,Docker 公司離自己的理想真的只有一步之遙,2013~2014 年,以 Cloud Foundry 為代表的 PaaS 專案,逐漸完成了教育用戶和開拓市場的艱巨任務,也正是在這個將概念逐漸落地的程序中,應用"打包"困難這個問題,成了整個后端技術圈子的一塊心病,Docker 專案的出現,則為這個根本性的問題提供了一個近乎完美的解決方案,這正是 Docker 專案剛剛開源不久,就能夠帶領一家原本默默無聞的 PaaS 創業公司脫穎而出,然后迅速占領了所有云計算領域頭條的技術原因, 而在成為了基礎設施領域近十年難得一見的技術明星之后,dotCloud 公司則在 2013 年底大膽改名為 Docker 公司,不過,這個在當時就頗具爭議的改名舉動,也成為了日后容器技術圈風云變幻的一個關鍵伏筆,
??在過去的很長一段時間里,相較于前端和互聯網技術社區,服務器端技術社區一直是一個相對沉悶而小眾的圈子,在這里,從事 Linux 內核開發的極客們自帶"不合群"的"光環",后端開發者們啃著多年不變的 TCP/IP 發著牢騷,運維更是天生注定的幕后英雄,而 Docker 專案,卻給后端開發者提供了走向聚光燈的機會,就比如 Cgroups 和 Namespace 這種已經存在多年卻很少被人們關心的特性,在 2014 年和 2015 年竟然頻繁入選各大技識訓議的分享議題,就因為聽眾們想要知道 Docker 這個東西到底是怎么一回事兒,而 Docker 專案之所以能取得如此高的關注,一方面正如前面所說的那樣,它解決了應用打包和發布這一困擾運維人員多年的技術難題;而另一方面,就是因為它第一次把一個純后端的技術概念,通過非常友好的設計和封裝,交到了最廣大的開發者群體手里,在這種獨特的氛圍烘托下,你不需要精通 TCP/IP,也無需深諳 Linux 內核原理,哪怕只是一個前端或者網站的 PHP 工程師,都會對如何把自己的代碼打包成一個隨處可以運行的 Docker 鏡像充滿好奇和興趣,
??這種受眾群體的變革,正是 Docker 這樣一個后端開源專案取得巨大成功的關鍵,這也是經典 PaaS 專案想做卻沒有做好的一件事情:PaaS 的最終用戶和受益者,一定是為這個 PaaS 撰寫應用的開發者們,而在 Docker 專案開源之前,PaaS 與開發者之間的關系卻從未如此緊密過,解決了應用打包這個根本性的問題,同開發者與生俱來的的親密關系,再加上 PaaS 概念已經深入人心的完美貧訓,成為 Docker 這個技術上看似平淡無奇的專案一舉走紅的重要原因,
二、docker系統
Docker系統有兩個程式:docker服務端和docker客戶端
?docker服務端:
??是一個服務行程,管理著所有的容器,
?docker客戶端:
??扮演著docker服務端的遠程控制器,可以用來控制docker的服務端行程,

Docker三大核心組件:
?Docker 鏡像 - Docker images
?Docker 倉庫 - Docker registeries
?Docker 容器 - Docker containers
??docker倉庫用于存盤鏡像,包含公有倉庫(docker-hub daocloud ali)和私有倉庫(公司自建)
??docker鏡像由鏡像名與tag號組成,是 Docker 容器運行時的只讀模板,每一個鏡像由一系列的層 (layers) 組成,Docker 使用 UnionFS 來將這些層聯合到單獨的鏡像中,UnionFS 允許獨立檔案系統中的檔案和檔案夾(稱之為分支)被透明覆寫,形成一個單獨連貫的檔案系統,正因為有了這些層的存在,Docker 是如此的輕量,當你改變了一個 Docker 鏡像,比如升級到某個程式到新的版本,一個新的層會被創建,因此,不用替換整個原先的鏡像或者重新建立(在使用虛擬機的時候你可能會這么做),只是一個新的層被添加或升級了,現在你不用重新發布整個鏡像,只需要升級,層使得分發 Docker 鏡像變得簡單和快速,
??由于 Docker 使用一個統一檔案系統,Docker 行程認為整個檔案系統是以讀寫方式掛載的, 但是所有的變更都發生頂層的可寫層,而下層的原始的只讀鏡像檔案并未變化,由于鏡像不可寫,所以鏡像是無狀態的,
??每一個鏡像都可能依賴于由一個或多個下層的組成的另一個鏡像,下層那個鏡像是上層鏡像的父鏡像,一個沒有任何父鏡像的鏡像,謂之基礎鏡像,
?

?
??Docker 容器和檔案夾很類似,一個Docker容器包含了所有的某個應用運行所需要的環境,每一個 Docker 容器都是從 Docker 鏡像創建的,Docker 容器可以運行、開始、停止、移動和洗掉,每一個 Docker 容器都是獨立和安全的應用平臺,Docker 容器是 Docker 的運行部分,
三、docker容器與鏡像
Docker鏡像
??假設Linux內核是第0層,那么無論怎么運行Docker,它都是運行于內核層之上的,這個Docker鏡像,是一個只讀的鏡像,位于第1層,它不能被修改或不能保存狀態,
??一個Docker鏡像可以構建于另一個Docker鏡像之上,這種層疊關系可以是多層的,第1層的鏡像層我們稱之為基礎鏡像(Base Image),其他層的鏡像(除了最頂層)我們稱之為父層鏡像(Parent Image),這些鏡像繼承了他們的父層鏡像的所有屬性和設定,并在Dockerfile中添加了自己的配置,
?? Docker鏡像通過鏡像ID進行識別,鏡像ID是一個64字符的十六進制的字串,但是當我們運行鏡像時,通常我們不會使用鏡像ID來參考鏡像,而是使用鏡像名來參考,
Docker容器
??Docker容器,它會在所有的鏡像層之上增加一個可寫層,這個可寫層是運行在CPU上的行程,而且有兩個不同的狀態:運行態(Running)和退出態 (Exited),
??當我們使用docker run啟動容器,Docker容器就進入運行態,當我們停止Docker容器時,它就進入退出態,當我們有一個正在運行的Docker容器時,從運行態到停止態,我們對它所做的一切變更都會永久地寫到容器的檔案系統中,對容器的變更是寫入到容器的檔案系統的,而不是寫入到Docker鏡像中的,我們可以用同一個鏡像啟動多個Docker容器,這些容器啟動后都是活動的,彼此還是相互隔離的,我們對其中一個容器所做的變更只會局限于那個容器本身,
??如果對容器的底層鏡像進行修改,那么當前正在運行的容器是不受影響的,不會發生自動更新現象,因為docker會從鏡像層復制一份資料到讀寫層,然后對讀寫層的資料修改,所以所有對容器的改動,無論添加、洗掉、還是修改檔案都只會發生在容器層中,只有容器層是可寫的,容器層下面的所有鏡像層都是只讀的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290773.html
標籤:其他
