這周分享的內(nèi)容是關(guān)于 Docker 的基礎(chǔ),大概的內(nèi)容分為下面的兩個(gè)部分,另外還做了個(gè)視頻,其實(shí)這個(gè)視頻僅僅用來(lái)娛樂(lè)娛樂(lè)而已。
前言
第一趴---Docker容器圈簡(jiǎn)介
Docker容器圈簡(jiǎn)介
第二趴---Docker基本操作
Docker基本操作
容器圈
容器這個(gè)新生事物,現(xiàn)在還可以說(shuō)是新生事物嗎?對(duì)于我們學(xué)生而言,我覺(jué)得沒(méi)毛病,你說(shuō)呢?
容器技術(shù)可說(shuō)重塑了整個(gè)云計(jì)算市場(chǎng)的形態(tài),帶動(dòng)了一批年輕有為的容器技術(shù)兒,不過(guò)「容器」這個(gè)概念是Docker公司發(fā)明的么,不是,它只是眾多Paas項(xiàng)目中的最底層,沒(méi)人關(guān)注的那一部分而已。
什么是Pass項(xiàng)目?
Paas項(xiàng)目之所會(huì)被很多公司所接受,自然是因?yàn)榻夥帕瞬糠珠_(kāi)發(fā)人員的勞動(dòng)力,盡快干玩活兒早點(diǎn)下班。其依賴的就是「應(yīng)用托管」的能力,在電腦上斗過(guò)地主的應(yīng)該知道,托管了以后就會(huì)自動(dòng)出牌,同樣的道理,為了盡量的彌補(bǔ)本地和云上的環(huán)境差異,就出現(xiàn)了Paas開(kāi)源項(xiàng)目。
舉個(gè)例子來(lái)說(shuō),運(yùn)維人員小仙云上部署一個(gè)Cloud Foundry項(xiàng)目,開(kāi)發(fā)人員只需要簡(jiǎn)單的一行代碼就可以實(shí)現(xiàn)將本地的應(yīng)用部署到云上
就這樣一行代碼就實(shí)現(xiàn)了將本地應(yīng)用上傳到云上,屬實(shí)很輕松。
那么這個(gè)命令執(zhí)行的基本原理是怎樣的?
實(shí)際上,我們可以將其最核心的組件理解為一套應(yīng)用的打包和分發(fā)機(jī)制。云上部署的Cloud Foundry會(huì)為大部分編程語(yǔ)言定義一種打包的格式,當(dāng)開(kāi)發(fā)人員執(zhí)行命令的時(shí)候,實(shí)際上是將可執(zhí)行文件和啟動(dòng)腳本打包上傳到云上的Coulud Foudry中,然后Cloud Foundry通過(guò)相應(yīng)的調(diào)度器選擇一個(gè)虛擬機(jī)的Agent將壓縮包下載后啟動(dòng)
那如何區(qū)分虛擬機(jī)中的不同應(yīng)用呢?
虛擬機(jī)一般不可能只跑一個(gè)應(yīng)用,因?yàn)檫@樣確實(shí)也太浪費(fèi)資源了,我們可以想想,現(xiàn)在手上的電腦,可以用Vmvare導(dǎo)入幾個(gè)虛擬機(jī),所以諸如Cloud Foundry通過(guò)引入操作系統(tǒng)的Cgroups和Namespace等機(jī)制,從而來(lái)為每個(gè)應(yīng)用單獨(dú)創(chuàng)建一個(gè)叫做「沙盒」的隔離環(huán)境,然后在這些「沙盒」中啟動(dòng)應(yīng)用,通過(guò)這樣的方法就讓虛擬機(jī)中應(yīng)用各自互不干擾,讓其自由翱翔,至于Cgroups和 Namespace 的實(shí)現(xiàn)原理,后續(xù)我們?cè)俟餐奶接?/p>
這里所謂的隔離環(huán)境就是「容器」。
那 Docker 和這 Pass 項(xiàng)目的 Cloud Foundry 的容器有啥不一樣?
自然不一樣,不然現(xiàn)在我們一旦提到容器,想到的不會(huì)是Docker,而是Cloud Foundry了吧。Cloud Foundry的首席產(chǎn)品經(jīng)理就覺(jué)得沒(méi)什么,畢竟自己放的屁都是香的!
不一樣,而且當(dāng)時(shí)還發(fā)了一份報(bào)告,報(bào)告中還寫到:“Docker不就是使用了 Cgroups和 Namespace實(shí)現(xiàn)的「沙盒」而已,不用過(guò)于關(guān)注”。
沒(méi)想到的是,隨后短短的幾個(gè)月,Docker項(xiàng)目迅速起飛以至于其他所有 Paas社區(qū)都還沒(méi)來(lái)及反應(yīng)過(guò)來(lái),就已經(jīng)宣告出局
什么魔力讓 Docker 一發(fā)不可收拾?
就是提出了鏡像的概念。上面我們說(shuō)過(guò),Paas提供的一套應(yīng)用打包的功能,看起很輕松省事,但是一旦使用了Paas,你就要終身服務(wù)于它,畢竟他是提供商,是「爸爸」,用戶需要為每個(gè)版本,每種語(yǔ)言去維護(hù)一個(gè)包,這個(gè)打包的過(guò)程是需要多次的嘗試,多次試錯(cuò)后,才能摸清本地應(yīng)用和遠(yuǎn)端Paas的脾氣,從而順利部署。
而Docker 鏡像恰恰就是解決了打包這一根本問(wèn)題。
什么是Docker鏡像?
Docker鏡像也是一個(gè)壓縮包,只是這個(gè)壓縮包不只是可執(zhí)行文件,環(huán)境部署腳本,它還包含了完整的操作系統(tǒng)。因?yàn)榇蟛糠值溺R像都是基于某個(gè)操作系統(tǒng)來(lái)構(gòu)建,所以很輕松的就可以構(gòu)建本地和遠(yuǎn)端一樣的環(huán)境。
這就很牛皮了,如果我們的應(yīng)用是在Centos7上部署,我們只需要將項(xiàng)目環(huán)境部署在基于Centos7的環(huán)境中,然后無(wú)論在哪里去解壓這個(gè)壓縮包,都可以保證環(huán)境的一致性。在整個(gè)過(guò)程中,我們根本不需要進(jìn)行任何的配置,因?yàn)檫@個(gè)壓縮包可以保證:本地的環(huán)境和云端是一致的,這也是Docker鏡像的精髓
開(kāi)發(fā)者體驗(yàn)到了Docker的便利,從而很快宣布Paas時(shí)代的結(jié)束,不過(guò)對(duì)于大規(guī)模應(yīng)用的部署,Docker能否實(shí)現(xiàn)在當(dāng)時(shí)還是個(gè)問(wèn)號(hào)
就在 2014 年的DockerCon上,緊接著發(fā)布了自研的「Docker swarm」,Docker就這樣 一度奔向高潮,即將就到達(dá)了自己夢(mèng)想之巔。
為什么會(huì)推出Docker Swarm?
雖然Docker通過(guò)「容器」完成了對(duì)Paas的「降維打擊」,但是Docker的目的是:如何讓更多的開(kāi)發(fā)者將項(xiàng)目部署在自己的項(xiàng)目上,從技術(shù),商業(yè),市場(chǎng)多方位的爭(zhēng)取開(kāi)發(fā)者的群體,為此形成自家的 Paas平臺(tái)做鋪墊
Docker項(xiàng)目雖然很受歡迎,就目前看來(lái)只是一個(gè)創(chuàng)建和啟動(dòng)容器的小工具。需要應(yīng)該清楚的一點(diǎn)是,用戶最終部署的還是他們的網(wǎng)站,服務(wù)甚至云計(jì)算業(yè)務(wù)。所以推出一個(gè)完整的整體對(duì)外提供集群管理功能的Swarm勢(shì)在必行,這個(gè)項(xiàng)目中的最大亮點(diǎn)即直接使用了Docker原生的API來(lái)完成對(duì)集群的管理。
對(duì)于單機(jī)項(xiàng)目,只需要執(zhí)行下面一條語(yǔ)句即可實(shí)現(xiàn)容器
對(duì)于多機(jī)的項(xiàng)目,只需要執(zhí)行
你看,從單機(jī)切換到多機(jī),使用的方法也就參數(shù)不同而已,所以這樣一個(gè)原生的「Docker容器集群管理」一發(fā)布就受到大家的青睞。隨著自身生態(tài)的逐漸完善,借助這一波浪潮并通過(guò)各種并購(gòu)來(lái)強(qiáng)大自己的平層能力
要說(shuō)最成功的案例,非Fig項(xiàng)目莫屬。之所以這么屌,是因?yàn)樽髡咛岢隽恕溉萜骶幣拧沟母拍睢?/p>
什么是容器編排?
其實(shí)這也不是什么新鮮內(nèi)容,比如在Linux中的Makefile和常見(jiàn)的SHELL腳本,它是一種通過(guò)工具或者配置來(lái)完成一組虛擬機(jī)或者關(guān)聯(lián)資源的定義、配置、創(chuàng)建等工具。
容器的編排是怎么樣的呢
我們先以 Fig 為例,假設(shè)開(kāi)發(fā)人員小黑,現(xiàn)在要部署一個(gè)項(xiàng)目,其中包含了應(yīng)用容器A,數(shù)據(jù)庫(kù)容器B,負(fù)載容器C,這個(gè)時(shí)候Fig只需要將三個(gè)容器定義在一個(gè)配置文件,然后指定他們的關(guān)聯(lián)關(guān)系,執(zhí)行下面的命令即可
當(dāng)然也可以在Fig的配置文件中配置各種容器的副本,然后加上Swarm的集群管理功能,這樣不就是Paas了么。只是這個(gè)項(xiàng)目被收購(gòu)以后,修改名字為compose了,后續(xù)也會(huì)的compose進(jìn)行詳細(xì)的闡述
就這樣一個(gè)以「鯨魚」為商標(biāo)的Docker,火遍全球,因?yàn)樗謱ⅰ搁_(kāi)發(fā)者」群體放在食物鏈的頂端。一分鐘實(shí)現(xiàn)網(wǎng)站的部署,三分鐘搭建集群,這么多年以來(lái),很多后端開(kāi)發(fā)者很少將眼光放在Linux技術(shù)上,開(kāi)發(fā)者們?yōu)榱松钊氲牧私釪ocker的技術(shù)原理,終于將眼光放入諸如Cgroups和Namespace技術(shù)中。
就在這一時(shí)之間,后端及云計(jì)算領(lǐng)域的大佬都匯聚于這個(gè)「小鯨魚」的身邊。隨后到了考慮集群的方案,論集群的管理調(diào)度能力,還不得不提Berkeley的Mesos,專注于大數(shù)據(jù)領(lǐng)域,更加關(guān)注的是計(jì)算密集型的業(yè)務(wù)。憑借著它天生的兩層調(diào)度機(jī)制,讓它很快發(fā)布了一個(gè)叫做Marathon的項(xiàng)目,這個(gè)項(xiàng)目隨即成為了Swarm的有力競(jìng)爭(zhēng)對(duì)手。
這還沒(méi)完,說(shuō)了這么久,還沒(méi)有提到在基礎(chǔ)設(shè)施領(lǐng)域翹楚的Google公司,是的,同在這一年,宣告了一個(gè)叫做Kubernetes項(xiàng)目的誕生。
隨著 Docker生態(tài)的建立,Docker swarm,Docker compose,Machine形成了三件套,此時(shí)大量圍繞Docker項(xiàng)目的網(wǎng)絡(luò),存儲(chǔ),監(jiān)控都涌現(xiàn)。在令人興奮的背后,是對(duì)它更多的擔(dān)憂,這主要來(lái)源于對(duì)Docker商業(yè)化戰(zhàn)略的顧慮,Docker公司對(duì)于Docker著絕對(duì)的權(quán)威并在多個(gè)場(chǎng)合直接和谷歌,微軟對(duì)干
其實(shí)在Docker興起的時(shí)候,谷歌也開(kāi)源了一個(gè)Linux容器:Imctfy,在當(dāng)時(shí)這個(gè)項(xiàng)目在Docker面前真是弟弟,所以向Docker公司表示想合作的意愿,Docker顯然不同意,且在之后的不久自己發(fā)布了一個(gè)容器運(yùn)行時(shí)的庫(kù)Libcontainer,可能由于太急躁,其代碼可讀性極差,不穩(wěn)定和頻繁的變更,讓社區(qū)叫苦不迭
為了切割Docker項(xiàng)目的話語(yǔ)權(quán),決定成立一個(gè)中立的基金會(huì)。所以于 2015 年將這個(gè)Libcontainer捐出,并修改名稱為Runc,然后依據(jù)RunC項(xiàng)目,制定了一套容器和鏡像的標(biāo)準(zhǔn)和規(guī)范----OCI
什么是OCI
為了讓Docker不能太囂張,其他玩家構(gòu)建自身平臺(tái)的時(shí)候不依賴于Docker項(xiàng)目,提出一個(gè)標(biāo)準(zhǔn)和規(guī)范----OCI。這一標(biāo)準(zhǔn)并沒(méi)有改變 Docker 在容器領(lǐng)域一家獨(dú)大的現(xiàn)狀。Google 坐不住了,必須得搞點(diǎn)大招
**Google **給RedHat等伙伴打了電話,說(shuō)咱們共同牽頭發(fā)起一個(gè)基金會(huì)-----CNCF。目的很簡(jiǎn)單,以kubernetes為基礎(chǔ),建立一個(gè)以由開(kāi)源基礎(chǔ)設(shè)置主導(dǎo),按照獨(dú)立基金會(huì)方式運(yùn)營(yíng)的平臺(tái)級(jí)社區(qū),來(lái)對(duì)抗Docker公司為核心的容器商業(yè)生態(tài)
為了做好這個(gè)事兒,CNCF 必須完成兩件事兒
必須在編排領(lǐng)取足夠的優(yōu)勢(shì)
CNCF 必須以 kubernetes 為核心,覆蓋更多的場(chǎng)景
CNCF 如何解決第一個(gè)問(wèn)題----編排能力
Swarm的無(wú)縫集成以及Mesos的大規(guī)模集群的調(diào)度管理能力,很明顯,如果繼續(xù)往這兩個(gè)方向發(fā)展,后面的路不一定好走。所以,kubernetes選擇的方式是Borg,其基礎(chǔ)特性是 Google 在容器化基礎(chǔ)設(shè)施多年來(lái)實(shí)踐的經(jīng)驗(yàn),這也正是項(xiàng)目從一開(kāi)始就避免了和Swarm,mesos 社區(qū)同質(zhì)化的重要手段
看似很有技巧,怎么落地?
RedHat正好擅長(zhǎng)這玩意呀,它能真正的理解開(kāi)源社區(qū)運(yùn)作和項(xiàng)目研發(fā)真諦的合作伙伴。作為Docker一方,主要不管的強(qiáng)調(diào)「Docker native」,但是由于kubernetes沒(méi)有跟Swarm展開(kāi)同質(zhì)化的競(jìng)爭(zhēng),所以這個(gè)「Docker Native」的說(shuō)法并沒(méi)有什么殺傷力。反而其獨(dú)特的設(shè)計(jì)理念和號(hào)召力,讓其構(gòu)建了一個(gè)完全與眾不同的容器編排管理生態(tài)。
就這樣很快就把Swarm甩在了身后。隨機(jī)開(kāi)始探討第二個(gè)問(wèn)題,CNCF 添加了一系列容器工具和項(xiàng)目,面對(duì)這樣的壓迫,Docker在2016年決定放棄現(xiàn)有的Swarm項(xiàng)目,而是將容器編排等全部?jī)?nèi)置到Docker項(xiàng)目中。
而kubunetes的應(yīng)對(duì)方案也蠻有意思,開(kāi)啟「民主化架構(gòu)」,kubernetes為開(kāi)發(fā)者暴露可以擴(kuò)展的插件機(jī)制,讓用戶可以隨意的通過(guò)植入代碼的方式介入到kubernetes的每一個(gè)階段,很快,整個(gè)容器圈出現(xiàn)了優(yōu)秀的作品:火熱的微服務(wù)治理項(xiàng)目lstio等
面對(duì)kubernetes的 強(qiáng)力攻擊,Docker公司不得不面對(duì)失敗的事實(shí),只好放棄開(kāi)源社區(qū)專注于商業(yè)化轉(zhuǎn)型,所以于2017年將容器運(yùn)行時(shí)部分containerd捐贈(zèng)給了CNCF,從而將Docker項(xiàng)目改名為Moby,然后交給社區(qū)維護(hù),于 2017 年,**Docker **公司宣布將在企業(yè)版內(nèi)置kubernetes項(xiàng)目,這也標(biāo)志了kubernetes「編排之爭(zhēng)」的結(jié)束
Docker能做什么
Docker是一個(gè)用于開(kāi)發(fā),發(fā)布,運(yùn)行應(yīng)用的程序于一體的開(kāi)放平臺(tái)。如果我們需要將貨物整齊的擺放在船上且互不影響,那么一種可行的方案即通過(guò)集裝箱進(jìn)行標(biāo)準(zhǔn)化,我們將各種貨品通過(guò)集裝箱打包,然后統(tǒng)一的放在船上進(jìn)行運(yùn)輸,Docker其實(shí)就是這樣一個(gè)將各種軟件進(jìn)行打包成集裝箱,然后分發(fā)。
Docker的安裝
Docker是一個(gè)跨平臺(tái)的解決方案,支持各大平臺(tái)比如Centos,Ubuntu等Linux發(fā)行版。下面講述的是在Centos中的使用,安裝
卸載當(dāng)前已經(jīng)存在的舊版Docker,執(zhí)行下面的命令
添加Docker安裝源
安裝最新版本
如果需要安裝指定版本,可以通過(guò)下面命令查看版本并選擇需要的版本
安裝完成,啟動(dòng)Docker
按照國(guó)際案例,先跑一個(gè) helloworld
運(yùn)行上述命令,Docker首先會(huì)檢查本地是否有hello-world這個(gè)鏡像,如果發(fā)現(xiàn)本地沒(méi)有這個(gè)鏡像,Docker就會(huì)去Docker Hub官方倉(cāng)庫(kù)下載此鏡像,然后運(yùn)行它。最后我們看到該鏡像輸出 "Hello from Docker!" 并退出。
Docker核心概念
Docker的操作主要圍繞鏡像,容器,倉(cāng)庫(kù)三大核心概念
什么是鏡像?
一句話說(shuō)即鏡像是Docker容器啟動(dòng)的先決條件,因?yàn)殓R像會(huì)提供容器運(yùn)行的一些基礎(chǔ)文件和配置文件,是容器啟動(dòng)的基礎(chǔ)。說(shuō)白了,要啟動(dòng)容器,需要鏡像來(lái)提供一些基礎(chǔ)環(huán)境。
使用的鏡像的方式有哪些?
自定義創(chuàng)建鏡像。首先找一個(gè)基礎(chǔ)鏡像,比如此鏡像是Centos,然后在此鏡像基礎(chǔ)上自定義需要的內(nèi)容。舉個(gè)例子,基礎(chǔ)鏡像為Centos,先安裝Nginx服務(wù),然后部署咱們的應(yīng)用程序,最后做一些自定義的配置,這樣一個(gè)鏡像就完成了,此鏡像的操作系統(tǒng)是Centos,其中包含了Nginx服務(wù)
從倉(cāng)庫(kù)尋找別人已經(jīng)做好的鏡像。直接去 **Docker hub **或者其他公開(kāi)倉(cāng)庫(kù) 下載即可
什么是容器?
容器是鏡像的運(yùn)行實(shí)體。鏡像是靜態(tài)的只讀文件,可是容器是要運(yùn)行的,需要可寫文件層。所以容器運(yùn)行著真正的應(yīng)用進(jìn)程,所以自然會(huì)有創(chuàng)建,運(yùn)行,停止,暫停和刪除五種狀態(tài)
既然容器是直接運(yùn)行的運(yùn)行程序,那它是有自己的命名空間嘛?
容器有自己獨(dú)立的命名空間和資源限制,意味著在容器內(nèi)部,你無(wú)法看到主機(jī)上面的進(jìn)程,環(huán)境變量等信息,這就是容器和物理機(jī)上的進(jìn)程本質(zhì)區(qū)別
什么是倉(cāng)庫(kù)?
鏡像倉(cāng)庫(kù)類似于代碼倉(cāng)庫(kù),用來(lái)分發(fā)和存儲(chǔ)鏡像,分為公共鏡像和私有鏡像。Docker hub是Docker的官方公開(kāi)鏡像倉(cāng)庫(kù),很多的官方鏡像都可以在上面找到,但是訪問(wèn)很慢,所以可以找國(guó)內(nèi)的鏡像源,當(dāng)然后面我們也會(huì)自己搭建一個(gè)私有鏡像倉(cāng)庫(kù)
三者的關(guān)系是怎么樣的?
上圖清晰的展現(xiàn)了鏡像是容器的基石,容器是在鏡像的基礎(chǔ)上創(chuàng)建的。一個(gè)鏡像可以創(chuàng)建多個(gè)容器,倉(cāng)庫(kù)用來(lái)存放和分發(fā)鏡像
Docker架構(gòu)
容器技術(shù)的發(fā)展可說(shuō)突飛猛進(jìn)了,市面上除了Docker容器還有coreos的 rkt,lxc 等,這么多種容器,是不是需要一個(gè)標(biāo)準(zhǔn)呢,不然就太容易亂套了
你可能會(huì)說(shuō)直接把Docker作為標(biāo)準(zhǔn)不就好了,但是有這么多相關(guān)的容器技術(shù),誰(shuí)不想吃個(gè)好瓜,除此之外,當(dāng)時(shí)的編排的技術(shù)也競(jìng)爭(zhēng)火爆,當(dāng)時(shí)的三主力分別是Docker Swarm,kubernetes以及mesos。作為原生的Docker Swarm自然優(yōu)勢(shì)明顯,但是kubernetes不同意啊,它們覺(jué)得調(diào)度形式太單一了
因此爆發(fā)了容器大戰(zhàn),OCI也就在此出現(xiàn)。
OCI是開(kāi)放的容器標(biāo)準(zhǔn),輕量級(jí)開(kāi)放的治理結(jié)構(gòu),目前主要有兩個(gè)標(biāo)準(zhǔn),分別是容器運(yùn)行時(shí)標(biāo)準(zhǔn)和容器鏡像標(biāo)準(zhǔn)
在如此競(jìng)爭(zhēng)激烈下面,Docker的架構(gòu)成為了下面這個(gè)樣子
Docker的整體架構(gòu)為CS架構(gòu),客戶端和服務(wù)端兩部分組成,客戶端發(fā)送命令,服務(wù)端接受處理指令,其通信的方式有多種,即可以通過(guò)Unix套接字通信,也可以網(wǎng)絡(luò)鏈接遠(yuǎn)程通信
Docker客戶端
我們平時(shí)通常使用Docker命令行的方式和服務(wù)端打交道,其實(shí)還可以通過(guò) **REST API **的方式和Docker服務(wù)端交互,甚至使用各種預(yù)言的sdk和Docker的服務(wù)端交互,美滋滋
Docker服務(wù)端
Docker服務(wù)端是 Docker 后臺(tái)服務(wù)的總稱。其中Dockerd是一個(gè)非常重要的后臺(tái)進(jìn)程,它負(fù)責(zé)響應(yīng)并處理Docker客戶端的請(qǐng)求,然后轉(zhuǎn)化為Docker的具體操作
Docker 重要的組件
我們?nèi)?Docker 默認(rèn)安裝路徑先看看有哪些組件
這里主要說(shuō)明下runc和contained組件
runc:是一個(gè)用來(lái)運(yùn)行容器的輕量級(jí)工具
contained:是容器標(biāo)準(zhǔn)化后的產(chǎn)物,從Dockerd剝離出來(lái),contained通過(guò)contained-shim啟動(dòng)并管理runc,可以說(shuō)contained是真正管理容器的生命周期
通過(guò)上圖,可以看到,dockerd通過(guò)gRPC與containerd通信,由于dockerd與真正的容器運(yùn)行時(shí),runC中間有了containerd這一 OCI標(biāo)準(zhǔn)層,使得dockerd可以確保接口向下兼容。
gRPC是一種遠(yuǎn)程服務(wù)調(diào)用。containerd-shim的意思是墊片,類似于擰螺絲時(shí)夾在螺絲和螺母之間的墊片。containerd-shim的主要作用是將containerd和真正的容器進(jìn)程解耦,使用containerd-shim作為容器進(jìn)程的父進(jìn)程,從而實(shí)現(xiàn)重啟dockerd不影響已經(jīng)啟動(dòng)的容器進(jìn)程。
docker 各個(gè)組件之間的關(guān)系
啟動(dòng)一個(gè)容器
啟動(dòng)完成,通過(guò)下面命令查看 docker 的 pid
此時(shí)發(fā)現(xiàn)其 pid 為 4428,隨后我們查看進(jìn)程之間的關(guān)系
通過(guò) pstree 查看進(jìn)程之間的關(guān)系
注意,docker19 就看不到兩者是父子關(guān)系了
可以先使用 ps aux | grep contained ,然后使用pstree查看 contained 的 pid ,實(shí)際上,Docker 啟動(dòng)的時(shí)候,contained 就啟動(dòng)了,dockerd 和 contained 一直就存在。當(dāng)執(zhí)行了docker run以后,contained 就會(huì)創(chuàng)建 contained-shim 充當(dāng)墊片進(jìn)程,然后啟動(dòng)容器的真正進(jìn)程 sleep 3600,這和架構(gòu)圖一致
075528566666
Docker相關(guān)組件
docker
對(duì)于我們最直觀的即Docker命令,作為Docker客戶端的完整實(shí)現(xiàn),通過(guò)Docker命令來(lái)實(shí)現(xiàn)所有的Docker客戶與服務(wù)端的通信
Docker 客戶端于服務(wù)端的交互過(guò)程是怎么樣的呢
Docker組件向服務(wù)端發(fā)送請(qǐng)求后,服務(wù)端根據(jù)請(qǐng)求執(zhí)行具體的動(dòng)作并將結(jié)果返回給Docker,Docker解析服務(wù)端的返回結(jié)果,并將結(jié)果通過(guò)命令行標(biāo)準(zhǔn)輸出展示給用戶。這樣一次完整的客戶端服務(wù)端請(qǐng)求就完成了
dockerd
dockerd 為Docker服務(wù)端后臺(tái)的常駐進(jìn)程,負(fù)責(zé)接收客戶端的請(qǐng)求,處理具體的任務(wù)并將結(jié)果返回客戶端
那么 Docke r客戶端采用哪幾種方式發(fā)送請(qǐng)求
第一種方式:通過(guò)unix套接字與服務(wù)端通信,配置的格式為:unix://socket_path。默認(rèn)的dockerd生成的 socket文件存放在 /var/run/docker.sock,此文件只能是root用戶才能訪問(wèn),這也是為什么剛安裝完Docker后只能root 來(lái)進(jìn)行訪問(wèn)操作
第二種方式:采用TCP的方式與服務(wù)端通信,配置格式為:tcp://host:por,為了保證安全,通常還需要使用TLS認(rèn)證
第三種方式:通過(guò)fd文件描述符的方式,配置格式為:fd://這種格式一般用于systemd管理的系統(tǒng)中。
docker-init
在Linux中,有一個(gè)叫做init的進(jìn)程,是所有進(jìn)程的父進(jìn)程,用來(lái)回收那些沒(méi)有回收的進(jìn)程,同樣的道理,在容器內(nèi)部,可以通過(guò)加上參數(shù) --init 的方式,讓 1 號(hào)進(jìn)程管理所有的子進(jìn)程,例如回收僵尸進(jìn)程
舉個(gè)例子示范,以鏡像 busybox 為例
此時(shí)的 1 號(hào)進(jìn)程為為 sh 進(jìn)程,如果加上 --init
你會(huì)發(fā)現(xiàn),此時(shí)的 1 號(hào)進(jìn)程為docker-init,而不是sh了
docker-proxy
docker-proxy 用來(lái)將容器啟動(dòng)的端口映射到主機(jī),方便主機(jī)的訪問(wèn)。
假設(shè)目前啟動(dòng)一個(gè)nginx容器并將容器的80端口映射到主機(jī)的8080端口
查看容器 IP
此時(shí)使用 ps 查看主機(jī)是否有 docker-proxy 進(jìn)程
可以發(fā)現(xiàn)當(dāng)進(jìn)行端口映射的時(shí)候,docker為我們創(chuàng)建了一個(gè)docker-proxy進(jìn)程,并且通過(guò)參數(shù)將容器的IP和端口傳遞給docker-proxy,然后proxy通過(guò)iptables完成nat的轉(zhuǎn)發(fā)
從最后一句可以看出,當(dāng)我們主機(jī)訪問(wèn) 8080 端口的時(shí)候,iptable將流量會(huì)轉(zhuǎn)發(fā)給 172.17.0.2 的 80 ,從而實(shí)現(xiàn)主機(jī)上直接訪問(wèn)容器的業(yè)務(wù)
使用curl訪問(wèn)一下nginx容器
contained組件
containerd
contained主要負(fù)責(zé)容器的生命周期管理,同時(shí)還會(huì)負(fù)責(zé)一些其他的功能
主要負(fù)責(zé)那些功能?
鏡像的管理
接收dockerd的請(qǐng)求
管理存儲(chǔ)相關(guān)資源
管理網(wǎng)絡(luò)資源
containerd-shim
containerd-shim 的意思是墊片,類似于擰螺絲時(shí)夾在螺絲和螺母之間的墊片。containerd-shim 的主要作用是將 containerd 和真正的容器進(jìn)程解耦,使用 containerd-shim 作為容器進(jìn)程的父進(jìn)程,從而實(shí)現(xiàn)重啟 containerd 不影響已經(jīng)啟動(dòng)的容器進(jìn)程。
ctr
ctr 實(shí)際上是 containerd-ctr,它是 containerd 的客戶端,主要用來(lái)開(kāi)發(fā)和調(diào)試,在沒(méi)有 dockerd 的環(huán)境中,ctr 可以充當(dāng) docker 客戶端的部分角色,直接向 containerd 守護(hù)進(jìn)程發(fā)送操作容器的請(qǐng)求。
Docker鏡像使用
來(lái),繼續(xù),我們看看鏡像是什么。鏡像是一個(gè)只讀的鏡像模版且包含了啟動(dòng)容器所需要的文件結(jié)構(gòu)內(nèi)容。鏡像不包含動(dòng)態(tài)數(shù)據(jù),構(gòu)建完成將不會(huì)改變
對(duì)于鏡像都有哪些操作?
對(duì)于鏡像的操作分為:
拉取鏡像:通過(guò)docker pull拉取遠(yuǎn)程倉(cāng)庫(kù)的鏡像
重命名鏡像:通過(guò)docker tag重命名鏡像
查看鏡像:通過(guò)docker image ls查看本地已經(jīng)存在的鏡像
刪除鏡像:通過(guò)docekr rmi刪除沒(méi)有用的鏡像
構(gòu)建鏡像
第一種是通過(guò)docker build命令基于dockerfile構(gòu)建鏡像,推薦
第二種是通過(guò)docker commit基于運(yùn)行的容器提交為鏡像
拉取鏡像
拉取鏡像直接使用 docker pull 命令即可,命令的格式如下
registry為注冊(cè)的服務(wù)器,docker 默認(rèn)會(huì)從官網(wǎng)docker.io上拉取鏡像,當(dāng)然可以將registry注冊(cè)為自己的服務(wù)器
repository為鏡像倉(cāng)庫(kù),library為默認(rèn)的鏡像倉(cāng)庫(kù)
image為鏡像的名稱
tag為給鏡像打的標(biāo)簽
現(xiàn)在舉個(gè)例子,這里有個(gè)鏡像叫做busybox,這個(gè)鏡像集成了上百個(gè)常用的Linux命令,可以通過(guò)這個(gè)鏡像方便快捷的查找生產(chǎn)環(huán)境中的問(wèn)題,下面我們一起操作一波
docker pull busybox
首先會(huì)在本地鏡像庫(kù)查找,如果不存在本地庫(kù)則直接去官網(wǎng)拉取鏡像。拉取完鏡像后隨即查看鏡像
查看鏡像---docker images
如果要查看指定的鏡像,則使用docker image ls命令進(jìn)一步查詢
重命名鏡像采用打標(biāo)簽的方式重命名,格式如下
我們仔細(xì)觀察這兩個(gè)鏡像,就會(huì)發(fā)現(xiàn)這兩個(gè)鏡像的 IMAGE ID其實(shí)是一樣的,這是什么原因呢
實(shí)際上他們都是指向的同一個(gè)鏡像文件,只不過(guò)其別名不一樣而已,如果此時(shí)不想要mybox鏡像,想刪除這個(gè)鏡像
使用 docker rmi 刪除鏡像
此時(shí)再次使用 docker images 查看確實(shí)刪除了
如何自己構(gòu)建自己鏡像呢
之前說(shuō)過(guò),有兩種方式,一種是通過(guò)docker commit的方式,一種是docker build的方式。首先看看使用容器提交鏡像的方式
此時(shí)啟動(dòng)了一個(gè)busybox容器并進(jìn)入到容器,并在容器中創(chuàng)建一個(gè)文件,并寫入內(nèi)容
此時(shí)就在當(dāng)前目錄下創(chuàng)建了一個(gè)hello.txt文件并寫入了內(nèi)容。現(xiàn)在新建另外一個(gè)窗口,然后提交為一個(gè)鏡像
然后使用 docker image ls 查看發(fā)現(xiàn)確實(shí)生成了鏡像
然后我們?cè)倏纯词褂?dockerfile 的方式
dockerfile的每一行的命令都會(huì)生成獨(dú)立的鏡像層并擁有唯一的id
dockerfile命令是完全透明的,通過(guò)查看dockerfile的內(nèi)容,就可以知道鏡像是怎么一步步構(gòu)建的
dockerfile為純文本,方便做版本控制
先看看都有哪些命令
這么多,不存在的,我們先看一個(gè)dockerfile就知道如何用了
首先第一行表示基于什么鏡像構(gòu)建
第二行是拷貝文件nginx。repo 到容器內(nèi)的 /etc/yum.repos.d
第三行為容器中運(yùn)行 yum install 命令,安裝 nginx 命令到容器
第四行為生命容器使用 80 端口對(duì)外開(kāi)放
第五行定義容器啟動(dòng)時(shí)的環(huán)境變量HOST=mynginx,容器啟動(dòng)后可以獲取到環(huán)境變量 HOST 的值為 mynginx。
第六行定義容器的啟動(dòng)命令,命令格式為json 數(shù)組。這里設(shè)置了容器的啟動(dòng)命令為 nginx ,并且添加了 nginx 的啟動(dòng)參數(shù) -g 'daemon off;' ,使得 nginx 以前臺(tái)的方式啟動(dòng)。
基本操作已經(jīng)會(huì)了,現(xiàn)在我們看看鏡像的實(shí)現(xiàn)原理
第一行:創(chuàng)建一個(gè) busybox 鏡像層
第二行:拷貝本機(jī) test 文件到鏡像內(nèi)
第三行 在tmp 文件夾創(chuàng)建一個(gè)目錄 testdir
為了清楚的看見(jiàn)鏡像的存儲(chǔ)結(jié)構(gòu),通過(guò) docker build 構(gòu)建鏡像
因?yàn)槲业?docker 使用的是 overlay2 文件驅(qū)動(dòng),所以進(jìn)入到/var/lib/docker/overlay2 ,使用 tree 查看
可以清楚的看到,dockerfile 的每一行命令都會(huì)生成一個(gè)鏡像層
Docker容器操作
我們通過(guò)一個(gè)鏡像可以輕松的創(chuàng)建一個(gè)容器,一個(gè)鏡像可以有多個(gè)容器,在運(yùn)行容器的時(shí)候,實(shí)際上是在容器內(nèi)部創(chuàng)建了這個(gè)文件系統(tǒng)的讀寫副本,如下圖所示
容器的生命周期是怎么樣的?
容器的生命周期一共有五個(gè)狀態(tài)分別為
created 初建狀態(tài)
running 運(yùn)行狀態(tài)
stopped 停止?fàn)顟B(tài)
opaused 暫停狀態(tài)
deleted 刪除狀態(tài)
通過(guò)docker cretate進(jìn)入容器的初建狀態(tài),然后通過(guò)docker start進(jìn)入運(yùn)行狀態(tài),通過(guò)docker stop進(jìn)入停止?fàn)顟B(tài),運(yùn)行狀態(tài)的容器可以通過(guò)docker pause讓其變?yōu)闀和顟B(tài),為了詳細(xì)的查看這些過(guò)程,我們實(shí)操一下
創(chuàng)建并啟動(dòng)容器
通過(guò)docker create創(chuàng)建的容器處于停止的狀態(tài),使用docker start busybox進(jìn)入啟動(dòng)狀態(tài)
當(dāng)使用docker run創(chuàng)建并啟動(dòng)容器的時(shí)候,docker后臺(tái)的執(zhí)行邏輯為
首先檢查本地是否有busybox鏡像,不存在則取dockerhub中拉取
使用busybox鏡像啟動(dòng)一個(gè)容器
分配文件系統(tǒng),并在鏡像的只讀層外創(chuàng)建一個(gè)讀寫層
從docker ip池分配個(gè)ip給容器
運(yùn)行鏡像
可以進(jìn)入交互模式么
同時(shí)使用-it 參數(shù)可以讓我們進(jìn)入交互模式,容器內(nèi)部和主機(jī)是完全隔離的。另外由于此時(shí)的 sh 為 1 號(hào)進(jìn)程,所以如果通過(guò) exit 退出 sh,那么容器也就退出,所以對(duì)于容器而言,殺死容器中的主進(jìn)程,那么容器也就會(huì)被殺死
通過(guò)docker stop停止容器,其原理是給運(yùn)行中的容器給 sigterm 信號(hào),如果容器為 1 號(hào)進(jìn)程接受并處理sigterm,則等待 1 號(hào)進(jìn)程處理完畢后就退出,如果等待一段時(shí)間后還是沒(méi)有處理,則會(huì)通過(guò)發(fā)送sigkill命令強(qiáng)制終止容器
如何進(jìn)入容器?
想要進(jìn)入容器,有三種方案,分別是 docker attach,docker exec,nsenter 等
使用 docker attach 方式進(jìn)入容器
通過(guò) docker ps -a 查看當(dāng)前的進(jìn)程信息
可是當(dāng)我們?cè)谶M(jìn)行窗口進(jìn)行docker attach的時(shí)候,這個(gè)命令就不好用了,所以使用docker exec的方式
使用 docker exec進(jìn)入容器
奇怪的發(fā)現(xiàn)居然是兩個(gè)sh 進(jìn)程,主要是因?yàn)椋?dāng)我們使用 docker exec方式進(jìn)入容器的時(shí)候,會(huì)單獨(dú)啟動(dòng)一個(gè) sh 進(jìn)程,此時(shí)的多個(gè)窗口都是獨(dú)立且不受干擾,也是非常常用的方式
刪除容器
現(xiàn)在基本上知道了如何創(chuàng)建,啟動(dòng)容器,那么怎么刪除容器呢
使用docker rm的方式刪除容器
如果此時(shí),容器正在運(yùn)行,那么需要添加-f的方式停止正在運(yùn)行的容器
如果想要導(dǎo)出容器怎么操作呢
這簡(jiǎn)單,不過(guò)在導(dǎo)出之前先進(jìn)入容器創(chuàng)建一個(gè)文件
然后導(dǎo)出為文件
此時(shí)會(huì)在當(dāng)前目錄生成一個(gè) busybox.tar 文件,此時(shí)就可以將其拷貝到其他的機(jī)器上使用
那如何導(dǎo)入容器呢
通過(guò) docker import的方式導(dǎo)入,然后使用docker run啟動(dòng)就完成了容器的遷移
此時(shí)容器名稱為 busybox:test,然后我們使用 docker run 啟動(dòng)并進(jìn)入容器
此時(shí)發(fā)現(xiàn)之前在/tmp創(chuàng)建的目錄也被遷移了過(guò)來(lái)
倉(cāng)庫(kù)
容器的基本操作應(yīng)該都會(huì)了,那么我們應(yīng)該如何去存儲(chǔ)和分發(fā)這些鏡像,這就需要介紹下倉(cāng)庫(kù);
我們可以使用共有鏡像倉(cāng)庫(kù)分發(fā),也可以搭建私有的倉(cāng)庫(kù)
倉(cāng)庫(kù)是啥玩意
錢錢倉(cāng)庫(kù)放錢,這個(gè)倉(cāng)庫(kù)放鏡像。Github 放代碼,我們理解鏡像的倉(cāng)庫(kù)可以聯(lián)想 Github 倉(cāng)庫(kù)。
在學(xué)習(xí)的過(guò)程中,不太能區(qū)分注冊(cè)服務(wù)器和倉(cāng)庫(kù)的關(guān)系。注冊(cè)服務(wù)器其實(shí)是用來(lái)存放倉(cāng)庫(kù)的實(shí)際機(jī)器,而倉(cāng)庫(kù)我們可以將其理解為具體的項(xiàng)目或者目錄。一個(gè)注冊(cè)服務(wù)器可以存放多個(gè)倉(cāng)庫(kù),每個(gè)倉(cāng)庫(kù)可以存放多個(gè)鏡像
公有倉(cāng)庫(kù)
Docker hub 是當(dāng)前全球最大的鏡像市場(chǎng),差不多超過(guò) 10w 個(gè)容器鏡像,大部分操作系統(tǒng)鏡像都來(lái)自于此。
如何使用公共鏡像倉(cāng)庫(kù)和存儲(chǔ)鏡像
注冊(cè) Docker hub
創(chuàng)建倉(cāng)庫(kù)
實(shí)戰(zhàn)鏡像推送到倉(cāng)庫(kù)
此時(shí)假設(shè)我的賬戶是 xiaolantest,創(chuàng)建一個(gè) busybox 的倉(cāng)庫(kù),隨后將鏡像推送到倉(cāng)庫(kù)中。
第一步:拉取 busybox 鏡像
第二步:推送鏡像之前先登錄鏡像服務(wù)器(注意用戶名密碼哦),出現(xiàn) login Succeeded表示登錄成功
第三步:推送之前還要做一件事,重新對(duì)鏡像命名,這樣測(cè)能正確的推動(dòng)到自己創(chuàng)建的倉(cāng)庫(kù)中
第四步:docker push 到倉(cāng)庫(kù)中
私有倉(cāng)庫(kù)
Docker 官方提供了開(kāi)源的鏡像倉(cāng)庫(kù) Distribution,鏡像存放于 Docker hub 的 Registry中
啟動(dòng)本地鏡像倉(cāng)庫(kù)
使用 docker ps查看啟動(dòng)的容器
重命名鏡像
此時(shí) Docker 為busybox鏡像創(chuàng)建了一個(gè)別名localhost:5000/busybox,localhost:5000為主機(jī)名和端口,Docker 將會(huì)把鏡像推送到這個(gè)地址。
推送鏡像到本地倉(cāng)庫(kù)
刪除之前存在的鏡像
此時(shí),我們驗(yàn)證一下從本地鏡像倉(cāng)庫(kù)拉取鏡像。首先,我們刪除本地的busybox和localhost:5000/busybox鏡像。
查看當(dāng)前本地鏡像
可以看到此時(shí)本地已經(jīng)沒(méi)有busybox這個(gè)鏡像了。下面,我們從本地鏡像倉(cāng)庫(kù)拉取busybox鏡像:
隨后再使用 docker image ls busybox 命令,這時(shí)可以看到我們已經(jīng)成功從私有鏡像倉(cāng)庫(kù)拉取 busybox 鏡像到本地了
總結(jié)
本篇文章從 Docker 容器圈到基本使用,寫的應(yīng)該蠻清楚了。另外說(shuō)明一下,由于直接使用代碼很可能導(dǎo)致格式排版混亂,所以全部采用截圖的方式,更加直觀和清晰,當(dāng)然如有不妥之處也望大家指正。
責(zé)任編輯:lq
-
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
7152瀏覽量
125582 -
編程語(yǔ)言
+關(guān)注
關(guān)注
10文章
1956瀏覽量
36651 -
Docker
+關(guān)注
關(guān)注
0文章
515瀏覽量
12964
發(fā)布評(píng)論請(qǐng)先 登錄
docker無(wú)法啟用怎么解決?
如何使用Docker部署大模型
Docker Compose的常用命令
Docker常用命令大全
【技術(shù)案例】Android in Docker

基于Docker鏡像逆向生成Dockerfile

云服務(wù)器 Flexus X 實(shí)例,Docker 集成搭建 NGINX

docker的基本命令和使用示例
docker通過(guò)中間鏡像加速部署
在 Huawei Cloud EulerOS 系統(tǒng)中安裝 Docker 的詳細(xì)步驟與常見(jiàn)問(wèn)題解決

docker-compose配置文件內(nèi)容詳解以及常用命令介紹

Docker運(yùn)行環(huán)境安裝
手動(dòng)構(gòu)建Docker鏡像的方法

評(píng)論