動手玩Windows 10 Docker(8) - 聰明的Docker是怎樣儲存Image的?

Windows 10 Docker 是2016年度更新後很大的一個進步但(好像)被很多人忽略沒有話題性

這個系列是我的學習筆記也順便推廣這好用的東西

今天我們來看看Docker在儲存Images上所用的分層(Layers)策略

 

大家有沒有奇怪過在進行Docker Pull時這個畫面是甚麼意思? 那些像亂碼的是甚麼東西?

這就是我今日的研究課題


我們可以看到當我們抓取ubuntu 15.04時, 它下載了4個東西

如果我們在Google查看一下Ubuntu 15的Project code, 可以知道他有個別號叫vivid

再用以往的方式看看, Ubuntu也有vivid這個tag的Image可以抓下來

如果我嘗試抓這個Image的話, docker的回報是這樣

在我們的Image列表上這兩個分別以不同的筆數顯示出來, 但Image ID是相同的

這裡我們可以了解, 這兩個Ubuntu的版本其實是相同的一個Image, 但只是下了不同的Tag去識別 (所以sha256的digest碼還是有分別)

在下載回來的時候, Docker很聰明地知道在Host上已經有同樣的4個Image Layers, 所以不需要再下載了

這種以Layer的方式儲存和共用空間的概念, 使得Docker在建立Image資料庫時可以更有效善用空間

要驗證Docker Image有層層遞進的概念, 我們要繼續做個小實驗, 在Ubuntu:15.04上加一點東西, 做我們自己的Image

運用Dockerfile, 我們可以製造一個副本去建立新的Image

這個例子只簡單的說在 /tmp 裡增加一個檔案, 裡面隨便寫東西

再以docker build指令要docker 以這個目錄的Dockerfile為藍本建立新的 Image

docker build -t newubuntu .

最後的這個 "." 是叫docker請在當前目錄找Dockerfile

留意Docker在做甚麼, 首先它拿到 ubuntu:15.04 Image ID是 d1b55fd07600 的這個Image​

運行一個暫時性的Container, 把dockerfile中所有的步驟執行

最後集結成一個擁有Image ID 767178b625fd的新Docker Image

再來我們看看這個新建的newubuntu Image一些歷史資料

docker history 這個指令可以看到這個Image曾經被人做過甚麼增改

docker history newubuntu

可以看到這個newubuntu有個紀錄是它是建立於d1b55fd07600這個Image ID上

甚至我做過甚麼都可以看到...那現在我來做個逆向測試

如果我現在把ubuntu 15.04和vivid image移除, 剩下newubuntu, 再下載Ubuntu 15.04那我需要下載甚麼嗎?

移除Image的指令是docker rmi (RMI 怕大家看不清楚)

docker rmi ubuntu:15.04

docker rmi ubuntu:vivid


在進行第2次docker rmi ubuntu:vivid時有一點點東西有趣, 就是docker把兩個sha256的tag拿掉了

尾碼29018和1510f正正是ubuntu:15.04和ubuntu:vivid的sha256 digest, 可以說這兩個Image真的"消失"了

但當我再docker pull ubuntu:15.04是, 系統顯示我已經不需要再下載任何東西

推論說當Docker進行untag的時候, 兼查各個Layer還有沒有其他Image正在共享中, 只要還有一個Image有使用那些Layer

Docker都不會完全把資料消去

假如要移除的是ubuntu:15.10, 由於沒有其他Image要使用那些Image Layers了, 

Docker就真的把它們從host中刪除 (deleted)

這個逆向測試證明Docker真的可以在Host裡找到重覆的Docker Image Layers而不會浪費你更多儲存空間

建基於這個思維, 下一篇我們進一步看看以Image起動的Containers又是怎樣的存在!