獲取鏡像
首先說明一下如何從Docker hub中獲取高質量的鏡像,從Docker鏡像庫獲取鏡像的命令是docker pull 。其命令格式為:
docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標簽]
具體的選項可以通過docker pull --help命令看到,下面我們說一下鏡像名稱的格式:
- docker鏡像倉庫地址:地址的格式一般是 <域名/IP>[:端口號] 。默認地址是 DockerHub。
- 倉庫名:倉庫名是兩段式名稱,即<用戶名>/<軟件名>。對於 Docker Hub,如果不給出用戶名,則默認為 library ,也就是官方鏡像
比如:
sudo docker pull ubuntu:16.04
#輸出一下信息
16.04: Pulling from library/ubuntu
50aff78429b1: Pull complete
f6d82e297bce: Pull complete
275abb2c8a6f: Pull complete
9f15a39356d6: Pull complete
fc0342a94c89: Pull complete
Digest: sha256:fbaf303d18563e57a3c1a0005356ad102509b60884f3aa89ef9a90c0ea5d1212
Status: Downloaded newer image for ubuntu:16.04
上述命令沒有給出docker鏡像倉庫地址,將會從docker hub獲取鏡像。鏡像名是ubuntu:16.04,因此將會獲取官方鏡像 library/ubuntu 倉庫中標簽為 16.04 的鏡
像。
從下載過程中可以看到我們之前提及的分層存儲的概念,鏡像是由多層存儲所構成。下載也
是一層層的去下載,並非單一文件。下載過程中給出了每一層的 ID 的前 12 位。並且下載結
束后,給出該鏡像完整的 sha256 的摘要,以確保下載一致性。
有了docker鏡像后,我們就可以以這個鏡像為基礎啟動運行一個容器,以上面的鏡像為例,我們想啟動上面的bash並以交互的方式運行,可以使用一下命令:
sudo docker run -it --rm ubuntu:16.04 bash
docker run是運行容器的命令,上面用到的參數意義如下:
- -it:這是兩個參數,一個是-i交互式操作,一個是-t終端。我們這里打算進入bash 執行一些命令並查看返回結果,因此我們需要交互式終端
- --rm:這個參數是說容器退出后隨之將其刪除
- ubuntu:16.04 :這是指用 ubuntu:16.04 鏡像為基礎來啟動容器
- bash :放在鏡像名后的是命令,這里我們希望有個交互式 Shell,因此用的是 bash
進入容易后,我們可以通過shell執行任何所需要的命令,最后我們通過exit退出這個容器。
列出鏡像
使用sudo docker image ls或則sudo docker images可以列出本地已下載的鏡像。
sudo docker image ls
#結果
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 00fd29ccc6f1 3 weeks ago 111MB
hello-world latest f2a91732366c 6 weeks ago 1.85kB
從上面可知,列表包含了倉庫名,標簽,鏡像ID,創建時間,占用空間這些信息,鏡像ID是鏡像的唯一表示,一個鏡像可以對應多個標簽,相同鏡像ID不同標簽的鏡像可以認為是同一個鏡像
鏡像體積
通過觀察鏡像的size我們可以發現,鏡像表示所占用的空間和docker hub上看到的鏡像的大小不一致。這是因為docker hub顯示的大小是壓縮后的體積大小。鏡像的下載和上傳過程中是保持壓縮狀態的。因此docker hub顯示的大小是壓縮后的體積大小。而docker image看到的是下載到本地后展開后的大小,是展開后各層所占用的空間的總和。查看空間的時候更關心的是本地磁盤空間占用的大小。
另外一個需要注意的問題是, docker image ls 列表中的鏡像體積總和並非是所有鏡像實際硬
盤消耗。由於 Docker 鏡像是多層存儲結構,並且可以繼承、復用,因此不同鏡像可能會因為
使用相同的基礎鏡像,從而擁有共同的層。由於 Docker 使用 Union FS,相同的層只需要保
存一份即可,因此實際鏡像硬盤占用空間很可能要比這個列表鏡像大小的總和要小的多。
可以通過以下命令來便捷的查看鏡像、容器、數據卷所占用的空間:
docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 2 1 110.5MB 110.5MB (99%)
Containers 2 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0B 0B
懸掛鏡像
懸掛鏡像是一種特殊的鏡像,這種鏡像既沒有倉庫名也沒有標簽,他們的值都為
docker image ls -f dangling=true
一般來說,虛懸鏡像已經失去了存在的價值,是可以隨意刪除的,可以用下面的命令刪除:
docker image prune
中間層鏡像
為了加速鏡像構建、重復利用資源,Docker 會利用 中間層鏡像。所以在使用一段時間后,可能會看到一些依賴的中間層鏡像。默認的 docker image ls 列表中只會顯示頂層鏡像,如果
希望顯示包括中間層鏡像在內的所有鏡像的話,需要加 -a 參數
docker image ls -a
列出部分鏡像
不加任何參數的情況下, docker image ls 會列出所有頂級鏡像,但是有時候我們只希望列出
部分鏡像。 docker image ls 有好幾個參數可以幫助做到這個事情。
- 根據倉庫名列出鏡像
docker image ls ubuntu
- 指定倉庫名和標簽列出特定的鏡像
docker image ls ubuntu:16.04
- 使用過濾參數列出鏡像
#如果鏡像構建時,定義了 LABEL ,還可以通過 LABEL 來過濾
docker image ls -f label=com.example.version=0.1
以特定格式顯示鏡像
默認情況下, docker image ls 會輸出一個完整的表格,但是我們並非所有時候都會需要這些
內容。比如,剛才刪除虛懸鏡像的時候,我們需要利用 docker image ls 把所有的虛懸鏡像
的 ID 列出來,然后才可以交給 docker image rm 命令作為參數來刪除指定的這些鏡像,這個
時候就用到了 -q 參數
docker image ls -q
00fd29ccc6f1
f2a91732366c
另外一些時候,我們可能只是對表格的結構不滿意,希望自己組織列;或者不希望有標題,
這樣方便其它程序解析結果等,這就用到了 Go 的模板語法
比如,下面的命令會直接列出鏡像結果,並且只包含鏡像ID和倉庫名:
docker image ls --format "{{.ID}}: {{.Repository}}"
或者打算以表格等距顯示,並且有標題行,和默認一樣,不過自己定義列:
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
00fd29ccc6f1 ubuntu 16.04
f2a91732366c hello-world latest
刪除本地鏡像
刪除本地鏡像可以使用docker image rm 命令格式如下:
docker image rm [選項] <鏡像1> [<鏡像2> ...]
其中, <鏡像> 可以是 鏡像短 ID 、 鏡像長 ID 、 鏡像名 或者 鏡像摘要 。
如果我們需要刪除所有倉庫名為 redis 的鏡像,可以使用下面的命令
docker image rm $(docker image ls -q redis)
Untagged 和 Deleted
刪除行為分為兩類,一類是Untagged,另一類是Deleted。我們使用上述命令刪除的時候,實際上是在要求刪除某個標簽的鏡像,這就是我們看到的Untagged信息。因為一個鏡像可以對應多個標簽,因此當我們刪除了所指定的標簽后,可能還有別的標簽指向了這個鏡像。如果是這種情況,那么 Delete 行為就不會發生。所以並非所有的 docker rmi 都會產生刪除鏡像的行為,有可能僅僅是取消了某個標簽而已。當該鏡像所有的標簽都被取消了,該鏡像很可能會失去了存在的意義,因此會觸發刪除行為。鏡像是多層存儲結構,因此在刪除的時候也是從上層向基礎層方向依次進行判斷刪除。鏡像的多層結構讓鏡像復用變動非常容易,因此很有可能某個其它鏡像正依賴於當前鏡像的某一層。這種情況,依舊不會觸發刪除該層的行為。直到沒有任何層依賴當前層時,才會真實的刪除當前層。除了鏡像依賴以外,還需要注意的是容器對鏡像的依賴。如果有用這個鏡像啟動的容器存在(即使容器沒有運行),那么同樣不可以刪除這個鏡像。