- 互聯(lián)網(wǎng)企業(yè)容器技術(shù)實踐
- 龔曦主編
- 2619字
- 2019-07-25 11:39:35
1.3 Docker鏡像及鏡像倉庫
??1.3.1 什么是Docker鏡像
Docker 鏡像是由一層層的文件系統(tǒng)組成的特殊文件系統(tǒng),為容器提供了運行時所需要的程序、配置、環(huán)境等。鏡像屬于只讀文件系統(tǒng),不能包含任何的動態(tài)數(shù)據(jù),在構(gòu)建完成后就不會被改變。
Docker在運行容器前需要在本地存在對應(yīng)的容器鏡像,如果本地不存在該鏡像,則Docker會先從鏡像倉庫中將對應(yīng)的鏡像拉取到本地,然后通過該鏡像啟動容器。
拉取完Docker鏡像就可以查看本地是否已經(jīng)存在對應(yīng)的鏡像,要查找本地擁有了哪些鏡像可以通過docker image ls命令,列出本地存在的鏡像,如下所示。
如果想要刪除某個鏡像,可以通過 docke rmi[鏡像:標(biāo)簽]命令實現(xiàn)。如下所示為刪除 test鏡像:
這樣就刪除了test:latest鏡像。其中的latest標(biāo)簽比較特殊,對于Docker鏡像來說,如果不顯式地指定標(biāo)簽,則默認會選擇latest標(biāo)簽,表示最新版本的鏡像。所以刪除test:latest鏡像也可以直接使用docker rmi test,同樣的拉取test:latest鏡像也可以直接使用docker pull test,省略latest標(biāo)簽。
??1.3.2 構(gòu)建Docker鏡像
構(gòu)建Docker鏡像的方式有兩種,一種是通過docker commit方式,另一種是通過Dockerfile文件構(gòu)建的。相比之下,推薦使用Dockerfile的方式構(gòu)建,因為Dockerfile方式簡化了鏡像的構(gòu)建過程,并且可以更好地進行版本控制。首先簡單講解通過docker commit的方式構(gòu)建鏡像,然后會詳細講解如何通過Dockerfile的方式構(gòu)建鏡像。
1. 使用docker commit構(gòu)建鏡像
下面通過一個簡單的示例講解如何通過docker commit的方式構(gòu)建鏡像。
通過如上命令創(chuàng)建了一個基于ubuntu:16.04鏡像的容器,并在容器中安裝了apache2。
可以看到生成的容器ID為2a87d7bbbbdf,接著可以通過docker commit命令創(chuàng)建一個新的鏡像。
成功地創(chuàng)建了一個新的鏡像licheng17/apache2,接著可以通過docker push命令把創(chuàng)建的鏡像提交到鏡像倉庫中。在提交前需要先登錄自己的docker hub 賬戶,如果沒有docker hub賬戶,則需要先注冊。當(dāng)然也可以創(chuàng)建自己的私有鏡像倉庫,登錄私有倉庫,將鏡像上傳。
鏡像上傳成功后可以登錄自己的 docker hub,查看是否增加了剛上傳的 Docker 鏡像licheng17/apache2,如圖1-3所示。

圖1-4 Docker網(wǎng)絡(luò)的整體架構(gòu)
從圖1-4中可以看出Docker daemon 通過Libnetwork提供的API接口實現(xiàn)對網(wǎng)絡(luò)的創(chuàng)建和管理功能。而Libnetwork通過CNM來實現(xiàn)這些網(wǎng)絡(luò)功能,CNM模型有三個組件:Sandbox (沙盒)、端點(Endpoint)、網(wǎng)絡(luò)(Network),具體如下。
? Sandbox(沙盒):每個沙盒包含一個容器網(wǎng)絡(luò)棧(Network stack)的配置,配置包括容器的網(wǎng)口、路由表和DNS設(shè)置等。
? Endpoint(端點):通過Endpoint,Sandbox可以被加入一個Network里。
? Network(網(wǎng)絡(luò)):一組能相互直接通信的Endpoints。
上面的定義還是比較抽象的,理解起來比較困難,所以可以參考CNM模型在Linux上的實現(xiàn)技術(shù)來理解。比如,沙盒的實現(xiàn)可以是一個Linux Network Namespace,Endpoint可以是一對VETH,Network則可以用Linux Bridge或Vxlan實現(xiàn)。
Libnetwork提供了Bridge、Host、Overlay、Remote和Null五種網(wǎng)絡(luò)模式。
1)Bridge驅(qū)動:此驅(qū)動為Docker的默認驅(qū)動,使用該驅(qū)動時,Libnetwork將創(chuàng)建出來的Docker容器連接到Docker網(wǎng)橋上,能夠滿足容器的基本使用性需求。
2)Host驅(qū)動:在該驅(qū)動模式下,Docker容器直接使用宿主機的網(wǎng)絡(luò),與宿主機享有完全相同的網(wǎng)絡(luò)環(huán)境。
3)Overlay驅(qū)動:此驅(qū)動采用VXLAN中的SDN controller模式。在使用過程中,需要一個額外的配置存儲服務(wù),例如Consul、etcd和Zookeeper等,并在啟動Docker daemon的時候通過參數(shù)指定所使用的配置存儲服務(wù)地址。
4)Remote驅(qū)動:該驅(qū)動實際上并沒有實現(xiàn)Docker自己的網(wǎng)絡(luò)服務(wù),而是通過調(diào)用外部的網(wǎng)絡(luò)驅(qū)動插件的形式實現(xiàn)網(wǎng)絡(luò)服務(wù)。用戶可以根據(jù)自己的需求選擇或開發(fā)合適的網(wǎng)絡(luò)插件。
5)Null驅(qū)動:在這種網(wǎng)絡(luò)模式下,Docker僅僅為容器創(chuàng)建自己的Network Namespace,提供網(wǎng)絡(luò)隔離的功能,但并不會為容器創(chuàng)建任何網(wǎng)絡(luò)配置,需要用戶根據(jù)自己的需求為容器添加網(wǎng)絡(luò),并配置網(wǎng)絡(luò)環(huán)境。
??1.4.2 Docker網(wǎng)絡(luò)原理
這部分主要介紹Docker的網(wǎng)絡(luò)原理,通過Linux系統(tǒng)模擬實現(xiàn)一個Docker默認網(wǎng)絡(luò)的方法。
首先對Docker網(wǎng)絡(luò)的實現(xiàn)原理進行整體簡略的介紹,當(dāng)Docker服務(wù)安裝并啟動后,在主機上輸入 ifconfig 命令,可以發(fā)現(xiàn)主機上多了一個 docker0 的虛擬網(wǎng)橋,這個網(wǎng)橋為 Docker的網(wǎng)絡(luò)通信提供支持。如圖1-5所示,在默認網(wǎng)絡(luò)情況下,當(dāng)啟動一個Docker容器時,Docker會為容器分配一個IP地址,并通過一對veth pair將容器的eth0綁定到主機的docker0網(wǎng)橋中。

圖1-5 Docker網(wǎng)絡(luò)的實現(xiàn)原理
1. 模擬實現(xiàn)Docker網(wǎng)絡(luò)
下面通過Linux系統(tǒng)模擬Docker網(wǎng)絡(luò)模型,實現(xiàn)上面介紹的網(wǎng)絡(luò)結(jié)構(gòu)。
第一步:創(chuàng)建Network Namespace
此時Namespace test創(chuàng)建成功了,在/var/run/netns目錄中可以看到一個test文件。當(dāng)啟動一個容器時,Docker會為容器創(chuàng)建一個Network Namespace,可以看到在/var/run/docker/netns目錄下生成了一個對應(yīng)的文件。
第二步:添加網(wǎng)口到Namespace
先創(chuàng)建veth:
在當(dāng)前Namespace中可以看到veth0和veth1:
將veth1加到namespace“test”:
通過ip link list命令發(fā)現(xiàn),當(dāng)前Namespapce只能看到veth0,而veth1已經(jīng)找不到了。
通過如下命令可以查看test namespace的網(wǎng)口,發(fā)現(xiàn)剛剛不見了的veth1。說明veth1已經(jīng)加入test namespace中。
配置Network Namespace的網(wǎng)口。可以通過ip netns exec進行配置。
通過ip netns exec可以配置查看veth1網(wǎng)口的IP地址正是172.16.0.2。
這樣一個隔離的容器網(wǎng)絡(luò)就完成了,又該如何實現(xiàn)容器網(wǎng)絡(luò)與外部的通信呢?這就需要用到Bridge了。
第三步:創(chuàng)建網(wǎng)橋
在默認的Network Namespace下創(chuàng)建test0網(wǎng)橋:
test0網(wǎng)橋創(chuàng)建成功,其中docker0是Docker服務(wù)器自己的網(wǎng)橋。下一步是給test0分配IP地址并生效,充當(dāng)Gateway:
將veth0“插到”test0這個Bridge上:
查看test網(wǎng)絡(luò)生成了一條直連路由表,現(xiàn)在test網(wǎng)絡(luò)可以ping通test0了,但由于沒有默認路由,Docker還不能與其他網(wǎng)絡(luò)相通,通過ping docker0測試發(fā)現(xiàn)確實如此。
為test網(wǎng)絡(luò)添加一條默認路由表,測試ping docker0發(fā)現(xiàn)成功。
現(xiàn)在的test網(wǎng)絡(luò)可以與主機相通了,但還不能訪問外部網(wǎng)絡(luò),因為icmp包回來時找不到目的地,也就找不到172.17.0.2了,可以通過iptables來解決。
可以看出添加完 iptables規(guī)則后已經(jīng)可以正常訪問外網(wǎng)了。這樣一個類Docker 的網(wǎng)絡(luò)就完成了,其實Docker的網(wǎng)絡(luò)相對會比這復(fù)雜很多,但基本實現(xiàn)原理方法是一樣的。
2.Docker容器端口映射原理
上一節(jié)已經(jīng)通過模擬實現(xiàn)Docker網(wǎng)絡(luò)的方式講解了Docker的網(wǎng)絡(luò)原理。但還有一個重要的功能沒有講,就是容器端口映射的功能,即將容器的服務(wù)端口a綁定到宿主機的端口b上,最終達到一種效果:外部程序通過宿主機的端口b訪問,就像直接訪問Docker容器網(wǎng)絡(luò)內(nèi)部容器提供的服務(wù)一樣。
如下通過Docker啟動了一個Nginx容器服務(wù),并將容器內(nèi)部的80端口映射到本地主機的9091端口。然后可以通過本地的9091端口訪問容器的80端口,即Nginx服務(wù)。
容器是怎樣實現(xiàn)端口映射功能的呢?在默認情況下,在1.12.1版本以前Docker引擎采用docker-proxy進程來實現(xiàn),在之后的版本中,雖然增加了iptables的方式實現(xiàn),但在默認情況下通過配置-userland-proxy=true為每個expose端口的容器啟動一個proxy實例來實現(xiàn)端口流量轉(zhuǎn)發(fā)。docker-proxy實際上是實現(xiàn)了在默認命名空間和容器命名空間之間的流量轉(zhuǎn)發(fā)功能而已。
但是因為每增加一個端口映射,宿主機就會多出一個docker-proxy進程,一旦需要過多的端口映射,就需要增加過多的docker-proxy進程,這樣將會消耗大量的資源。因此,在1.7及更高版本中,Docker提供了一種完全由iptables DNAT實現(xiàn)的端口映射,但docker-proxy的方式依舊是默認方式,通過配置-userland-proxy=false來選擇iptables DNAT模式。
從上述的iptables規(guī)則可以看出,iptables將本地的9091端口通過DNAT映射到172.12.0.2的80端口,其中172.12.0.2就是Nginx的容器IP。
- 重構(gòu):數(shù)字化轉(zhuǎn)型的邏輯
- 如何準(zhǔn)備PMP考試(第4版)
- 互聯(lián)網(wǎng)項目管理實戰(zhàn)指南
- 項目管理基礎(chǔ)(第五版)
- 經(jīng)營一家最賺錢的酒店
- 微信公眾號營銷實戰(zhàn)
- 公司合作文化
- 項目管理超圖解:快速提升團隊行動力的8個關(guān)鍵
- 項目管理知與行
- 10人以下小團隊管理手冊
- 中央財經(jīng)大學(xué)經(jīng)管實驗項目精選集(2016)
- 女人精品店全攻略
- 創(chuàng)業(yè)園:創(chuàng)業(yè)生態(tài)系統(tǒng)構(gòu)建指南
- PPP模式:全流程指導(dǎo)與案例分析
- 人人都是項目經(jīng)理(第2版)