摘要:在構建鏡像的過程中會緩存一系列中間鏡像。鏡像時,會順序執行中的指令,并同時比較當前指令和其基礎鏡像的所有子鏡像,若發現有一個子鏡像也是由相同的指令生成,則命中緩存,同時可以直接使用該子鏡像而避免再去重新生成了。
Dockerfile 是專門用來進行自動化構建鏡像的編排文件(就像Jenkins 2.0時代的Jenkinsfile是對Jenkins的Job和Stage的編排一樣),我們可以通過 docker build 命令來自動化地從 Dockerfile 所描述的步驟來構建自定義的 Docker鏡像,這比我們去命令行一條條指令執行的方式構建高效得多。
另一方面,由于 Dockerfile 提供了統一的配置語法,因此通過這樣一份配置文件,我們可以在各種不同的平臺上進行分發,需要時通過 Dockerfile 構建一下就能得到所需的鏡像。
最后一個必須提的優點便是:Dockerfile 通過與鏡像配合使用,使得 Docker鏡像構建之時可以充分利用 “鏡像的緩存功能”,因此也提效不少!
然而寫 Dockerfile 也像寫代碼一樣,一份精心設計、Clean Code 的 Dockerfile 能在提高可讀性的同時也大大提升Docker的使用效率
因此下面就結合實踐來講幾條 Dockerfile 的實踐心得!
注: 本文首發于 My 公眾號 CodeSheep ,可 長按 或 掃描 下面的 小心心 來訂閱 ↓ ↓ ↓
在我的文章 《利用K8S技術棧打造個人私有云(連載之:基礎鏡像制作與實驗)》 中,我們是基于某個Linux基礎鏡像作為底包,然后打包進我需要的功能從而形成自己的鏡像。
這里選擇基礎鏡像時是有講究的:
一是 應當盡量選擇官方鏡像庫里的基礎鏡像;
二是 應當選擇輕量級的鏡像做底包
就典型的Linux基礎鏡像來說,大小關系如下:
Ubuntu > CentOS > Debian
因此相比 Ubuntu,其實更推薦使用最輕量級的 Debian鏡像,而且它也是一個完整的Release版,可以放心使用
構建鏡像時,給其打上一個易讀的鏡像標簽有助于幫助了解鏡像的功能,比如:
docker build -t=“centos:wordpress" .
例如上面的這個centos鏡像是用來做wordpress用的,所以已經集成了wordpress功能,這一看就很清晰明了
再者,我們也應該在 Dockerfile 的 FROM 指令中明確指明標簽 Tag,不要再讓 Docker daemon 去猜,如
FROM debian:codesheep
什么是鏡像緩存?
由 Dockerfile 最終構建出來的鏡像是在基礎鏡像之上一層層疊加而得,因此在過程中會產生一個個新的 鏡像層。Docker daemon 在構建鏡像的過程中會緩存一系列中間鏡像。
docker build鏡像時,會順序執行Dockerfile中的指令,并同時比較當前指令和其基礎鏡像的所有子鏡像,若發現有一個子鏡像也是由相同的指令生成,則 命中緩存,同時可以直接使用該子鏡像而避免再去重新生成了。
為了有效地使用緩存,需要保證 Dockerfile 中指令的 連續一致,盡量將相同指令的部分放在前面,而將有差異性的指令放在后面
舉例:假如我想用 Dockerfile方式 基于最基本的 CentOS 鏡像來構建兩個不同的鏡像時,兩個Dockerfile的開頭可以相同:
FROM centos:latest # 下面安裝兩個常用的工具 RUN yum install -y net-tools.x86_64 RUN yum install lrzsz ######## 上面為兩個Dockerfile文件中相同的部分###### ######## 下面為兩個Dockerfile文件中不同的部分###### ......
雖然兩者都可以添加文件到鏡像中,但在一般用法中,還是推薦以COPY指令為首選,原因在于ADD指令并沒有COPY指令來的純粹,ADD會添加一些額外功能,典型的如下 ADD 一個壓縮包時,其不僅會復制,還會自動解壓,而有時我們并不需要這種額外的功能。
ADD codesheep.tar.gz /path
除此之外,在需要添加多個文件到鏡像中的時候,不要一次性集中添加,而是選擇 按需 在必要時 逐個 添加即可,因為這樣有利于利用鏡像緩存
雖然上面一條原則說推薦通過 COPY 命令來向鏡像中添加多個文件,然而實際情況中,若文件 大而多 的時候還是應該優先用 docker -v 命令來掛載文件,而不是依賴于 ADD 或者 COPY
最后必須說一下,這里的“盡量”是有個度的,適度把握才行。
Dockerfile 制作鏡像時,會組合 CMD 和 ENTRYPOINT 指令來作為容器運行時的默認命令:即 CMD + ENTRYPOINT。此時的默認命令組成中:
ENTRYPOINT 指令部分“一般”固定不變,容器運行時不修改
而 CMD 部分的指令也可以改變,表現在運行容器時,docker run 命令中提供的參數會覆蓋CMD的指令內容。
舉個例子:
FROM debian:latest MAINTAINER codesheep@163.com ENTRYPOINT [ "ls", "-l"] CMD ["-a"]
若以默認命令運行容器,可以發現,執行的是 ls -a -l 命令:
若 docker run 中增加參數 -t
docker run -it --rm --name test debian:codesheep -t
也可以發現執行的是 ls -l -t,即 Dockerfile 中的 CMD 原參數被覆蓋了:
因此推薦的使用方式是:
使用exec格式的 ENTRYPOINT指令 設置固定的默認命令和參數
使用 CMD指令 設置可變的參數
Dockerfile 可以通過 EXPOSE指令 將容器端口映射到主機端口上,但這樣會導致鏡像在一臺主機上僅能啟動一個容器!
所以應該在 docker run 命令中來用 -p 參數來指定端口映射,而不要將該工作置于 Dockerfile 之中:
#盡量避免這種方式 EXPOSE 8080:8899 #僅僅暴露端口 EXPOSE 8080
推薦通過共享 Dockerfile 的方式來共享鏡像,優點多多:
通過 Dockerfile 構建的鏡像用戶可以清楚地看到構建的過程
就像 Jenkinsfile 可以加入版本控制從而追蹤CI系統的變遷和步驟的回滾一樣,Dockerfile 作為一個編排文件同樣可以入庫做版本控制,這樣也可以回溯
使用 Dockerfile 構建的鏡像具有確定性,沒有玄學的成分
作者更多的原創文章在此,歡迎觀賞
如果有興趣,也可以抽點時間看看作者一些關于容器化、微服務化方面的文章:
從一份配置清單詳解Nginx服務器配置
利用K8S技術棧打造個人私有云 連載文章
Docker容器可視化監控中心搭建
利用ELK搭建Docker容器化應用日志中心
利用TICK搭建Docker容器可視化監控中心
RPC框架實踐之:Apache Thrift
RPC框架實踐之:Google gRPC
微服務調用鏈追蹤中心搭建
Docker容器跨主機通信
Docker Swarm集群初探
作者相關的SpringBt實踐文章在此:
SpringBoot應用部署于外置Tomcat容器
ElasticSearch搜索引擎在SpringBt中的實踐
初探Kotlin+SpringBoot聯合編程
Spring Boot日志框架實踐
SpringBoot優雅編碼之:Lombok加持
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/27384.html
摘要:本文已獲得原作者授權。在構建鏡像的過程中會緩存一系列中間鏡像。鏡像時,會順序執行中的指令,并同時比較當前指令和其基礎鏡像的所有子鏡像,若發現有一個子鏡像也是由相同的指令生成,則命中緩存,同時可以直接使用該子鏡像而避免再去重新生成了。 本文已獲得原作者 CodeSheep 授權。 概述 Dockerfile 是專門用來進行自動化構建鏡像的編排文件(就像 Jenkins 2.0時代的 J...
摘要:微服務的基本思想在于考慮圍繞著業務領域組件來創建應用,這些應用可獨立地進行開發管理和加速。在分散的組件中使用微服務云架構和平臺,使部署管理和服務功能交付變得更加簡單。 showImg(https://segmentfault.com/img/remote/1460000014332184); 概述 當下web服務端開發中最火的名詞中絕對有微服務的一席之地,其也成為當下互聯網后端服務架...
摘要:概述在我之前的應用監控實戰一文中,講述了如何利用版本來可視化地監控應用。接下來我們就來創建一個待監控的示例。 showImg(https://segmentfault.com/img/remote/1460000015671446); 概述 在我之前的 《Spring Boot應用監控實戰》 一文中,講述了如何利用 Spring Boot Admin 1.5.X 版本來可視化地監控 ...
摘要:概述進行的開發過程中,我們很多時候經常需要重啟服務器才能保證修改的源代碼文件或者一些諸如的配置文件以及一些靜態文件生效,這樣耗時又低效。 showImg(https://segmentfault.com/img/remote/1460000015363888); 概述 進行SpringBoot的Web開發過程中,我們很多時候經常需要重啟Web服務器才能保證修改的 源代碼文件、或者一些...
摘要:但考慮到實際的情形中,我們的服務器一般是另外部署好了的,有專門的維護方式。此時我們需要剝離掉應用內置的服務器,進而將應用發布并部署到外置的容器之中,本文就實踐一下這個。 showImg(https://segmentfault.com/img/remote/1460000015173574); 0x01. 概述 SpringBoot平時我們用的爽歪歪,爽到它自己連Tomcat都自集成...
閱讀 3061·2021-11-23 09:51
閱讀 1040·2021-09-02 15:21
閱讀 3005·2019-08-30 13:56
閱讀 1829·2019-08-29 14:12
閱讀 707·2019-08-29 13:53
閱讀 1664·2019-08-29 11:32
閱讀 1325·2019-08-29 11:25
閱讀 1492·2019-08-28 17:51