刪除本地映像檔

如果要刪除本地的映像檔,可以使用 docker rmi 指令,其格式為:

docker rmi [選項] <映像檔1> [<映像檔2> ...]

注意 docker rm 指令是刪除容器,不要混淆。

用 ID、映像檔名、摘要刪除映像檔

其中,<映像檔> 可以是 映像檔短 ID映像檔長 ID映像檔名 或是 映像檔摘要

比如我們有這麼一些映像檔:

$ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
centos                      latest              0584b3d2cf6d        3 weeks ago         196.5 MB
redis                       alpine              501ad78535f0        3 weeks ago         21.03 MB
docker                      latest              cf693ec9b5c7        3 weeks ago         105.1 MB
nginx                       latest              e43d811ce2f4        5 weeks ago         181.5 MB

我們可以用映像檔的完整 ID,也稱為 長 ID,來刪除映像檔。使用指令碼的時候可能會用長 ID,但是人工輸入就太累了,所以更多的時候是用 短 ID 來刪除映像檔。docker images 預設列出的就已經是短 ID 了,一般取前3個字型以上,只要足夠區分於別的映像檔就可以了。

比如這裡,如果我們要刪除 redis:alpine 映像檔,可以執行:

$ docker rmi 501
Untagged: redis:alpine
Untagged: [email protected]:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d
Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7
Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b
Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
Deleted: sha256:127227698ad74a5846ff5153475e03439d96d4b1c7f2a449c7a826ef74a2d2fa
Deleted: sha256:1333ecc582459bac54e1437335c0816bc17634e131ea0cc48daa27d32c75eab3
Deleted: sha256:4fc455b921edf9c4aea207c51ab39b10b06540c8b4825ba57b3feed1668fa7c7

我們也可以用映像檔名,也就是 <倉庫名>:<標籤>,來刪除映像檔。

$ docker rmi centos
Untagged: centos:latest
Untagged: [email protected]:b2f9d1c0ff5f87a4743104d099a3d561002ac500db1b9bfa02a783a46e0d366c
Deleted: sha256:0584b3d2cf6d235ee310cf14b54667d889887b838d3f3d3033acd70fc3c48b8a
Deleted: sha256:97ca462ad9eeae25941546209454496e1d66749d53dfa2ee32bf1faabd239d38

當然,更精確的是使用 映像檔摘要 刪除映像檔。

$ docker images --digests
REPOSITORY                  TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
node                        slim                sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228   6e0c4c8e3913        3 weeks ago         214 MB

$ docker rmi [email protected]:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
Untagged: [email protected]:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228

Untagged 和 Deleted

如果觀察上面這幾個指令的執行輸出資訊的話,你會注意到刪除行為分為兩類,一類是 Untagged,另一類是 Deleted。我們之前介紹過,映像檔的唯一識別是其 ID 和摘要,而一個映像檔可以有多個標籤。

因此當我們使用上面指令刪除映像檔的時候,實際上是在要求刪除某個標籤的映像檔。所以首先需要做的是將滿足我們要求的所有映像檔標籤都取消,這就是我們看到的 Untagged 的資訊。因為一個映像檔可以對應多個標籤,因此當我們刪除了所指定的標籤後,可能還有別的標籤指向了這個映像檔,如果是這種情況,那麼 Delete 行為就不會發生。所以並非所有的 docker rmi 都會產生刪除映像檔的行為,有可能僅僅是取消了某個標籤而已。

當該映像檔所有的標籤都被取消了,該映像檔很可能會失去了存在的意義,因此會觸發刪除行為。映像檔是多層儲存結構,因此在刪除的時候也是從上層向基礎層方向依次進行判斷刪除。映像檔的多層結構讓映像檔復用變動非常容易,因此很有可能某個其它映像檔正依賴於目前映像檔的某一層。這種情況,依舊不會觸發刪除該層的行為。直到沒有任何層依賴目前層時,才會真實的刪除目前層。這就是為什麼,有時候會奇怪,為什麼明明沒有別的標籤指向這個映像檔,但是它還是存在的原因,也是為什麼有時候會發現所刪除的層數和自己 docker pull 看到的層數不一樣的源。

除了映像檔依賴以外,還需要注意的是容器對映像檔的依賴。如果有用這個映像檔啟動的容器存在(即使容器沒有執行),那麼同樣不可以刪除這個映像檔。之前講過,容器是以映像檔為基礎,再加一層容器儲存層,組成這樣的多層儲存結構去執行的。因此該映像檔如果被這個容器所依賴的,那麼刪除必然會導致故障。如果這些容器是不需要的,應該先將它們刪除,然後再來刪除映像檔。

用 docker images 指令來配合

像其它可以承接多個實體的指令一樣,可以使用 docker images -q 來配合使用 docker rmi,這樣可以成批的刪除希望刪除的映像檔。比如之前我們介紹過的,刪除虛懸映像檔的指令是:

$ docker rmi $(docker images -q -f dangling=true)

我們在「映像檔清單」章節介紹過很多過濾映像檔清單的方式都可以拿過來使用。

比如,我們需要刪除所有倉庫名為 redis 的映像檔:

$ docker rmi $(docker images -q redis)

或是刪除所有在 mongo:3.2 之前的映像檔:

$ docker rmi $(docker images -q -f before=mongo:3.2)

充分利用你的想像力和 Linux 指令行指令列的強大,你可以完成很多非常讚的功能。

CentOS/RHEL 的使用者需要注意的事項

在 Ubuntu/Debian 上有 UnionFS 可以使用,如 aufs 或是 overlay2,而 CentOS 和 RHEL 的核心中沒有相關驅動。因此對於這類系統,一般使用 devicemapper 驅動利用 LVM 的一些機制來類比分層儲存。這樣的做法除了效能比較差外,穩定性一般也不好,而且設定相對複雜。Docker 安裝在 CentOS/RHEL 上後,會 預設選擇 devicemapper,但是為了簡化設定,其 devicemapper 是跑在一個稀疏檔案類比的塊裝置上,也被稱為 loop-lvm。這樣的選擇是因為不需要額外設定就可以執行 Docker,這是自動設定唯一能做到的事情。但是 loop-lvm 的做法非常不好,其穩定性、效能更差,無論是日誌還是 docker info 中都會看到警告資訊。官方文件有明確的文章講解了如何設定塊裝置給 devicemapper 驅動做儲存層的做法,這類做法也被稱為設定 direct-lvm

除了前面說到的問題外,devicemapper + loop-lvm 還有一個缺陷,因為它是稀疏檔案,所以它會不斷增長。使用者在使用程序中會注意到 /var/lib/docker/devicemapper/devicemapper/data 不斷增長,而且無法控制。很多人會希望刪除映像檔或是可以解決這個問題,結果發現效果並不明顯。原因就是這個稀疏檔案的空間釋放後基本不進行垃圾回收的問題。因此往往會出現即使刪除了檔案內容,空間卻無法回收,隨著使用這個稀疏檔案一直在不斷增長。

所以對於 CentOS/RHEL 的使用者來說,在沒有辦法使用 UnionFS 的情況下,一定要設定 direct-lvmdevicemapper,無論是為了效能、穩定性還是空間利用率。

或許有人注意到了 CentOS 7 中存在被 backports 回來的 overlay 驅動,不過 CentOS 裡的這個驅動達不到生產環境使用的穩定程度,所以不推薦使用。

results matching ""

    No results matching ""