Docker筆記(四):Docker映象管理

【空山新雨】發表於2019-07-17

原文地址:http://blog.jboost.cn/2019/07/16/docker-4.html

 

在Docker中,應用是通過容器來執行的,而容器的執行是基於映象的,類似物件導向設計中類與物件的關係——沒有類的定義就談不上例項的建立與使用,沒有映象的定義就談不上容器的建立與執行。

1. 獲取映象

映象從哪裡來,一般兩個途徑,一是公共映象庫,如官方映象庫Docker Hub,上面有大量的高質量的映象直接可拿來用;二是自定義,我們可基於一個已有映象,在其基礎上增加一些層(還記得映象的分層儲存特性吧),然後構建形成自己的映象。

如果我們知道某個映象的名稱,則可直接通過docker pull來下載映象到本地,如ubuntu、redis、nginx等,docker pull命令的格式如下(中括號表示可有可沒有)

docker pull [選項] [Docker Registry的地址[:埠號]/]倉庫名[:標籤]

 

其中選項可設定: 

  • -a, –all-tags:下載倉庫中所有標籤(一般指版本)的映象
  • –disable-content-trust:跳過映象驗證,預設為true

Docker Registry的地址即映象倉庫地址,一般為域名或IP加埠號,如果不指定則預設為Docker Hub;倉庫名包含兩部分,<使用者名稱>/<軟體名>,對於Docker Hub,如果不給出使用者名稱,則預設為library,表示官方提供;標籤一般是對應軟體的版本號,如果不指定則預設為latest。

比如我們要下一個nginx映象,則可執行如下命令

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
fc7181108d40: Already exists 
d2e987ca2267: Pull complete 
0b760b431b11: Pull complete 
Digest: sha256:48cbeee0cb0a3b5e885e36222f969e0a2f41819a68e07aeb6631ca7cb356fed1
Status: Downloaded newer image for nginx:latest

這裡我們沒有指定選項,也沒有指定映象倉庫地址,那麼預設會從Docker Hub獲取映象(但Docker Hub由於在國外,速度比較慢,所以一般要設定國內加速器,參考Docker筆記(三):Docker安裝與配置第二部分:配置國內映象),也沒有給出使用者名稱,所以預設是library(第三行),沒有指定標籤,所以預設是latest(第二行),由第四至第六行可見,這個映象包含三個層,並且第一個層已經存在了(之前下載的映象已經包含了這個層, 直接複用),映象分層的概念及層的複用,應該已經理解了。

 

如果我們不知道映象的完整名稱怎麼辦,那就搜尋一下,有兩個途徑,一是通過命令,假設我們記不起nginx全稱了, 只記得ngi,則可通過如下命令搜尋

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker search ngi
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                             Official build of Nginx.                        11693               [OK]                
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker con…   1628                                    [OK]
richarvey/nginx-php-fpm           Container running Nginx + PHP-FPM capable of…   726                                     [OK]
bitnami/nginx                     Bitnami nginx Docker Image                      69                                      [OK]
linuxserver/nginx                 An Nginx container, brought to you by LinuxS…   69                                      
tiangolo/nginx-rtmp               Docker image with Nginx using the nginx-rtmp…   48                                      [OK]
nginx/nginx-ingress               NGINX Ingress Controller for Kubernetes         20                                      
nginxdemos/hello                  NGINX webserver that serves a simple page co…   18                                      [OK]
jlesage/nginx-proxy-manager       Docker container for Nginx Proxy Manager        17                                      [OK]
schmunk42/nginx-redirect          A very simple container to redirect HTTP tra…   17                                      [OK]
crunchgeek/nginx-pagespeed        Nginx with PageSpeed + GEO IP + VTS + more_s…   13                                      
blacklabelops/nginx               Dockerized Nginx Reverse Proxy Server.          12                                      [OK]
...

該命令會從Docker Hub搜尋映象名包含ngi的映象,其中STARS表示收藏使用者數,OFFICIAL為[OK]表示官方提供的映象,AUTOMATED [OK]表示由自動構建生成,一般選擇STARS最多,官方提供的映象。 

這種方式獲取到的資訊有限,比如具體包含哪些版本不知道。還有一個途徑是直接在Docker Hub網站上搜尋,開啟 https://hub.docker.com , 在搜尋框輸入ngi,如下圖

docker-hub

 

則會列出所有滿足條件的映象,點開nginx結果連結,可以看到提供的版本(通過版本連結可以檢視定義對應映象的Dockerfile),及相應的文件說明。這種方式獲取的資訊更加全面,所以推薦這種方式!

 

另外,當我們沒有執行docker pull,直接通過docker run xx來執行一個容器時,如果沒有對應的映象,則會先自動下載映象,再基於映象啟動一個容器,比如我們在Docker筆記(三):Docker安裝與配置中檢驗docker是否安裝成功時執行的hello-world
hello-docker

 

2. 管理本地映象

將映象下載到本地後,我們可以基於映象來建立、執行容器,及對映象進行管理。

檢視本地映象

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              f68d6e55e065        2 weeks ago         109MB
mysql               latest              c7109f74d339        5 weeks ago         443MB
hello-world         latest              fce289e99eb9        6 months ago        1.84kB

上面各列依次列出了映象名稱、標籤(版本)、映象ID、建立時間、映象大小。映象可以擁有多個標籤(版本)。映象的大小總和一般要大於實際的磁碟佔有量,為什麼?回憶一下映象的分層儲存概念,層是可以複用的,某個層其中一個映象有了,另一個映象就不會再下載了。口說無憑,我們來驗證下,docker system df可列出映象、容器、資料卷所佔用的空間

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              3                   1                   497.1MB             497.1MB (99%)
Containers          1                   0                   0B                  0B
Local Volumes       0                   0                   0B                  0B
Build Cache         0                   0                   0B                  0B

通過docker image ls列出的各映象大小總共約552MB,但這裡列出的映象大小隻有約497MB,這下有憑有據了吧。

 

根據條件列出映象

docker image ls nginx # 根據名稱列出映象
docker image ls nginx:latest # 根據名稱與標籤列出映象
docker image ls -f since=hello-world:latest # -f 是--filter的縮寫,過濾器引數,列出在hello-world:latest之後建立的映象,before=hello-world:latest則檢視之前建立的映象

 

指定顯示格式 

docker image ls -q # 只顯示映象ID
docker image ls --digests # 列出映象摘要

docker image ls --format "{{.ID}}: {{.Repository}}"  # 使用Go的模板語法格式化顯示,這裡顯示格式為 映象ID:映象名稱
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" # 自己定義表格格式

 

虛懸映象 

有時候會看到某些映象既沒有倉庫名,也沒有標籤,均為 <none>。這些映象原本是有映象名和標籤的,隨著官方映象維護,釋出了新版本後(新版本會複用之前的映象名稱與標籤,一般是bug修復版),重新docker pull xx 時, 這個映象名被轉移到了新下載的映象身上,而舊的映象上的這個名稱則被取消,從而成為了<none> 。除了docker pull可能導致這種情況, docker build也同樣可以導致這種現象。由於新舊映象同名,舊映象名稱被取消,從而出現倉庫名、標籤均為 <none> 的映象。這類無標籤映象被稱為虛懸映象(dangling image) ,可以用下面的命令專門顯示這類映象:

docker image ls -f dangling=true

一般虛懸映象沒什麼意義了,可以通過如下命令刪除 

docker image prune

 

中間層映象 

為了加速映象構建、重複利用資源,Docker會利用中間層映象。所以在使用一段時間後,可能會看到一些依賴的中間層映象。預設的docker image ls列表中只會顯示頂層映象,如果希望顯示包括中間層映象在內的所有映象的話,可以加 -a

$ docker image ls -a

這樣會看到很多無標籤的映象,與虛懸映象不同,這些無標籤的映象很多都是中間層映象,是其它映象所依賴的映象。這些無標籤映象不應該刪除,否則會導致上層映象因為依賴丟失而出錯。實際上,這些映象也沒必要刪除,因為相同的層只會存一遍,而這些映象是別的映象的依賴,因此並不會因為它們被列出來而多存了一份,無論如何你也會需要它們。只要刪除那些依賴它們的映象後,這些依賴的中間層映象也會被連帶刪除。 

 

刪除映象
刪除映象命令格式

docker image rm [選項] <映象1> [<映象2> ...]

選項可以設定: 

  • -f, –force 強制刪除映象
  • –no-prune 不刪除沒有標籤的父映象

<映象1>、<映象2> 等可以是映象的名稱,映象的全ID,也可以是映象ID的前面幾個數字(只要與其它映象區分開來就行),或者是映象摘要。 如刪除映象名稱為mysql的映象

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker image rm mysql
Untagged: mysql:latest
Untagged: mysql@sha256:415ac63da0ae6725d5aefc9669a1c02f39a00c574fdbc478dfd08db1e97c8f1b
Deleted: sha256:c7109f74d339896c8e1a7526224f10a3197e7baf674ff03acbab387aa027882a
Deleted: sha256:35d60530f024aa75c91a123a69099f7f6eaf5ad7001bb983f427f674980d8482
Deleted: sha256:49d8bb533eee600076e3a513a203ee24044673fcef0c1b79e088b2ba43db2c17
...

由上面命令的執行結果可見,刪除映象包括另個行為:UntaggedDeleted。 

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

當該映象所有的標籤都被取消了,該映象很可能就失去了存在的意義,因此會觸發刪除行為。映象是多層儲存結構,因此在刪除的時候也是從上層向基礎層方向依次進行判斷刪除。如果某個其它映象正依賴於當前映象的某一層,這種情況,依舊不會觸發刪除該層的行為。直到沒有任何映象依賴當前層時,才會真實的刪除當前層。

另外還需要注意是容器對映象的依賴。如果基於映象啟動的容器存在(即使容器沒有執行處於停止狀態) ,同樣不可以刪除這個映象。我們之前說了容器是以映象為基礎,再加一層容器儲存層組成的多層儲存結構去執行的。所以如果這些容器是不需要的,應該先將它們刪除,然後再來刪除映象。

 

通過組合命令來刪除

docker image rm $(docker image ls -q nginx) # 刪除映象名稱為nginx的所有映象
docker image rm $(docker image ls -q -f since=hello-world:latest) # 刪除所有在hello-world:latest之後建立的映象

 

3. 總結 

本文對映象的獲取及本地映象的基本管理做了介紹,本文映象的獲取途徑都是從映象倉庫直接獲取,映象的另一個獲取途徑便是自定義,接下來會通過例項來進行介紹,歡迎關注。


我的個人部落格地址:http://blog.jboost.cn
我的微信公眾號:jboost-ksxy (一個不只有技術乾貨的公眾號,歡迎關注,及時獲取更新內容)
———————————————————————————————————————————————————————————
微信公眾號

相關文章