摘要:本文已獲得原作者授權(quán)。在構(gòu)建鏡像的過程中會(huì)緩存一系列中間鏡像。鏡像時(shí),會(huì)順序執(zhí)行中的指令,并同時(shí)比較當(dāng)前指令和其基礎(chǔ)鏡像的所有子鏡像,若發(fā)現(xiàn)有一個(gè)子鏡像也是由相同的指令生成,則命中緩存,同時(shí)可以直接使用該子鏡像而避免再去重新生成了。
本文已獲得原作者 CodeSheep 授權(quán)。
概述Dockerfile 是專門用來進(jìn)行自動(dòng)化構(gòu)建鏡像的編排文件(就像 Jenkins 2.0時(shí)代的 Jenkinsfile 是對(duì) Jenkins 的 Job 和 Stage 的編排一樣),我們可以通過?docker build命令來自動(dòng)化地從 Dockerfile 所描述的步驟來構(gòu)建自定義的 Docker鏡像,這比我們?nèi)ッ钚幸粭l條指令執(zhí)行的方式構(gòu)建高效得多。
另一方面,由于 Dockerfile 提供了統(tǒng)一的配置語法,因此通過這樣一份配置文件,我們可以在各種不同的平臺(tái)上進(jìn)行分發(fā),需要時(shí)通過 Dockerfile 構(gòu)建一下就能得到所需的鏡像。
最后一個(gè)必須提的優(yōu)點(diǎn)便是:Dockerfile 通過與鏡像配合使用,使得 Docker 鏡像構(gòu)建之時(shí)可以充分利用?“鏡像的緩存功能”,因此也提效不少!
然而寫 Dockerfile 也像寫代碼一樣,一份精心設(shè)計(jì)、Clean Code 的 Dockerfile 能在提高可讀性的同時(shí)也大大提升 Docker 的使用效率
因此下面就結(jié)合實(shí)踐來講幾條 Dockerfile 的實(shí)踐心得!
基礎(chǔ)鏡像的選擇有講究在我的文章?《利用K8S技術(shù)棧打造個(gè)人私有云(連載之:基礎(chǔ)鏡像制作與實(shí)驗(yàn))》中,我們是基于某個(gè) Linux 基礎(chǔ)鏡像作為底包,然后打包進(jìn)我需要的功能從而形成自己的鏡像。
這里選擇基礎(chǔ)鏡像時(shí)是有講究的:
一是應(yīng)當(dāng)盡量選擇官方鏡像庫里的基礎(chǔ)鏡像;
二是應(yīng)當(dāng)選擇輕量級(jí)的鏡像做底包
就典型的 Linux 基礎(chǔ)鏡像來說,大小關(guān)系如下:
Ubuntu > CentOS > Debian
因此相比 Ubuntu,其實(shí)更推薦使用最輕量級(jí)的 Debian 鏡像,而且它也是一個(gè)完整的 Release 版,可以放心使用
多使用標(biāo)簽 Tag 有好處構(gòu)建鏡像時(shí),給其打上一個(gè)易讀的鏡像標(biāo)簽有助于幫助了解鏡像的功能,比如:
docker build -t=“centos:wordpress" .
例如上面的這個(gè) centos 鏡像是用來做 wordpress 用的,所以已經(jīng)集成了 wordpress 功能,這一看就很清晰明了
再者,我們也應(yīng)該在 Dockerfile 的 FROM 指令中明確指明標(biāo)簽 Tag,不要再讓 Docker daemon 去猜,如
FROM debian:codesheep充分利用鏡像緩存
什么是鏡像緩存?
由 Dockerfile 最終構(gòu)建出來的鏡像是在基礎(chǔ)鏡像之上一層層疊加而得,因此在過程中會(huì)產(chǎn)生一個(gè)個(gè)新的?鏡像層。Docker daemon 在構(gòu)建鏡像的過程中會(huì)緩存一系列中間鏡像。
docker build 鏡像時(shí),會(huì)順序執(zhí)行 Dockerfile 中的指令,并同時(shí)比較當(dāng)前指令和其基礎(chǔ)鏡像的所有子鏡像,若發(fā)現(xiàn)有一個(gè)子鏡像也是由相同的指令生成,則?命中緩存,同時(shí)可以直接使用該子鏡像而避免再去重新生成了。
為了有效地使用緩存,需要保證 Dockerfile 中指令的?連續(xù)一致,盡量將相同指令的部分放在前面,而將有差異性的指令放在后面
舉例:假如我想用 Dockerfile 方式 基于最基本的 CentOS 鏡像來構(gòu)建兩個(gè)不同的鏡像時(shí),兩個(gè) Dockerfile 的開頭可以相同:
FROM centos:latest # 下面安裝兩個(gè)常用的工具 RUN yum install -y net-tools.x86_64 RUN yum install lrzsz ######## 上面為兩個(gè) Dockerfile 文件中相同的部分###### ######## 下面為兩個(gè) Dockerfile 文件中不同的部分###### ......ADD 與 COPY 指令的正確使用
雖然兩者都可以添加文件到鏡像中,但在一般用法中,還是推薦以 COPY 指令為首選,原因在于 ADD 指令并沒有 COPY 指令來的純粹,ADD 會(huì)添加一些額外功能,典型的如下 ADD 一個(gè)壓縮包時(shí),其不僅會(huì)復(fù)制,還會(huì)自動(dòng)解壓,而有時(shí)我們并不需要這種額外的功能。
ADD codesheep.tar.gz /path
除此之外,在需要添加多個(gè)文件到鏡像中的時(shí)候,不要一次性集中添加,而是選擇?按需在必要時(shí)?逐個(gè)添加即可,因?yàn)檫@樣有利于利用鏡像緩存
盡量使用docker volume雖然上面一條原則說推薦通過 COPY 命令來向鏡像中添加多個(gè)文件,然而實(shí)際情況中,若文件?大而多的時(shí)候還是應(yīng)該優(yōu)先用?docker -v命令來掛載文件,而不是依賴于 ADD 或者 COPY
CMD 和 ENTRYPOINT 指令 的正確理解使用Dockerfile 制作鏡像時(shí),會(huì)組合 CMD 和 ENTRYPOINT 指令來作為容器運(yùn)行時(shí)的默認(rèn)命令:即?CMD + ENTRYPOINT。此時(shí)的默認(rèn)命令組成中:
ENTRYPOINT 指令部分固定不變,容器運(yùn)行時(shí)是無法修改的
而 CMD 部分的指令也可以改變,表現(xiàn)在運(yùn)行容器時(shí),docker run命令中提供的參數(shù)會(huì)覆蓋CMD的指令內(nèi)容。
舉個(gè)例子:
FROM debian:latest MAINTAINER [email protected] ENTRYPOINT [ "ls", "-l"] CMD ["-a"]
若以默認(rèn)命令運(yùn)行容器,可以發(fā)現(xiàn),執(zhí)行的是?ls -a -l命令:
若?docker run中增加參數(shù)?-t
docker run -it --rm --name test debian:codesheep -t
也可以發(fā)現(xiàn)執(zhí)行的是?ls -l -t,即 Dockerfile 中的 CMD 原參數(shù)被覆蓋了:
因此推薦的使用方式是:
使用 exec 格式的 ENTRYPOINT 指令 設(shè)置固定的默認(rèn)命令和參數(shù)
使用 CMD 指令 設(shè)置可變的參數(shù)
不推薦在 Dockerfile 中 做端口映射Dockerfile 可以通過 EXPOSE 指令 將容器端口映射到主機(jī)端口上,但這樣會(huì)導(dǎo)致鏡像在一臺(tái)主機(jī)上僅能啟動(dòng)一個(gè)容器!
所以應(yīng)該在?docker run命令中來用?-p參數(shù)來指定端口映射,而不要將該工作置于 Dockerfile 之中:
#盡量避免這種方式 EXPOSE 8080:8899 #選擇僅僅暴露端口即可,端口映射的任務(wù)交給 docker run 去做 EXPOSE 8080使用 Dockerfile 來共享鏡像
推薦通過共享 Dockerfile 的方式來共享鏡像,優(yōu)點(diǎn)多多:
通過 Dockerfile 構(gòu)建的鏡像用戶可以清楚地看到構(gòu)建的過程
就像 Jenkinsfile 可以加入版本控制從而追蹤C(jī)I系統(tǒng)的變遷和步驟的回滾一樣,Dockerfile 作為一個(gè)編排文件同樣可以入庫做版本控制,這樣也可以回溯
使用 Dockerfile 構(gòu)建的鏡像具有確定性,沒有玄學(xué)的成分
后記作者更多的原創(chuàng)文章在此,歡迎觀賞
作者:CodeSheep
鏈接:https://juejin.im/post/5b4615b0f265...
來源:掘金
更多相關(guān)文章:
使用 Dockerfile 定制鏡像
用 Dockerfile 打造你的自動(dòng)化構(gòu)建工具
Docker 底層技術(shù)
如果你還想了解更多,想和技術(shù)同僚分享切磋,可掃下方二維碼,回復(fù) yw,加入掘金運(yùn)維技術(shù)交流群
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/8063.html
摘要:在構(gòu)建鏡像的過程中會(huì)緩存一系列中間鏡像。鏡像時(shí),會(huì)順序執(zhí)行中的指令,并同時(shí)比較當(dāng)前指令和其基礎(chǔ)鏡像的所有子鏡像,若發(fā)現(xiàn)有一個(gè)子鏡像也是由相同的指令生成,則命中緩存,同時(shí)可以直接使用該子鏡像而避免再去重新生成了。 showImg(https://segmentfault.com/img/remote/1460000015606308?w=2000&h=1428); 概述 Docker...
摘要:微服務(wù)的基本思想在于考慮圍繞著業(yè)務(wù)領(lǐng)域組件來創(chuàng)建應(yīng)用,這些應(yīng)用可獨(dú)立地進(jìn)行開發(fā)管理和加速。在分散的組件中使用微服務(wù)云架構(gòu)和平臺(tái),使部署管理和服務(wù)功能交付變得更加簡(jiǎn)單。 showImg(https://segmentfault.com/img/remote/1460000014332184); 概述 當(dāng)下web服務(wù)端開發(fā)中最火的名詞中絕對(duì)有微服務(wù)的一席之地,其也成為當(dāng)下互聯(lián)網(wǎng)后端服務(wù)架...
摘要:概述在我之前的應(yīng)用監(jiān)控實(shí)戰(zhàn)一文中,講述了如何利用版本來可視化地監(jiān)控應(yīng)用。接下來我們就來創(chuàng)建一個(gè)待監(jiān)控的示例。 showImg(https://segmentfault.com/img/remote/1460000015671446); 概述 在我之前的 《Spring Boot應(yīng)用監(jiān)控實(shí)戰(zhàn)》 一文中,講述了如何利用 Spring Boot Admin 1.5.X 版本來可視化地監(jiān)控 ...
摘要:概述進(jìn)行的開發(fā)過程中,我們很多時(shí)候經(jīng)常需要重啟服務(wù)器才能保證修改的源代碼文件或者一些諸如的配置文件以及一些靜態(tài)文件生效,這樣耗時(shí)又低效。 showImg(https://segmentfault.com/img/remote/1460000015363888); 概述 進(jìn)行SpringBoot的Web開發(fā)過程中,我們很多時(shí)候經(jīng)常需要重啟Web服務(wù)器才能保證修改的 源代碼文件、或者一些...
摘要:但考慮到實(shí)際的情形中,我們的服務(wù)器一般是另外部署好了的,有專門的維護(hù)方式。此時(shí)我們需要?jiǎng)冸x掉應(yīng)用內(nèi)置的服務(wù)器,進(jìn)而將應(yīng)用發(fā)布并部署到外置的容器之中,本文就實(shí)踐一下這個(gè)。 showImg(https://segmentfault.com/img/remote/1460000015173574); 0x01. 概述 SpringBoot平時(shí)我們用的爽歪歪,爽到它自己連Tomcat都自集成...
閱讀 1220·2023-04-25 20:31
閱讀 3730·2021-10-14 09:42
閱讀 1502·2021-09-22 16:06
閱讀 2684·2021-09-10 10:50
閱讀 3536·2021-09-07 10:19
閱讀 1782·2019-08-30 15:53
閱讀 1180·2019-08-29 15:13
閱讀 2826·2019-08-29 13:20