Docker筆記(四):Docker鏡像管理

原文地址:http://blog.jboost.cn/docker-4.htmlphp

 

在Docker中,應用是經過容器來運行的,而容器的運行是基於鏡像的,相似面向對象設計中類與對象的關係——沒有類的定義就談不上實例的建立與使用,沒有鏡像的定義就談不上容器的建立與運行。

html

1. 獲取鏡像

鏡像從哪裏來,通常兩個途徑,一是公共鏡像庫,如官方鏡像庫Docker Hub,上面有大量的高質量的鏡像直接可拿來用;二是自定義,咱們可基於一個已有鏡像,在其基礎上增長一些層(還記得鏡像的分層存儲特性吧),而後構建造成本身的鏡像。mysql

若是咱們知道某個鏡像的名稱,則可直接經過docker pull來下載鏡像到本地,如ubuntu、redis、nginx等,docker pull命令的格式以下(中括號表示可有可沒有)linux

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

 

其中選項可設置: nginx

  • -a, –all-tags:下載倉庫中全部標籤(通常指版本)的鏡像
  • –disable-content-trust:跳過鏡像驗證,默認爲true

Docker Registry的地址即鏡像倉庫地址,通常爲域名或IP加端口號,若是不指定則默認爲Docker Hub;倉庫名包含兩部分,<用戶名>/<軟件名>,對於Docker Hub,若是不給出用戶名,則默認爲library,表示官方提供;標籤通常是對應軟件的版本號,若是不指定則默認爲latest。web

好比咱們要下一個nginx鏡像,則可執行以下命令redis

[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(第二行),由第四至第六行可見,這個鏡像包含三個層,而且第一個層已經存在了(以前下載的鏡像已經包含了這個層, 直接複用),鏡像分層的概念及層的複用,應該已經理解了。sql

 

若是咱們不知道鏡像的完整名稱怎麼辦,那就搜索一下,有兩個途徑,一是經過命令,假設咱們記不起nginx全稱了, 只記得ngi,則可經過以下命令搜索docker

[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最多,官方提供的鏡像。 ubuntu

這種方式獲取到的信息有限,好比具體包含哪些版本不知道。還有一個途徑是直接在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 (一個不僅有技術乾貨的公衆號,歡迎關注,及時獲取更新內容)
———————————————————————————————————————————————————————————
微信公衆號

相關文章
相關標籤/搜索