docker有兩個重要的概念:鏡像,容器。
1.鏡像
docker pull ubuntu:15.04
使用上面的命令可以下載一個ubuntu鏡像,這裡我沒有指定倉庫,默認是從Docker Hub下載。
使用下面命令查看本地鏡像的信息
docker images
有一個問題:為什麼docker下載的鏡像只有131.3MB,而通常我們在虛擬機中安裝ubuntu的鏡像一般都有3個G多?
這裡需要說明一個概念,傳統虛擬機上面安裝的鏡像包含兩個部分,一個是Linux內核的發行版(比如Linux3.13內核),一個是作業系統的發行版(比如說ubuntu15.04),這部分內容不包含Linux內核,但是包含Linux之外的軟體管理方式,軟體驅動,如 apt-get軟體管理包等。內核和發行版是相對獨立的,我們可能都做過這樣的事:升級發行版中的內核。同樣的道理相同的內核也可以對應不同的發行版,docker的鏡像就是利用了這個技術。
使用docker pull ubuntu:15.04命令下載鏡像時系統會出現這樣的消息
給人的第一感覺就是鏡像並不是鐵板一塊,好像是分成4個部分,一個一個的下載。事實也確實如此,下面就要介紹鏡像的分層概念。
首先在說一下docker鏡像的存儲位置/var/lib/docker/,在aufs/layer/下可以看到ubuntu15.04鏡像的分層,正是這四層組成了ubuntu15.04鏡像。
在aufs/diff目錄下使用 ls | xargs ls命令,下圖所顯示的內容相信大家都已經很熟悉了
有人可能已經觀察到了下載時所顯示的層標識和在aufs/layer/下看到的不一樣,首先說一下下載時顯示的ID
在docker 1.10之前鏡像和分層數據通過一個隨機產生的UUID標識,到1.10版本時docker引入了哈希值的方式,而且在1.10之前層ID與aufs/layer/下的目錄名是相同的,1.10之後也變得不一樣了。
鏡像分層的可以使得鏡像的規模變小了很多,這裡通過自己創建一個鏡像來說明。下面用一個簡單的Dockerfile來創建鏡像,將Dockerfile放到當前目錄下。
Dockerfile內容:
FROM ubuntu:15.04RUN echo "hello world" > /tmp/newfile
執行docker build命令
docker build -t changed-ubuntu .
生成的鏡像ID為769951131a6a,使用docker images查看
使用docker history命令查看創建了那些鏡像層
docker history changed-ubuntu
這裡可以看出新創建的changed-ubuntu鏡像並不是所有的東西的是新的,它只是在原有的ubuntu15.04上增加了一層,這個層只有12B。一個鏡像可以被重複利用創建新的鏡像,這會使得鏡像可以被高效的存儲和創建。
2.容器
下面介紹一下創建一個容器的過程。
鏡像是靜態的,鏡像的每一層都只是可讀的,而容器是動態的裡面運行著我們指定的應用,容器裡面的應用可能會新建一個文件,修改一個目錄,這些操作所帶來的改變並不會作用到鏡像裡面,因為鏡像只是可讀的。所以通過鏡像創建容器就是在鏡像上加一個可讀寫的層。下面的圖引用自docker docs,ID上有些不同。
一個鏡像可創建多個容器,每個容器都有各自的一個可讀寫層,這些層相互獨立共享下面的鏡像