查找 Docker 映像的層和層大小
一、概述
容器化技術幫助我們以更低的成本快速構建和配置我們的部署環境。秉承“一次編寫,隨處部署”的座右銘,我們使用容器化來解決現代應用程序的複雜性。
在本教程中,我們將深入研究 Docker 鏡像層,它們是容器化技術的基本構建塊。
2. 圖像層
Docker 鏡像是通過連接許多只讀層創建的,這些層相互堆疊形成一個完整的鏡像。像 Docker 和 Podman 這樣的平台將這些層組合在一起,將它們描繪成一個單一的統一對象。
例如,讓我們從註冊表中拉取一個 MySQL 映像并快速瀏覽一下:
# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
492d84e496ea: Pull complete
bbe20050901c: Pull complete
e3a5e171c2f8: Pull complete
c3aceb7e4f48: Pull complete
269002e5cf58: Pull complete
d5abeb1bd18e: Pull complete
cbd79da5fab6: Pull complete
Digest: sha256:cdf3b62d78d1bbb1d2bd6716895a84014e00716177cbb7e90f6c6a37a21dc796
Status: Downloaded newer image for mysql:latest
上面代碼片段中以“Pull complete”結尾的每一行代表從註冊表中提取的層以形成一個圖像。正如我們所見,MySQL 映像有七層。
2.1。圖像層創建
現在讓我們更深入地了解這些層是如何通過Dockerfile
插圖構建的。
Dockerfile
中的RUN
、 COPY
和ADD
等指令創建新層,而其他指令僅創建中間層。前一個命令對層大小有影響,但後者沒有。
讓我們通過Dockerfile
構建一個鏡像。我們可以從此鏈接引用Dockerfile
。我們使用 docker docker build
命令通過Dockerfile
創建鏡像:
# docker build -t layer-demo/latest .
Sending build context to Docker daemon 3.072kB
Step 1/8 : FROM ubuntu:latest
---> df5de72bdb3b
Step 2/8 : MAINTAINER baeldung.com
---> Running in 2c90e21f29e2
Removing intermediate container 2c90e21f29e2
---> 460d0651cc3d
Step 3/8 : ADD get_date.sh /root/get_date.sh
---> 492d1b205a94
Step 4/8 : RUN chmod 0644 /root/get_date.sh
---> Running in 08d04f1db0de
Removing intermediate container 08d04f1db0de
---> 480ba7f4bc50
Step 5/8 : RUN apt-get update
...
... output truncated ...
...
---> 28182a44db71
Step 6/8 : RUN apt-get -y install cron
...
... output truncated ...
...
---> 822f3eeca346
Step 7/8 : RUN crontab -l | { cat; echo "* * * * * bash /root/get_date.sh"; } | crontab -
---> Running in 635190dfb8d7
no crontab for root
Removing intermediate container 635190dfb8d7
---> 2822aac1f51b
Step 8/8 : CMD cron
---> Running in 876f0d5aca27
Removing intermediate container 876f0d5aca27
---> 5fc87be0f286
Successfully built 5fc87be0f286
這裡發生了什麼事?要創建這個鏡像,我們注意到它需要八個步驟,一個用於Dockerfile
中的每條指令。最初,從註冊表中提取 Ubuntu 映像 [Image ID: df5de72bdb3b
]:
- 它使用上一步的圖像 [Image ID:
df5de72bdb3b
2c90e21f29e2
。 - 之後,在中間容器[Container ID:
2c90e21f29e2
]上執行指令。 - 隨後,中間容器通過 commit 轉換為鏡像 [Image ID:
460d0651cc3d
],導致中間容器 [Container ID:2c90e21f29e2
] 被移除。 - 去掉中間容器後,鏡像就變成了只讀層。然後執行
Dockerfile
中的下一條指令。
但是,新圖層的創建步驟與上述相同。中間層不能影響圖像大小,而使用RUN
、 ADD
和COPY
的普通層能夠增加大小。
3.層大小
通常,圖像的大小完全由與其關聯的層決定。 docker history
命令顯示與圖像關聯的每個層的大小。
在下面的示例中,大小為 0B 的層表示中間層,而RUN
、 COPY
和ADD
指令對圖像大小有貢獻:
# docker history layer-demo/latest
IMAGE CREATED CREATED BY SIZE COMMENT
5fc87be0f286 8 hours ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "cron… 0B
2822aac1f51b 8 hours ago /bin/sh -c crontab -l | { cat; echo "* * * *… 208B
822f3eeca346 8 hours ago /bin/sh -c apt-get -y install cron 987kB
28182a44db71 8 hours ago /bin/sh -c apt-get update 36MB
480ba7f4bc50 8 hours ago /bin/sh -c chmod 0644 /root/get_date.sh 5B
492d1b205a94 8 hours ago /bin/sh -c #(nop) ADD file:1f79f73be93042145… 5B
460d0651cc3d 8 hours ago /bin/sh -c #(nop) MAINTAINER baeldung.com 0B
df5de72bdb3b 4 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
4 weeks ago /bin/sh -c #(nop) ADD file:396eeb65c8d737180… 77.8MB
現在,讓我們總結一下所有層的大小,從基礎圖像開始:
- df5de72bdb3b – 77.800000 MB ## 第 1 步:基礎 Ubuntu 映像
- 492d1b205a94 – 0.000005 MB ## 第 3 步:添加指令
- 480ba7f4bc50 – 0.000005 MB ## 第 4 步:運行指令
- 28182a44db71 – 36.000000 MB ## 第 5 步:運行指令
- 822f3eeca346 – 0.987000 MB ## 第 6 步:運行指令
- 2822aac1f51b – 0.000208 MB ## 第 7 步:運行指令
將上述所有數字加在一起為 114.787 MB,可以進一步四捨五入為 115 MB。正如我們所看到的,計算的總和與docker image
命令中的layer-demo:latest
圖像大小完全匹配:
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
layer-demo/latest latest 5fc87be0f286 8 hours ago 115MB
ubuntu latest df5de72bdb3b 4 weeks ago 77.8MB
4. 懸空圖像
懸空圖像是在圖像形成過程中創建的圖像層。但是,在創建圖像之後,這些圖層將與任何標記的圖像沒有任何關係。因此刪除所有這些圖像是安全的,因為它們會消耗不必要的磁盤空間。
要列出所有懸空圖像,我們可以使用docker image
命令,在搜索過濾器中將懸空屬性設置為 true:
# docker images --filter "dangling=true"
下面的命令顯示了懸空的圖像,然後將它們刪除:
# docker images --quiet --filter=dangling=true | xargs --no-run-if-empty docker rmi
5. 結論
在本文中,我們研究了 Docker 鏡像層的概念和層的創建。此外,我們還討論了可用於識別與圖像關聯的層列表和每層大小的命令。
最後,我們看到了中間層是如何創建的,並了解到如果我們不經常清除懸空圖像,它們就會留在我們的系統上。