Docker鏡像原理
Linux系統組成
要了解Docker鏡像原理,需要先了解linux作業系統。
作業系統的組成部分分為:程序排程子系統、程序通信子系統、記憶體管理子系統、裝置管理子系統、檔案管理子系統、網絡通信子系統、作業控制子系統等。從整體層面來說,linux系統都是由不同的檔案構成并運作的。
Docker鏡像的本質是一個分層檔案系統。而linux檔案系統由bootfs和rootfs兩部分組成(fs:file system的縮寫):
- bootfs:包含bootloader(引導加載程式)和kernel(核心)。bootloader主要是引導加載kernel
- rootfs:root檔案系統,包含的就是Linux系統中的/dev、/proc、/bin、/etc等标準目錄和檔案
我們經常接觸到的linux系統如ubuntu、RedHat、centos等系統,bootfs基本一樣,rootfs不同。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL4gDOhBTOlRjN4kzNyQmMhR2M3QTMmJTNyEzYlNmN5UzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
Docker鏡像原理
-
Docker鏡像是由特殊的檔案系統疊加而成的,其最低端使用了主機(主控端)的bootfs,其他應用是在其基礎上一層層往上疊加,提供給使用者的就是最頂層檔案提供的對接接口。
以下以tomcat應用進行講解:
我們想要運作tomcat服務,需要java可運作的環境(即jdk),jdk和tomcat又需要在linux系統上運作,是以鏡像如下圖:
docker鏡像建構Docker鏡像原理鏡像制作
底層使用主控端的bootfs,第二層是rootfs(root檔案系統,被稱base image,即基礎鏡像),由于tomcat服務是基于jdk開發的,是以需要在實際的tomcat服務之前,疊加jdk鏡像,jdk鏡像之後,再疊加真正要使用的tomcat鏡像(使用者使用tomcat提供的服務),是以如果我們本地安裝tomcat服務時,下載下傳的安裝包隻有幾十MB,但是tomcat鏡像卻有400多MB,就是因為實際的tomcat鏡像包含了其他鏡像,隻是對使用者來說,需要的是最頂層的tomcat服務而已,tomcat官網的安裝包安裝前需要我們自己去安裝jdk等内容,而docker鏡像是一步到位。
我們在拉取tomcat鏡像時,可以看到有多個Pull,就是因為要下載下傳多個鏡像(但給使用者看到的是最頂層的tomcat鏡像)
我們在tomcat鏡像生成的容器中,檢視jdk版本和linux版本,是可以查到對應的資訊的
我們也可以通過
docker inspect tomcat:latest
指令檢視該鏡像的具體分層資訊:
總結
- Docker鏡像時由特殊的檔案系統分層疊加而成
- Docker容器是基于主控端的bootfs運作,第2層是rootfs(基礎鏡像),然後根據需求往上疊加其他鏡像檔案。
- Docker鏡像使用了聯合檔案系統(Union File System)技術,該技術能夠基于基礎鏡像,将鏡像通過分層并繼承的方式制作成一個完整的、統一的鏡像,即一次同時加載多個檔案系統,但使用者隻能看到一個檔案系統(可以了解為:對使用者隐藏了頂層以下的鏡像檔案)。
鏡像制作
官方提供的鏡像有時候不能滿足日常使用,這個時候就需要制作符合自己個性化的鏡像,鏡像制作有2種方式:
- 容器轉為鏡像:拉取鏡像,根據鏡像生成了docker容器,然後在容器的基礎上進行修改,修改完成後,将容器轉成鏡像,然後分享給其他人。
- dockerfile建構:在建構檔案裡指定建構鏡像所需的指令和說明,然後通過docker bulid指令生成新的鏡像。
容器轉為鏡像
對于使用者來說,是沒有權限去修改鏡像檔案的(隻有隻讀權限),但是我們可以操作容器啊,鏡像啟動容器時,Docker會在最頂層加載一個讀寫檔案系統作為容器。
我們可以在容器内操作,然後根據容器生成鏡像:
docker commit 容器id或容器名稱 鏡像名稱:版本号
如果想要分享給其他人,可以将鏡像壓縮儲存(docker save)儲存到本地,然後将壓縮包分享給他人,他人可以通過裝載(docker load)壓縮包的方式安裝鏡像。
鏡像壓縮到本地:
docker save 鏡像名稱:版本号>路徑/xxx.tar
壓縮包安裝鏡像:
docker load<路徑/xxx.tar
以下以tomcat鏡像為例,想要修改tomcat預設打開的頁面:
Dockerfile建構鏡像
Dockerfile是一個文本檔案,包含了一條條的指令,在基于指定的鏡像上,一條指令建構一層,最終建構出一個新的鏡像。Dockerfile的關鍵字說明如下:
關鍵字 | 作用 | 備注 | 格式 |
---|---|---|---|
FROM | 指定父鏡像 | 指定基于哪個image開始建構 | 或 |
MAINTAINER | 作者或維護者資訊 | 标明這個dockerfile是誰寫的或維護的 | |
LABEL | 标簽 | 給鏡像添加中繼資料,以鍵值對的形式,可以了解類似注釋 | |
RUN | 制作鏡像時執行的指令 | 建構鏡像時運作的指令,預設是/bin/sh | 或 (相當于:RUN 可執行檔案 參數1 參數2 … 參數n) |
CMD | 容器啟動時執行的指令 | 運作容器時執行的shell環境。每個 Dockerfile 隻能有一條 CMD 指令。如果指定了多條指令,隻有最後一條會被執行。 | 有3種格式: 1.exec執行: 2./bin/sh中執行: 3.提供給 ENTRYPOINT 的預設參數: |
ENTRYPOINT | 入口 | 一般在制作一些執行就關閉的容器中會使用 | |
COPY | 複制檔案到鏡像中 | 建構的時候複制檔案到鏡像中 | (源路徑是主控端的路徑,目标路徑是容器的路徑) |
ADD | 添加檔案 | 建構時添加檔案到鏡像中(即将主控端的檔案添加到容器内),與COPY的差別是ADD會自動解壓 | (源路徑是主控端的路徑,目标路徑是容器的路徑) |
ENV | 環境變量 | 在建構鏡像時,設定環境變量,可以在啟動容器的時候,通過-e覆寫(即容器内也可以使用) | |
ARG | 建構參數 | 用于指定傳遞給建構運作時的變量(給dockerfile傳參),相當于建構鏡像時可以在外部為裡面傳參 | |
VOLUME | 定義外部可以挂載的匿名資料卷 | 在啟動容器時若忘記挂載資料卷,會自動挂載到匿名卷 | |
EXPOSE | 聲明容器的服務端口 | 僅僅聲明容器的服務端口(及提供服務的端口),幫助使用裡了解并使用該端口 | |
WORKDIR | 工作目錄 | 指定容器的開始工作目錄(若沒有時會自動建立)。設定之後,Dockerfile中其後的指令RUN、CMD、ENTRYPOINT、ADD、COPY等指令都會在該目錄下執行 | |
USER | 指定容器執行使用者 | 指定運作容器時的使用者名或ID執行使用者 | |
dockerfile的注釋符号是
#
通過dockerfile建構鏡像指令格式為:
docker build -f dockerfile檔案路徑 -t 鏡像名稱:版本
示例1
以tomcat鏡像為例,想要修改tomcat預設打開的頁面:
步驟1:編輯dockerfile檔案(如tomcat_dockerfile檔案):
父鏡像tomcat:jre17-temurin的資訊我們可以在docker hub官網
選擇某個版本,點選之後,跳轉到的頁面會展示類似dockerfile檔案内容的資訊,我們可以看到,tomcat設定的工作目錄WORKDIR是/usr/local/tomcat,申明的服務端口是8080
步驟2:生成鏡像(docker build)
注:關于docker build指令末尾的
.
,本人還是沒搞懂,可以參考其他大神的文章:Docker學習:Docker核心指令 | 常用指令 | Docker build . 點的含義 | docker build和docker commit關系 | docker rm 與sleep用法
步驟3:驗證鏡像
通路伺服器的8080端口,顯示了自己編輯的内容
如果其他人也想使用該tomcat,你可以将鏡像打包(docker save)或直接将dockerfile檔案發送過去,dockerfile檔案建構鏡像的時候,還有一個友善的地方就是docker build的dockerfile可以是網際網路可通路的檔案,可以及時更新,友善通路。
使用網際網路url的dockerfile建構鏡像的指令是:
docker build url
注意:url不需要定位到具體的檔案,要定位到檔案所在路徑,然後該路徑下需要有檔案名稱是 Dockerfile
的檔案。
示例:
docker build github.com/creack/docker-firefox
示例2
題目:自定義centos:7鏡像,要求:預設登入路徑為/usr;可以使用vim
官網提供的centos:7預設登入路徑是根目錄,無法使用vim
預設登入路徑可以根據WORKDIR來設定,vim無法使用,是因為沒有安裝該應用(預設安裝了vi),如果需要使用,我們就需要安裝vim,是以dockerfile的RUN需要做2件事情:設定WORKDIR、安裝vim,dockerfile檔案内容如下:
# 基于centos:7的鏡像
FROM centos:7
# 維護者資訊
MAINTAINER wenxiaoba [email protected]
# 設定初始工作目錄
WORKDIR /usr
# 執行centos安裝vim指令
RUN yum -y install vim
# 定義容器啟動執行的指令
CMD /bin/bash
通過docker build生成鏡像
我們根據生成的鏡像vim_centos:7v去建立并啟動容器,驗證是否符合預期