Docker
Docker 是一個(gè)開(kāi)源的應(yīng)用容器引擎,基于 Go 語(yǔ)言 并遵從Apache2.0協(xié)議開(kāi)源。
Docker 可以讓開(kāi)發(fā)者打包他們的應(yīng)用以及依賴(lài)包到一個(gè)輕量級(jí)、可移植的容器中,然后發(fā)布到任何流行的 Linux 機(jī)器上,也可以實(shí)現(xiàn)虛擬化。

解決的問(wèn)題
由于不同的機(jī)器有不同的操作系統(tǒng),以及不同的庫(kù)和組件,在將一個(gè)應(yīng)用部署到多臺(tái)機(jī)器上需要進(jìn)行大量的環(huán)境配置操作。
Docker 主要解決環(huán)境配置問(wèn)題,它是一種虛擬化技術(shù),對(duì)進(jìn)程進(jìn)行隔離,被隔離的進(jìn)程獨(dú)立于宿主操作系統(tǒng)和其它隔離的進(jìn)程。使用 Docker 可以不修改應(yīng)用程序代碼,不需要開(kāi)發(fā)人員學(xué)習(xí)特定環(huán)境下的技術(shù),就能夠?qū)F(xiàn)有的應(yīng)用程序部署在其他機(jī)器中。
與虛擬機(jī)的比較
虛擬機(jī)也是一種虛擬化技術(shù),它與 Docker 最大的區(qū)別在于它是通過(guò)模擬硬件,并在硬件上安裝操作系統(tǒng)來(lái)實(shí)現(xiàn)。

Hypervisor是一種運(yùn)行在物理服務(wù)器和操作系統(tǒng)之間的中間軟件層,可允許多個(gè)操作系統(tǒng)和應(yīng)用共享一套基礎(chǔ)物理硬件,因此也可以看作是虛擬環(huán)境中的“元”操作系統(tǒng),它可以協(xié)調(diào)訪問(wèn)服務(wù)器上的所有物理設(shè)備和虛擬機(jī),也叫虛擬機(jī)監(jiān)視器(Virtual Machine Monitor)。

啟動(dòng)速度
啟動(dòng)虛擬機(jī)需要啟動(dòng)虛擬機(jī)的操作系統(tǒng),再啟動(dòng)應(yīng)用,這個(gè)過(guò)程非常慢;
而啟動(dòng) Docker 相當(dāng)于啟動(dòng)宿主操作系統(tǒng)上的一個(gè)進(jìn)程。
占用資源
虛擬機(jī)是一個(gè)完整的操作系統(tǒng),需要占用大量的磁盤(pán)、內(nèi)存和 CPU,一臺(tái)機(jī)器只能開(kāi)啟幾十個(gè)的虛擬機(jī)。
而 Docker 只是一個(gè)進(jìn)程,只需要將應(yīng)用以及相關(guān)的組件打包,在運(yùn)行時(shí)占用很少的資源,一臺(tái)機(jī)器可以開(kāi)啟成千上萬(wàn)個(gè) Docker。
優(yōu)勢(shì)
更容易遷移
提供一致性的運(yùn)行環(huán)境,可以在不同的機(jī)器上進(jìn)行遷移,而不用擔(dān)心環(huán)境變化導(dǎo)致無(wú)法運(yùn)行。
更容易維護(hù)
使用分層技術(shù)和鏡像,使得應(yīng)用可以更容易復(fù)用重復(fù)部分。復(fù)用程度越高,維護(hù)工作也越容易。
更容易擴(kuò)展
可以使用基礎(chǔ)鏡像進(jìn)一步擴(kuò)展得到新的鏡像,并且官方和開(kāi)源社區(qū)提供了大量的鏡像,通過(guò)擴(kuò)展這些鏡像可以非常容易得到我們想要的鏡像。
使用場(chǎng)景
持續(xù)集成
持續(xù)集成指的是頻繁地將代碼集成到主干上,這樣能夠更快地發(fā)現(xiàn)錯(cuò)誤。
Docker 具有輕量級(jí)以及隔離性的特點(diǎn),在將代碼集成到一個(gè) Docker 中不會(huì)對(duì)其它 Docker 產(chǎn)生影響。
提供可伸縮的云服務(wù)
根據(jù)應(yīng)用的負(fù)載情況,可以很容易地增加或者減少 Docker。
搭建微服務(wù)架構(gòu)
Docker 輕量級(jí)的特點(diǎn)使得它很適合用于部署、維護(hù)、組合微服務(wù)。
鏡像與容器
鏡像是一種靜態(tài)的結(jié)構(gòu),可以看成面向?qū)ο罄锩娴?strong>類(lèi),而容器是鏡像的一個(gè)實(shí)例。
鏡像包含著容器運(yùn)行時(shí)所需要的代碼以及其它組件,它是一種分層結(jié)構(gòu),每一層都是只讀的(read-only layers)。構(gòu)建鏡像時(shí),會(huì)一層一層構(gòu)建,前一層是后一層的基礎(chǔ)。鏡像的這種分層存儲(chǔ)結(jié)構(gòu)很適合鏡像的復(fù)用以及定制。
構(gòu)建容器時(shí),通過(guò)在鏡像的基礎(chǔ)上添加一個(gè)可寫(xiě)層(writable layer),用來(lái)保存著容器運(yùn)行過(guò)程中的修改。

網(wǎng)絡(luò)模式
docker run創(chuàng)建Docker容器時(shí),可以用–net選項(xiàng)指定容器的網(wǎng)絡(luò)模式,Docker有以下4種網(wǎng)絡(luò)模式:
- bridge模式:使用–net =bridge指定,默認(rèn)設(shè)置;
- host模式:使用–net =host指定;
- none模式:使用–net =none指定;
- container模式:使用–net =container:NAMEorID指定。
bridge模式
bridge模式是Docker默認(rèn)的網(wǎng)絡(luò)設(shè)置,此模式會(huì)為每一個(gè)容器分配N(xiāo)etwork Namespace、設(shè)置IP等,并將并將一個(gè)主機(jī)上的Docker容器連接到一個(gè)虛擬網(wǎng)橋上。當(dāng)Docker server啟動(dòng)時(shí),會(huì)在主機(jī)上創(chuàng)建一個(gè)名為docker0的虛擬網(wǎng)橋,此主機(jī)上啟動(dòng)的Docker容器會(huì)連接到這個(gè)虛擬網(wǎng)橋上。虛擬網(wǎng)橋的工作方式和物理交換機(jī)類(lèi)似,這樣主機(jī)上的所有容器就通過(guò)交換機(jī)連在了一個(gè)二層網(wǎng)絡(luò)中。接下來(lái)就要為容器分配IP了,Docker會(huì)從RFC1918所定義的私有IP網(wǎng)段中,選擇一個(gè)和宿主機(jī)不同的IP地址和子網(wǎng)分配給docker0,連接到docker0的容器就從這個(gè)子網(wǎng)中選擇一個(gè)未占用的IP使用。如一般Docker會(huì)使用172.17.0.0/16這個(gè)網(wǎng)段,并將172.17.42.1/16分配給docker0網(wǎng)橋(在主機(jī)上使用ifconfig命令是可以看到docker0的,可以認(rèn)為它是網(wǎng)橋的管理端口,在宿主機(jī)上作為一塊虛擬網(wǎng)卡使用)。

host模式
該模式將禁用Docker容器的網(wǎng)絡(luò)隔離。因?yàn)槿萜鞴蚕砹怂拗鳈C(jī)的網(wǎng)絡(luò)命名空間,直接暴露在公共網(wǎng)絡(luò)中。因此,你需要通過(guò)端口映射(port mapping)來(lái)進(jìn)行協(xié)調(diào)。
$ docker run -d --net=host ubuntu:14.04 tail -f /dev/null
$ ip addr | grep -A 2 eth0:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 06:58:2b:07:d5:f3 brd ff:ff:ff:ff:ff:ff
inet **10.0.7.197**/22 brd 10.0.7.255 scope global dynamic eth0
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
b44d7d5d3903 ubuntu:14.04 tail -f 2 seconds ago
Up 2 seconds jovial_blackwell
$ docker exec -it b44d7d5d3903 ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 06:58:2b:07:d5:f3 brd ff:ff:ff:ff:ff:ff
inet **10.0.7.197**/22 brd 10.0.7.255 scope global dynamic eth0
我們可以從上例中看到:容器和宿主機(jī)具有相同的IP地址10.0.7.197。
在下圖中,我們可以看到:當(dāng)使用host模式網(wǎng)絡(luò)時(shí),容器實(shí)際上繼承了宿主機(jī)的IP地址。該模式比bridge模式更快(因?yàn)闆](méi)有路由開(kāi)銷(xiāo)),但是它將容器直接暴露在公共網(wǎng)絡(luò)中,是有安全隱患的。

none模式
該模式將容器放置在它自己的網(wǎng)絡(luò)棧中,但是并不進(jìn)行任何配置。實(shí)際上,該模式關(guān)閉了容器的網(wǎng)絡(luò)功能,在以下兩種情況下是有用的:
- 容器并不需要網(wǎng)絡(luò)(例如只需要寫(xiě)磁盤(pán)卷的批處理任務(wù))
- 你希望自定義網(wǎng)絡(luò)
container模式
這個(gè)模式指定新創(chuàng)建的容器和已經(jīng)存在的一個(gè)容器共享一個(gè)Network Namespace,而不是和宿主機(jī)共享。新創(chuàng)建的容器不會(huì)創(chuàng)建自己的網(wǎng)卡,配置自己的IP,而是和一個(gè)指定的容器共享IP、端口范圍等。同樣,兩個(gè)容器除了網(wǎng)絡(luò)方面,其他的如文件系統(tǒng)、進(jìn)程列表等還是隔離的。兩個(gè)容器的進(jìn)程可以通過(guò)lo網(wǎng)卡設(shè)備通信。
$ docker run -d -P --net=bridge nginx:1.9.1
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
eb19088be8a0 nginx:1.9.1 nginx -g 3 minutes ago Up 3 minutes
0.0.0.0:32769->80/tcp,
0.0.0.0:32768->443/tcp admiring_engelbart
$ docker exec -it admiring_engelbart ip addr
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet **172.17.0.3**/16 scope global eth0
$ docker run -it --net=container:admiring_engelbart ubuntu:14.04 ip addr
...
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet **172.17.0.3**/16 scope global eth0
結(jié)果(上面的例子)顯示:第二個(gè)容器使用了--net=container參數(shù),因此和第一個(gè)容器admiring_engelbart具有相同的IP地址172.17.0.3。