原文地址: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
,如下圖
則會列出所有滿足條件的映象,點開nginx
結果連結,可以看到提供的版本(通過版本連結可以檢視定義對應映象的Dockerfile),及相應的文件說明。這種方式獲取的資訊更加全面,所以推薦這種方式!
另外,當我們沒有執行docker pull
,直接通過docker run xx
來執行一個容器時,如果沒有對應的映象,則會先自動下載映象,再基於映象啟動一個容器,比如我們在Docker筆記(三):Docker安裝與配置中檢驗docker是否安裝成功時執行的hello-world
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 ...
由上面命令的執行結果可見,刪除映象包括另個行為:Untagged、Deleted。
當我們使用上面命令來刪除映象的時候,實際上是在要求刪除某個/某些標籤的映象。所以首先需要做的是將滿足要求的所有映象標籤都取消,這就是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 (一個不只有技術乾貨的公眾號,歡迎關注,及時獲取更新內容)
———————————————————————————————————————————————————————————