天天看點

第八篇:Docker鏡像結構原理

一、base 鏡像

base 鏡像有兩層含義:

1. 不依賴其他鏡像,從 scratch 建構。
2. 其他鏡像可以之為基礎進行擴充。           

base 鏡像的通常都是各種 Linux 發行版的 Docker 鏡像,比如 Ubuntu, Debian, CentOS 等,以 CentOS 為例學習 base 鏡像包含哪些内容。

下載下傳鏡像:

[root@docker ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
af4b0a2388c6: Pull complete
Digest: sha256:2671f7a3eea36ce43609e9fe7435ade83094291055f1c96d9d1d1d7c0b986a5d
Status: Downloaded newer image for centos:latest ##下載下傳centos最新鏡像           

檢視鏡像資訊:

[root@docker ~]# docker images centos
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              ff426288ea90        4 weeks ago         207MB           

使用docker pull centos下載下傳最新版本的Centos鏡像也就207M左右,而我們平時下載下傳一個原生的centos鏡像都是4G,對于 Docker 初學者都會有這個疑問。

下面來了解下Linux 作業系統由核心空間和使用者空間組成,如下圖所示:

第八篇:Docker鏡像結構原理

rootfs

核心空間是 kernel,Linux 剛啟動時會加載 bootfs 檔案系統,之後 bootfs 會被解除安裝掉。

使用者空間的檔案系統是 rootfs,包含我們熟悉的 /dev, /proc, /bin 等目錄。

對于 base 鏡像來說,底層直接用 Host 的 kernel,自己隻需要提供 rootfs 就行了。

而對于一個精簡的 OS,rootfs 可以很小,隻需要包括最基本的指令、工具和程式庫就可以了。相比其他 Linux 發行版,CentOS 的 rootfs 已經算臃腫的了,alpine 還不到 10MB。

我們平時安裝的 CentOS 除了 rootfs 還會選裝很多軟體、服務、圖形桌面等,需要好幾個 GB 就不足為奇了。

base 鏡像提供的是最小安裝的 Linux 發行版。

下面是 CentOS 鏡像的 Dockerfile 的内容:

第八篇:Docker鏡像結構原理

第二行 ADD 指令添加到鏡像的 tar 包就是 CentOS 7 的 rootfs。在制作鏡像時,這個 tar 包會自動解壓到 / 目錄下,生成 /dev, /porc, /bin 等目錄。

注:可在 Docker Hub 的鏡像描述頁面中檢視 Dockerfile 。

支援運作多種 Linux OS

不同 Linux 發行版的差別主要就是 rootfs。

比如 Ubuntu 14.04 使用 upstart 管理服務,apt 管理軟體包;而 CentOS 7 使用 systemd 和 yum。這些都是使用者空間上的差別,Linux kernel 差别不大。

是以 Docker 可以同時支援多種 Linux 鏡像,模拟出多種作業系統環境。

第八篇:Docker鏡像結構原理

上圖 Debian 和 BusyBox上層提供各自的 rootfs,底層共用 Docker Host 的 kernel。

注意:base 鏡像隻是在使用者空間與發行版一緻,kernel 版本與發型版是不同的。

[root@docker ~]# uname -r
3.10.0-514.el7.x86_64                 ##Host kernel 為 3.10.0-514
[root@docker ~]# docker run -ti centos    ##啟動并進入 CentOS 容器
[root@263132669aa3 /]# cat /etc/redhat-release   ##驗證容器是 CentOS 7
CentOS Linux release 7.4.1708 (Core)
[root@263132669aa3 /]# uname -r      ##容器的 kernel 版本與 Host 一緻
3.10.0-514.el7.x86_64
           

說明:

容器隻能使用 Host 的 kernel,并且不能修改。所有容器都共用 host 的 kernel,在容器中沒辦法對 kernel 更新。如果容器對 kernel 版本有要求(比如應用隻能在某個 kernel 版本下運作),則不建議用容器,這種場景虛拟機可能更合适。

二、鏡像的分層結構

Docker 支援通過擴充現有鏡像,建立新的鏡像。

實際上,Docker Hub 中 99% 的鏡像都是通過在 base 鏡像中安裝和配置需要的軟體建構出來的。比如我們現在建構一個新的鏡像,Dockerfile 如下:

[root@docker ~]# docker pull debian
Using default tag: latest
latest: Pulling from library/debian
723254a2c089: Pull complete
Digest: sha256:800943bdddf4511392fe453a0eb66eacadf322b392c521700bcac29c0b858582
Status: Downloaded newer image for debian:latest
[root@docker ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
liulei/centos       6.7                 dc64de0c25c4        2 days ago          191MB
liulei/centos       new                 dc64de0c25c4        2 days ago          191MB
liu/ubuntu          v2                  15caed782326        2 days ago          151MB
httpd               latest              2e202f453940        13 days ago         179MB
ubuntu              16.04               0458a4468cbc        2 weeks ago         112MB
centos              latest              ff426288ea90        4 weeks ago         207MB
nginx               latest              3f8a4339aadd        6 weeks ago         108MB
debian              latest              da653cee0545        8 weeks ago         100MB
hello-world         latest              f2a91732366c        2 months ago        1.85kB
training/webapp     latest              6fae60ef3446        2 years ago         349MB           
第八篇:Docker鏡像結構原理

① 新鏡像不再是從 scratch 開始,而是直接在 Debian base 鏡像上建構。

② 安裝 emacs 編輯器。

③ 安裝 apache2。

④ 容器啟動時運作 bash。

建構過程如下圖所示:

第八篇:Docker鏡像結構原理

可以看到,新鏡像是從 base 鏡像一層一層疊加生成的。每安裝一個軟體,就在現有鏡像的基礎上增加一層。

問什麼 Docker 鏡像要采用這種分層結構呢?

最大的一個好處就是 - 共享資源。

比如:有多個鏡像都從相同的 base 鏡像建構而來,那麼 Docker Host 隻需在磁盤上儲存一份 base 鏡像;同時記憶體中也隻需加載一份 base 鏡像,就可以為所有容器服務了。而且鏡像的每一層都可以被共享。

這時可能就有人會問了:如果多個容器共享一份基礎鏡像,當某個容器修改了基礎鏡像的内容,比如 /etc 下的檔案,這時其他容器的 /etc 是否也會被修改?

答案:不會!因為修改會被限制在單個容器内。

這就是我們接下來要學習的容器 Copy-on-Write 特性。

三、容器的可寫層

  1. 讀取檔案

    在容器中讀取某個檔案時,Docker 會從上往下依次在各鏡像層中查找此檔案。一旦找到,打開并讀入記憶體。

  2. 修改檔案

    在容器中修改已存在的檔案時,Docker 會從上往下依次在各鏡像層中查找此檔案。一旦找到,立即将其複制到容器層,然後修改之。

  3. 删除檔案

    在容器中删除檔案時,Docker 也是從上往下依次在鏡像層中查找此檔案。找到後,會在容器層中記錄下此删除操作。