6.1 Docker鏡像——簡(jiǎn)介
對(duì)于運(yùn)維人員來(lái)說(shuō),Docker鏡像可以理解為VM模板逸爵,VM模板就像停止運(yùn)行的VM具滴,而Docker鏡像就像停止運(yùn)行的容器;對(duì)于開(kāi)發(fā)人員师倔,可以把鏡像理解為類(lèi)(Class)构韵。
讀者需要從鏡像倉(cāng)庫(kù)中拉取鏡像。常見(jiàn)的鏡像倉(cāng)庫(kù)服務(wù)是Docker Hub,但是也存在其他鏡像倉(cāng)庫(kù)服務(wù)贞绳。拉取操作會(huì)將鏡像下載到本地Docker主機(jī)谷醉,讀者可以使用該鏡像啟動(dòng)一個(gè)或者多個(gè)容器。
鏡像由多層組成冈闭,每層疊加之后俱尼,從外部看來(lái)就如一個(gè)獨(dú)立的對(duì)象。鏡像內(nèi)部是一個(gè)精簡(jiǎn)的操作系統(tǒng)萎攒,同時(shí)還包含應(yīng)用運(yùn)行所必須的文件和依賴(lài)包遇八。因?yàn)槿萜鞯脑O(shè)計(jì)初衷就是快速和小巧,所以鏡像通常都比較小耍休。
6.2 Docker鏡像——詳解
前面多次提到鏡像就像是停止運(yùn)行的容器(類(lèi))刃永。實(shí)際上,讀者可以停止某個(gè)容器的運(yùn)行羊精,并從中創(chuàng)建新的鏡像斯够。在該前提下,鏡像可以理解為一種構(gòu)建時(shí)結(jié)構(gòu)喧锦,而容器可以理解為一種運(yùn)行時(shí)結(jié)構(gòu)读规。
6.2.1 鏡像和容器
我們通常使用docker container run 和 docker service create 命令從某個(gè)鏡像啟動(dòng)一個(gè)或多個(gè)容器。一旦容器從鏡像啟動(dòng)后燃少,二者之間就變成了相互依賴(lài)的關(guān)系束亏,并且在鏡像上啟動(dòng)的容器全部停止之前,鏡像是沒(méi)法被刪除的阵具。
容器的目的就是運(yùn)行應(yīng)用或者服務(wù)碍遍,這意味這容器的鏡像中必須包含應(yīng)用/服務(wù)運(yùn)行所必須的操作系統(tǒng)和應(yīng)用文件。但是阳液,容器由追求小巧和快速怕敬,這意味這構(gòu)建鏡像的時(shí)候通常需要裁剪掉不必要的部分,保持較小的體積趁舀。
例如赖捌,Docker鏡像不會(huì)像一個(gè)完整的Linux那樣提供多個(gè)Shell讓讀者選擇——通常Docker鏡像中只有一個(gè)精簡(jiǎn)的Shell祝沸,甚至沒(méi)有Shell矮烹。此外,鏡像中還不包含內(nèi)核——容器都是共享所在Docker主機(jī)的內(nèi)核的罩锐。所以有時(shí)會(huì)說(shuō)容器僅包含必要的操作系統(tǒng)(通常只有操作系統(tǒng)文件和文件系統(tǒng)對(duì)象)奉狈。Docker官方鏡像Alpine Linux大約只有4MB,Ubuntu官方Docker鏡像大小大概為110MB涩惑,這都遠(yuǎn)遠(yuǎn)小于完整的Linux OS鏡像仁期。
6.2.2 拉取鏡像
Docker主機(jī)安裝之后,本地并沒(méi)有鏡像。Linux Docker主機(jī)本地鏡像倉(cāng)庫(kù)通常位于 /var/lib/docker/<storage-driver>
跛蛋,我們可以使用下面的命令來(lái)查看Docker主機(jī)的本地倉(cāng)庫(kù)中包含了哪些鏡像
docker image ls
將鏡像拉取到本地Docker主機(jī)的操作是拉取熬的,如果你要使用最新版本的Ubuntu鏡像,那就需要拉取它赊级⊙嚎颍可以通過(guò)下面的命令去拉取:
docker image pull ubuntu:latest
我的Dokcer主機(jī)在前面已經(jīng)拉取了幾個(gè)鏡像理逊,我們來(lái)看下:
[pangcm@docker01 ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 775349758637 2 weeks ago 64.2MB
nginx latest 540a289bab6c 3 weeks ago 126MB
alpine latest 965ea09ff2eb 3 weeks ago 5.55MB
hello-world latest fce289e99eb9 10 months ago 1.84kB
6.2.3 鏡像倉(cāng)庫(kù)服務(wù)
Docker鏡像存儲(chǔ)在鏡像倉(cāng)庫(kù)服務(wù)(Image Registry)當(dāng)中橡伞。Docker 客戶端的鏡像倉(cāng)庫(kù)服務(wù)是可以配置的,默認(rèn)使用 Docker Hub晋被。Docker Hub可以分為官方倉(cāng)庫(kù)和非官方倉(cāng)庫(kù)兑徘,通常我們更加建議使用官方倉(cāng)庫(kù)的鏡像,因?yàn)檫@會(huì)更加安全可靠羡洛;非官方倉(cāng)庫(kù)雖然也有不少的優(yōu)秀鏡像挂脑,但是使用之前要仔細(xì)確認(rèn),以免造成不必要的損失欲侮。
6.2.4 鏡像命名和標(biāo)簽
只要給出鏡像的名稱(chēng)和標(biāo)簽最域,就能在官方倉(cāng)庫(kù)中定位一個(gè)鏡像(采用“:”分隔)。從官方參考拉取鏡像時(shí)锈麸,使用docker image pull 命令镀脂。默認(rèn)情況下,我們拉取的是帶有標(biāo)簽 "latest"的鏡像忘伞,如果要拉取不同的鏡像薄翅,需要指定特有的標(biāo)簽,如:
docker image pull ubuntu:18.04
這里要注意標(biāo)簽為latest的鏡像不保證這是最新的鏡像氓奈,比如Apline的最新鏡像的標(biāo)簽通過(guò)是edge翘魄。如果要從非官方鏡像中拉取鏡像,還需要在鏡像名稱(chēng)中加入 "/" 分割符舀奶。
docker image pull nigelpoulton/tu-demo:v2
如果你要從第三方倉(cāng)庫(kù)下載鏡像暑竟,那還有在前面加上第三方鏡像倉(cāng)庫(kù)的DNS名稱(chēng),在拉取鏡像之前還需要完成登錄育勺。
一個(gè)鏡像可以有多個(gè)標(biāo)簽但荤,比如我們剛剛下載的ubuntu:18.04鏡像,以及前面現(xiàn)在的ubuntu:latest 實(shí)際上是同一個(gè)鏡像來(lái)的涧至,我們使用docker image ls ubuntu 來(lái)查看腹躁,可以看到這兩個(gè)鏡像的ID是一樣的。
[pangcm@qcloud01 ~]$ docker image ls ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 775349758637 2 weeks ago 64.2MB
ubuntu latest 775349758637 2 weeks ago 64.2MB
6.2.5 使用 --filter 參數(shù)
Docker提供了--filter參數(shù)來(lái)過(guò)濾docker image ls命令返回的鏡像列表內(nèi)容南蓬。下面的示例指揮返回懸虛(dangling)鏡像纺非。
[pangcm@qcloud01 ~]$ docker image ls --filter dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
b3log/solo <none> ff78fbb88bec 2 weeks ago 151MB
b3log/solo <none> f5d60038de5c 3 weeks ago 151MB
懸虛鏡像就是那些沒(méi)有標(biāo)簽的鏡像哑了,在列表中展示為<none>:<none>。出現(xiàn)這種情況通常是因?yàn)闃?gòu)建了一個(gè)新鏡像的時(shí)候烧颖,打上了一個(gè)已存在的標(biāo)簽弱左。這時(shí)候,Docker會(huì)移除舊鏡像上的標(biāo)簽炕淮,然后把這個(gè)標(biāo)簽打在新的鏡像上科贬。這樣下來(lái),舊的鏡像舊變成了懸虛鏡像鳖悠。
使用docker image prune命令可以移除全部的懸虛鏡像榜掌,如果加上 -a 參數(shù),Docker會(huì)額外移除沒(méi)有被使用的鏡像(那些沒(méi)有被任何容器使用的鏡像)乘综。
Docker image 目前支持如下的過(guò)濾器:
- dangling:可以指定true或者false憎账,僅返回懸虛鏡像或者非懸虛鏡像。
- before: 需要鏡像名稱(chēng)或者ID作為參數(shù)卡辰,返回之前被創(chuàng)建的全部鏡像
- label:根據(jù)標(biāo)注(label)的名稱(chēng)或者值胞皱,對(duì)鏡像進(jìn)行過(guò)濾。docker image ls 命令中不顯示標(biāo)注內(nèi)容九妈。
我們除了在docker image ls 中使用filter參數(shù)之外反砌,通常在docker search 命令中也會(huì)用到。docker search 命令允許通過(guò)CLI的方式搜索Docker Hub萌朱,比如我要搜索ubuntu的鏡像:
[pangcm@qcloud01 ~]$ docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 10169 [OK]
dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface … 362 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 235 [OK]
consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 194 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 101 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 98 [OK]
......
要進(jìn)一步過(guò)濾查詢(xún)結(jié)果宴树,我們可以使用 filter 參數(shù),必要我只要官方的鏡像:
[pangcm@qcloud01 ~]$ docker search ubuntu --filter is-official=true
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 10169 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 101 [OK]
ubuntu-debootstrap debootstrap --variant=minbase --components=m… 40 [OK]
有一點(diǎn)要注意的是晶疼,默認(rèn)情況下酒贬,Docker只返回25行結(jié)果,要顯示更多結(jié)果請(qǐng)使用 --limit 參數(shù)翠霍,最多為100行锭吨。
6.2.6 鏡像和分層
Docker鏡像有一些松耦合的只讀鏡像層組成,如下圖所示:
Docker負(fù)責(zé)堆疊這些鏡像層寒匙,并且將它們表示為單個(gè)統(tǒng)一對(duì)象零如。在你使用docker image pull ubuntu 拉取鏡像的時(shí)候,你會(huì)發(fā)現(xiàn)拉取多個(gè)鏡像層的過(guò)程锄弱。此外考蕾,我們可以使用docker image inspect 命令來(lái)查看鏡像的分層情況:
[pangcm@qcloud01 ~]$ docker image inspect ubuntu
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:cc967c529ced563b7746b663d98248bc571afdb3c012019d7f54d6c092793b8b",
"sha256:2c6ac8e5063e35e91ab79dfb7330c6154b82f3a7e4724fb1b4475c0a95dfdd33",
"sha256:6c01b5a53aac53c66f02ea711295c7586061cbe083b110d54dafbeb6cf7636bf",
"sha256:e0b3afb09dc386786d49d6443bdfb20bc74d77dcf68e152db7e5bb36b1cca638"
]
},
...
可以看到Ubuntu這個(gè)鏡像一個(gè)包含了4個(gè)鏡像層,這里使用了SHA256散列值來(lái)表示鏡像層棵癣。
所有的Docker鏡像都起始于一個(gè)基礎(chǔ)鏡像層辕翰,當(dāng)進(jìn)行修改或增加新的內(nèi)容時(shí),就會(huì)在當(dāng)前鏡像層之上狈谊,創(chuàng)建新的鏡像層。舉個(gè)例子,加入基于ubuntu:18.04創(chuàng)建了一個(gè)新的鏡像層河劝,這就是新鏡像層的第一層壁榕;如果在該鏡像中添加python包,就會(huì)在這個(gè)基礎(chǔ)上創(chuàng)建第二個(gè)鏡像層赎瞎;如果繼續(xù)添加一個(gè)安全補(bǔ)丁牌里,就會(huì)創(chuàng)建第三個(gè)鏡像層。
Docker通過(guò)存儲(chǔ)引擎(新版本采用快照機(jī)制)的方式來(lái)實(shí)現(xiàn)鏡像層堆棧务甥,并保證多個(gè)鏡像層對(duì)外展示為一個(gè)統(tǒng)一的文件牡辽。Linux上可用的存儲(chǔ)引擎有AUFS、Overlay2敞临、Device Maooer等等态辛,每種存儲(chǔ)引擎都基于Linux對(duì)應(yīng)的文件系統(tǒng)或者塊設(shè)備技術(shù),并且每種存儲(chǔ)引擎都有獨(dú)特的性能特點(diǎn)挺尿。
Docker通過(guò)共享鏡像層來(lái)節(jié)省空間并且提高性能奏黑。我們使用docker image pull命令的時(shí)候,Docker會(huì)識(shí)別出要拉取的鏡像中编矾,哪幾層已經(jīng)在本地存在的了熟史。這樣只需要拉取不存在的鏡像層即可。
6.2.7 刪除鏡像
當(dāng)不需要某個(gè)鏡像的時(shí)候窄俏,可以通過(guò)docker image rm命令從Docker主機(jī)刪除該鏡像蹂匹,其中,rm是remove的縮寫(xiě)凹蜈。
刪除操作會(huì)在當(dāng)前主機(jī)上刪除該鏡像以及相關(guān)的鏡像層怒详。這意味著無(wú)法通過(guò)docker image ls 命令看到刪除后的鏡像,并且對(duì)應(yīng)的包含鏡像層數(shù)據(jù)的目錄也會(huì)被刪除踪区。但是昆烁,如果某個(gè)鏡像層被多個(gè)鏡像共享,那只有當(dāng)全部依賴(lài)該鏡像層的鏡像都被刪除后缎岗,該鏡像層才會(huì)被刪除静尼。
下面示例使用鏡像ID來(lái)刪除鏡像
[pangcm@qcloud01 ~]$ docker image rm 9b915a241e29
Untagged: nigelpoulton/tu-demo:latest
Untagged: nigelpoulton/tu-demo@sha256:42e34e546cee61adb100144aed000d90e6dc403a0c5b53f324a9e1c1aae451e9
Untagged: nigelpoulton/tu-demo@sha256:9ccc0c67e5c5eaae4bebeeed9b22e0e22f8a35624c1d5c80f2c9623cbcc9b59a
Deleted: sha256:9b915a241e29dc2767980445e3109412b1905b6f1617aea7098e7ac1e5837ae2
Deleted: sha256:27eb08aec7b41dbfa2fd49bc2b3fad9b020fe40b0bc8289af7f53770f0843e7d
如果被刪除的鏡像上存在運(yùn)行狀態(tài)的容器,那么該刪除操作不會(huì)被允許传泊。再次執(zhí)行刪除鏡像命令之前鼠渺,需要停止并刪除該鏡像相關(guān)的全部容器。
要快速刪除Dokcer 主機(jī)上的全部鏡像眷细,可以使用docker image ls -q 來(lái)傳入鏡像ID拦盹。如下:
docker image rm $(docker image ls -q) -f
6.3 鏡像——命令
- docker image pull 是下載鏡像的命令。
- docker image ls 列出了本地Docker主機(jī)上存儲(chǔ)的鏡像溪椎。
- docker image inspect 命令可以展示鏡像的細(xì)節(jié)普舆,包括鏡像層和元數(shù)據(jù)恬口。
- docker image rm 用于刪除鏡像。
6.4 本章小結(jié)
在本章中沼侣,讀者學(xué)習(xí)了Docker鏡像的相關(guān)內(nèi)容祖能,包括鏡像和虛擬機(jī)模板很類(lèi)似,可用于啟動(dòng)容器蛾洛;鏡像由一個(gè)或者多個(gè)只讀鏡像層構(gòu)成养铸,當(dāng)多個(gè)鏡像層堆疊在一起,就構(gòu)成了一個(gè)完整鏡像轧膘。
本書(shū)使用Docker image pull命令拉取到Docker主機(jī)本地倉(cāng)庫(kù)钞螟。此外,本章還涵蓋了鏡像命名谎碍、官方和非官方倉(cāng)庫(kù)鳞滨、鏡像分層、鏡像層共享以及加密ID等等椿浓。本章還極少了Docker是如何支持多架構(gòu)和多平臺(tái)鏡像的太援,并且在本章最后重新梳理了常見(jiàn)的鏡像操作命令。