docker鏡像的相關概念
鏡像體積:
列出已經下載下來的鏡像,可以使用 docker image ls 命令:
[root@work ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 9f38484d220f 32 hours ago 202 MB
-如果仔細觀察,會注意到,這裏標識的所佔用空間和在 Docker Hub 上看到的鏡像大小不同。比如, centos:latest 顯示鏡像大小是202 MB ,但是在 Docker Hub 顯示的卻是 50MB 。
-這是因爲 Docker Hub 中顯示的體積是壓縮後的體積。在鏡像下載和上傳過程中鏡像是保持着壓縮狀態的,因此 Docker Hub 所顯示的大小是網絡傳輸中更關心的流量大小。而docker image ls 顯示的是鏡像下載到本地後展開的大小,準確說,是展開後的各層所佔空間的總和,因爲鏡像到本地後,查看空間的時候,更關心的是本地磁盤空間佔用的大小。
-另外一個需要注意的問題是, docker image ls 列表中的鏡像體積總和並非是所有鏡像實際硬盤消耗。由於 Docker 鏡像是多層存儲結構,並且可以繼承、複用,因此不同鏡像可能會因爲使用相同的基礎鏡像,從而擁有共同的層。由於 Docker 使用 Union FS,相同的層只需要保存一份即可,因此實際鏡像硬盤佔用空間很可能要比這個列表鏡像大小的總和要小的多。可以通過以下命令來便捷的查看鏡像、容器、數據卷所佔用的空間。
[root@work ~]# docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 2 2 201.8 MB 0 B (0%)
Containers 2 0 6 B 6 B (100%)
Local Volumes 0 0 0 B 0 B
虛懸鏡像:
在鏡像列表中,可能看到一些特殊的鏡像,鏡像既沒有倉庫名,也沒有標籤,均爲 <none> 。:
<none> <none> 00285df0df87 5 days ago 342 MB
這個鏡像原本是有鏡像名和標籤的,原來爲 mongo:3.2 ,隨着官方鏡像維護,發佈了新版本後,重新 docker pull mongo:3.2 時, mongo:3.2 這個鏡像名被轉移到了新下載的鏡像身上,而舊的鏡像上的這個名稱則被取消,從而成爲了 <none> 。
除了 docker pull 可能導致這種情況, docker build 也同樣可以導致這種現象。由於新舊鏡像同名,舊鏡像名稱被取消,從而出現倉庫名、標籤均爲 <none> 的鏡像。這類無標籤鏡像也被稱爲 虛懸鏡像(dangling image) ,可以用下面的命令專門顯示這類鏡像:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 00285df0df87 5 days ago 342 MB
一般來說,虛懸鏡像已經失去了存在的價值,是可以隨意刪除的,可以用下面的命令刪除:$ docker image prune
中間層鏡像:
爲了加速鏡像構建、重複利用資源,Docker 會利用 中間層鏡像。所以在使用一段時間後,可能會看到一些依賴的中間層鏡像。默認的 docker image ls 列表中只會顯示頂層鏡像,如果顯示包括中間層鏡像在內的所有鏡像的話,需要加 -a 參數。
$ docker image ls -a
這樣會看到很多無標籤的鏡像,與之前的虛懸鏡像不同,這些無標籤的鏡像很多都是中間層鏡像,是其它鏡像所依賴的鏡像。這些無標籤鏡像不應該刪除,否則會導致上層鏡像因爲依賴丟失而出錯。實際上,這些鏡像也沒必要刪除,因爲之前說過,相同的層只會存一遍,而這些鏡像是別的鏡像的依賴,因此並不會因爲它們被列出來而多存了一份,無論如何你也會需要它們。只要刪除那些依賴它們的鏡像後,這些依賴的中間層鏡像也會被連帶刪除。
只列出鏡像ID:
$ docker image ls -q
5f515359c7f8
05a60462f8ba
fe9198c04d62
00285df0df87
f753707788c5
f753707788c5
1e0c3dd64ccd
刪除本地鏡像:
如果要刪除本地的鏡像,可以使用 docker image rm 命令,其格式爲:
$ docker image rm [選項] <鏡像1> [<鏡像2> ...]
- 可以用鏡像的完整 ID,也稱爲長ID,來刪除鏡像。
- 可以用 短 ID 來刪除鏡像。 docker image ls 默認列出的就已經是短ID 了,一般取前3個字符以上,只要足夠區分於別的鏡像就可以。
- 可以用 鏡像名 ,也就是 <倉庫名>:<標籤> ,來刪除鏡像。
用 docker image ls 命令來配合使用:
像其它可以承接多個實體的命令一樣,可以使用 docker image ls -q 來配合使用 docker image rm ,這樣可以成批的刪除希望刪除的鏡像。
比如,我們需要刪除所有倉庫名爲 redis 的鏡像:
$ docker image rm $(docker image ls -q redis)
或者刪除所有在 mongo:3.2 之前的鏡像:
$ docker image rm $(docker image ls -q -f before=mongo:3.2)
顯示鏡像摘要:
[root@work ~]# docker image ls --digests
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
docker.io/centos latest sha256:a81ea5364ff9199b53c7de2eda6dffbff0739116a0908c39e83d7d74b2702a71 9f38484d220f 33 hours ago 202 MB
docker.io/hello-world latest sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535 fce289e99eb9 2 months ago 1.84 kB
devicemapper + loop-lvm 的缺陷問題:
因爲它是稀疏文件,所以它會不斷增長。用戶在使用過程中會注意到 /var/lib/docker/devicemapper/devicemapper/data 不斷增長,而且無法控制。很多人會希望刪除鏡像或者可以解決這個問題,結果發現效果並不明顯。原因就是這個稀疏文件的空間釋放後基本不進行垃圾回收的問題。因此往往會出現即使刪除了文件內容,空間卻無法回收,隨着使用這個稀疏文件一直在不斷增長。
所以對於 CentOS/RHEL 的用戶來說,在沒有辦法使用 UnionFS 的情況下,一定要配置 direct-lvm 給 devicemapper ,無論是爲了性能、穩定性還是空間利用率。
或許有人注意到了 CentOS 7 中存在被 backports 回來的 overlay 驅動,不過 CentOS 裏的這個驅動達不到生產環境使用的穩定程度,所以不推薦使用。