映象是什麼?
映象是一種輕量級的,可執行的獨立的軟體包。
映象用來打包軟體的執行環境和基於執行環境開發的軟體,它包含執行某些軟體所需要的所有內容,例如:程式碼,執行時庫,環境變數和配置檔案等等
所有的應用,可以直接打包 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 來提交,獲得一個想要的映象,這就有點像使用虛擬機器打快照一樣
參考資料:
歡迎點贊,關注,收藏
朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力
好了,本次就到這裡
技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是小魔童哪吒,歡迎點贊關注收藏,下次見~
本作品採用《CC 協議》,轉載必須註明作者和本文連結