鏡像的內部機制是什么
鏡像是一個打包檔案,里面包含了應用程式和依賴的環境,例如:檔案系統、環境變數和配置引數等,
環境變數和配置引數比較簡單一個manifest清單就可以管理,真正麻煩的是檔案系統,為了保證容器運行環境的一致性,鏡像必須把應用程式所在作業系統的根目錄,也就是rootfs都包含進來,
容器是共享宿主機內核,檔案系統不包含系統內核,假如有一千個鏡像基于Ubuntu系統打包,那么這些鏡像里就會重復一千次Ubuntu目錄,對于磁盤存盤、網路傳輸都是很大的浪費,
把重復的部分抽取出來存放到一份根目錄檔案,然后讓其他鏡像以某種方式共享這部分資料,這個思路正是容器的分層,Layer,
一個鏡像是由許多的鏡像層組成的,每層都是只讀不可修改的一組檔案,相同的層可以在鏡像之間共享,多個層像搭積木一樣推疊起來,再使用一種“Union FS聯合檔案系統”的技術把它們合并在一起,就形成了容器最終看到的檔案系統,
docker inspect可以查看鏡像分層資訊,比如nginx:alpine鏡像
docker inspect nginx:alpine
在執行docker pull 或 docker rmi命令時輸出的資訊其實就是鏡像里的各個Layer,Docker會檢查是否有重復的層,如果本地已經存在就不會重復下載,如果層被其他鏡像共享就不會被洗掉,這樣就可以節約磁盤和網路成本,
以上就是鏡像的內部結構和基本原理,
Dockerfile是什么
Dockerfile如果是施工圖紙,鏡像就是由旋工圖紙建造的房子,而容器就是住進人的房子,
Dockerfile就是一個純文本檔案,里面記錄了構建指令,比如選擇基礎鏡像、拷貝檔案、運行腳本,每個指令都會生成一個Layer,Docker順序執行這個檔案里的所有指令,最終生成一個新的鏡像檔案,
最簡單的Dockerfile
# filename:Dockerfile.busybox
FROM busybox
CMD echo "hello world"
第一條指令:選擇基礎鏡像
第二條指令:啟動容器時默認運行的命令
根據圖紙建造房子是由施工團隊完成的,這里就是docker build
docker build -f Dockerfile.busybox .
查看、運行鏡像
docker images
docker inspect image_id
docker run image_id
怎樣撰寫正確、高效的Dockerfile
選擇鏡像 - FROM指令
選擇基礎鏡像非常關鍵,如果關注鏡像的安全和大小一般選擇Alpine,如果關注應用運行的穩定性一般選擇CentOS、Ubuntu、Debian,
FROM alpine:3.15
FROM ubunt:bionic
復制檔案 - COPY指令
如果要將原始碼、組態檔打包進鏡像,就需要COPY指令,注意復制的源檔案路徑必須是構建背景關系里的路徑,也就是用相對路徑,
# 把構建背景關系里的a.txt拷貝到鏡像的/tmp目錄
COPY ./a.txt /tmp/a.txt
# 下面方式不正確,不能用構建背景關系之外的檔案
COPY /etc/hosts /tmp
執行命令 - RUN指令
執行任意shell命令,就需要RUN指令,Dockerfile里一條指令只能是一行,所以RUN指令每行末尾用\續行符,命令之間用&&連接,這樣就能保證在邏輯上是一行,減少Layer,
RUN apt-get update \
&& apt-get install -y \
build-essential \
curl \
make \
unzip \
&& cd /tmp \
&& curl -fSL xxx.tar.gz -o xxx.tar.gz\
&& tar xzf xxx.tar.gz \
&& cd xxx \
&& ./config \
&& make \
&& make clean
這樣寫一是不美觀,二是一旦寫錯每次除錯都要重新構建很麻煩,可以采用一種變通的技巧:把這些shell命令集中到一個腳本檔案中,用COPY命令復制進去,再用RUN來執行,
COPY setup.sh /tmp/ # 拷貝腳本到/tmp目錄
RUN cd /tmp && chmod +x setup.sh \ # 添加執行權限
&& ./setup.sh && rm setup.sh # 運行腳本然后再洗掉
定義變數 - ARG與ENV指令
ARG和ENV都是定義變數,區別是ARG定義的變數只能在鏡像構建程序中可見,ENV創建的變數不僅能在構建鏡像程序中使用,也能在容器運行時以環境變數的形式被應用程式使用
開放埠 - EXPOSE指令
它用來宣告容器對外服務的埠號,對基于Node.js、Tomcat、Nginx、Go等開發的微服務系統來說非常有用,
# 默認是TCP協議
EXPOSE 443
# 指定UDP協議
EXOPSE 53/udp
docker build是怎么作業的
排除檔案 - .dockerignore
一個機制,docker是個客戶端,真正的鏡像構建作業是由Docker daemon來完成的,所以Docker會把構建背景關系的目錄打包上傳,這樣服務器才能獲取本地檔案,
如果構建背景關系中一些檔案不需要打包到鏡像,docker也會全部打包上傳,效率很低,
可以在構建背景關系目錄中創建一個.dockerignore檔案,將那些不需要的檔案寫入
# docker ignore
*.swp
*.sh
指定檔案
用-f來指定Dockerfile檔案,如果不指定默認檔案名為Dockerfile
docker build -f xxx
指定標簽
用:分割名字和標簽,如果不指定標簽默認為latest
小結
1、容器鏡像是由多個只讀的Layer構成的,同一個Layer可以被不同的鏡像共享,減少了存盤和傳輸成本
2、Dockerfile中每個指令都會生成一個Layer
3、Dockerfile第一條指令必須是FROM
4、docker build使用-f來指定Dockerfile,不指定默認國為當前目錄下的以Dockerfile為名的檔案
5、盡量不要在構建背景關系中存入多余的檔案
6、盡量使用-t引數,為鏡像起一個有意義的名字,方便管理
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/518515.html
標籤:其他
下一篇:[Leetcode62]不同路徑
