【Docker 系列】docker 學習 四,映象相關原理

小魔童哪吒發表於2021-11-14

【Docker 系列】docker 學習 四,映象相關原理

映象是什麼?

映象是一種輕量級的,可執行的獨立的軟體包。

映象用來打包軟體的執行環境和基於執行環境開發的軟體,它包含執行某些軟體所需要的所有內容,例如:程式碼,執行時庫,環境變數和配置檔案等等

所有的應用,可以直接打包 docker 映象,一鍵部署,一鍵執行

得到映象方式有哪些?

  • 直接拷貝其他 docker 映象
  • 自己製作一個映象 DockerFile
  • 從遠端倉庫下載,如 dockerhub

Docker 映象的載入原理

UnionFS

UnionFS,是聯合檔案系統,還記的我們 docker 學習二 裡面安裝 redis 的時候,出現的分層下載嗎

這就是聯合檔案系統

UnionFS 聯合檔案系統,是一種分層,輕量級並且高效能的檔案系統

它支援對檔案系統的修改作為一次提交來一層一層的疊加,同時可以將不同目錄掛載到一個虛擬檔案系統下

UnionFS 聯合檔案系統是 Docker 映象的基礎,映象還可以通過分層來繼承,基於基礎的映象,我們可以製作成各種應用映象

特性:

聯合檔案系統一次同時載入多個檔案系統,聯合載入會把各層的檔案系統疊加起來,最終的檔案系統會包含所有底層的檔案和目錄

Docker 的映象載入原理是什麼呢?

圖片來源於網路

Docker 的映象是有一層一層的檔案系統組成的,這個層級的檔案系統就叫做聯合檔案系統,一般底下的層都是共用的

一般系統啟動,是一個載入的過程,這個過程是 bootloader 引導載入 kernel,linux 作業系統剛啟動的時候還會載入 bootfs 檔案系統,而我們們的 Docker 映象最底層就是 bootfs

bootfs

boot file system 是一個檔案系統,主要是包含 bootloader 和 kernel

當 boot 載入完畢之後,整個核心都在執行正在記憶體中的,此時記憶體的使用權已經由 bootfs 交接給核心,這個時候系統會將 bootfs 解除安裝掉

rootfs

在來說一下 rootfs,root file system,根檔案系統,它是在 bootfs 之上的,就是包含了,linux 作業系統中的 /dev ,/proc,/bin,/etc 等目錄和檔案

例如我們知道的 rootfs 有 centos,ubuntu等等

分層原理

我們來下載一個 redis 看看效果

Docker 是按照層級進行下載,之前下載過的層級就不會再次下載了,我們可以通過 docker inspect 檢視 redis 的細節

# docker inspect redis:latest
...
"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4",
                "sha256:dd1ebb1f5319785e34838c7332a71e5255bda9ccf61d2a0bf3bff3d2c3f4cdb4",
                "sha256:11f99184504048b93dc2bdabf1999d6bc7d9d9ded54d15a5f09e36d8c571c32d",
                "sha256:e461360755916af80821289b1cbc503692cf63e4e93f09b35784d9f7a819f7f2",
                "sha256:45f6df6342536d948b07e9df6ad231bf17a73e5861a84fc3c9ee8a59f73d0f9f",
                "sha256:262de04acb7e0165281132c876c0636c358963aa3e0b99e7fbeb8aba08c06935"
            ]
        },
...

如上結果我們可以看到,redis 的層級與我們 pull 拉取映象時候的層級一致

那麼Docker 為什麼要採用分層下載呢?

主要是為了共享資源

例如我們的多個映象都是從基礎映象構建而來,那麼宿主機只需要在機器上保留一份基礎映象即可,並且記憶體中也只需要載入一份基礎映象,就可以為所有需要的容器服務,而且映象的每一層也都是可以共享的

我們可以這樣來理解:

所有的 Docker 映象都來源於基礎映象,我們增加或修改映象內容的時候,就會在當前映象層上面,新建一個映象層,這就例如 windows 裡面的一個安全補丁

如上面圖例:

我們在映象的第一層,放置 file1,file2,映象的第二層放置 file3,file4,映象的第三層放置file3.1 (file3.1 是 file3 的一個新版本)

那麼,我們在打包映象的時候,就會合並出 一個映象裡面,有 4 個檔案,此處也就是 4個 layer

當我們下載這個最終合併的映象時,就會一次下載上述的 4 個layer

Docker 映象的特點:

Docker 映象預設都是隻讀的,當容器啟動時,一個新的可寫層被載入到映象的頂部

上面說的這一層就是我們們的容器層,容器層下面是映象層,如下圖所示

如何提交我們們的映象

Docker 提交原理和命令與 Git 類似

docker commit

提交當前容器,成為一個新的版本

我們一般會這樣使用

docker commit -m="描述資訊" -a="作者" 容器ID 目標映象名:[TAG]

舉個例子:

我們們自己修改一下 nginx 映象,作為我們自己的映象來使用

啟動 nginx ,設定埠對映為 -p 8888:80

docker run -d -p 8888:80 nginx

以互動方式進入 nginx

# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES
30841a3a26cb   nginx     "/docker-entrypoint.…"   4 seconds ago   Up 2 seconds   0.0.0.0:8888->80/tcp   strange_hugle

# docker exec -it 30841a3a26cb /bin/bash

進入到nginx 的html 目錄,將index.html 檔案替換掉,,nginx重新載入配置

#cd /usr/share/nginx/html
#ls
50x.html  index.html
#mv index.html index.html.bak
#mv 50x.html index.html
#/usr/sbin/nginx -s reload

這個時候,我們訪問一個伺服器的 8888 埠,檢視效果(我們將正常的 index.html 頁面,換成了一個顯示錯誤的頁面)

如上圖,果然更換成功了

我們們來進行一下 commit

docker commit -a="xiaomotong" -m="modify index.html" 30841a3a26cb nginx01:1.0

~# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                  NAMES
30841a3a26cb   nginx     "/docker-entrypoint.…"   10 minutes ago   Up 10 minutes   0.0.0.0:8888->80/tcp   strange_hugle
root@iZuf66y3tuzn4wp3h02t7pZ:~# docker commit -a="xiaomotong" -m="modify index.html" 30841a3a26cb nginx01:1.0
sha256:1d072fa616573ba67a103925c6114e40171eb1d14ca573f146a28b8c51e5fdff
root@iZuf66y3tuzn4wp3h02t7pZ:~# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
nginx01               1.0       1d072fa61657   3 seconds ago   133MB
ubuntu                latest    1318b700e415   7 days ago      72.8MB
redis                 latest    aa4d65e670d6   11 days ago     105MB
nginx                 latest    08b152afcfae   12 days ago     133MB
portainer/portainer   latest    580c0e4e98b0   4 months ago    79.1MB

如果我們想要儲存自己的容器當前狀態,我們們就可以通過 commit 來提交,獲得一個想要的映象,這就有點像使用虛擬機器打快照一樣

參考資料:

docker docs

歡迎點贊,關注,收藏

朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力

好了,本次就到這裡

技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~

相關文章