編寫高效Dockerfile的幾條準(zhǔn)則

Profile

概述

  • Dockerfile 是專門用來(lái)進(jìn)行自動(dòng)化構(gòu)建鏡像的編排文件(就像Jenkins 2.0時(shí)代的Jenkinsfile是對(duì)Jenkins的Job和Stage的編排一樣),我們可以通過(guò) docker build 命令來(lái)自動(dòng)化地從 Dockerfile 所描述的步驟來(lái)構(gòu)建自定義的 Docker鏡像蒙畴,這比我們?nèi)ッ钚幸粭l條指令執(zhí)行的方式構(gòu)建高效得多沮尿。

  • 另一方面,由于 Dockerfile 提供了統(tǒng)一的配置語(yǔ)法宠能,因此通過(guò)這樣一份配置文件蚯斯,我們可以在各種不同的平臺(tái)上進(jìn)行分發(fā),需要時(shí)通過(guò) Dockerfile 構(gòu)建一下就能得到所需的鏡像昔搂。

  • 最后一個(gè)必須提的優(yōu)點(diǎn)便是:Dockerfile 通過(guò)與鏡像配合使用,使得 Docker鏡像構(gòu)建之時(shí)可以充分利用 “鏡像的緩存功能”,因此也提效不少缀雳!

然而寫 Dockerfile 也像寫代碼一樣横辆,一份精心設(shè)計(jì)、Clean Code 的 Dockerfile 能在提高可讀性的同時(shí)也大大提升Docker的使用效率

因此下面就結(jié)合實(shí)踐來(lái)講幾條 Dockerfile 的實(shí)踐心得逛裤!

注: 本文首發(fā)于 My 公眾號(hào) CodeSheep ,可 長(zhǎng)按掃描 下面的 小心心 來(lái)訂閱 ↓ ↓ ↓

CodeSheep · 程序羊


基礎(chǔ)鏡像的選擇有講究

在我的文章 《利用K8S技術(shù)棧打造個(gè)人私有云(連載之:基礎(chǔ)鏡像制作與實(shí)驗(yàn))》 中猴抹,我們是基于某個(gè)Linux基礎(chǔ)鏡像作為底包带族,然后打包進(jìn)我需要的功能從而形成自己的鏡像。

這里選擇基礎(chǔ)鏡像時(shí)是有講究的:

  • 一是 應(yīng)當(dāng)盡量選擇官方鏡像庫(kù)里的基礎(chǔ)鏡像蟀给;
  • 二是 應(yīng)當(dāng)選擇輕量級(jí)的鏡像做底包

就典型的Linux基礎(chǔ)鏡像來(lái)說(shuō)蝙砌,大小關(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鏡像是用來(lái)做wordpress用的肚邢,所以已經(jīng)集成了wordpress功能,這一看就很清晰明了

  • 再者拭卿,我們也應(yīng)該在 Dockerfile 的 FROM 指令中明確指明標(biāo)簽 Tag骡湖,不要再讓 Docker daemon 去猜贱纠,如
FROM debian:codesheep


充分利用鏡像緩存

什么是鏡像緩存?

由 Dockerfile 最終構(gòu)建出來(lái)的鏡像是在基礎(chǔ)鏡像之上一層層疊加而得响蕴,因此在過(guò)程中會(huì)產(chǎn)生一個(gè)個(gè)新的 鏡像層并巍。Docker daemon 在構(gòu)建鏡像的過(guò)程中會(huì)緩存一系列中間鏡像。

docker build鏡像時(shí)换途,會(huì)順序執(zhí)行Dockerfile中的指令懊渡,并同時(shí)比較當(dāng)前指令和其基礎(chǔ)鏡像的所有子鏡像,若發(fā)現(xiàn)有一個(gè)子鏡像也是由相同的指令生成军拟,則 命中緩存剃执,同時(shí)可以直接使用該子鏡像而避免再去重新生成了。

為了有效地使用緩存懈息,需要保證 Dockerfile 中指令的 連續(xù)一致肾档,盡量將相同指令的部分放在前面,而將有差異性的指令放在后面

舉例:假如我想用 Dockerfile方式 基于最基本的 CentOS 鏡像來(lái)構(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指令來(lái)的純粹遣耍,ADD會(huì)添加一些額外功能,典型的如下 ADD 一個(gè)壓縮包時(shí)炮车,其不僅會(huì)復(fù)制舵变,還會(huì)自動(dòng)解壓,而有時(shí)我們并不需要這種額外的功能瘦穆。

ADD codesheep.tar.gz /path

除此之外纪隙,在需要添加多個(gè)文件到鏡像中的時(shí)候,不要一次性集中添加扛或,而是選擇 按需 在必要時(shí) 逐個(gè) 添加即可绵咱,因?yàn)檫@樣有利于利用鏡像緩存



盡量使用docker volume

雖然上面一條原則說(shuō)推薦通過(guò) COPY 命令來(lái)向鏡像中添加多個(gè)文件,然而實(shí)際情況中熙兔,若文件 大而多 的時(shí)候還是應(yīng)該優(yōu)先用 docker -v 命令來(lái)掛載文件悲伶,而不是依賴于 ADD 或者 COPY

最后必須說(shuō)一下,這里的“盡量”是有個(gè)度的黔姜,適度把握才行拢切。



CMD 和 ENTRYPOINT指令 的理解使用

Dockerfile 制作鏡像時(shí)蒂萎,會(huì)組合 CMD 和 ENTRYPOINT 指令來(lái)作為容器運(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 codesheep@163.com

ENTRYPOINT [ "ls", "-l"]
CMD ["-a"]

若以默認(rèn)命令運(yùn)行容器,可以發(fā)現(xiàn)毙芜,執(zhí)行的是 ls -a -l 命令:

ls -l -a

docker run 中增加參數(shù) -t

docker run -it --rm --name test debian:codesheep -t

也可以發(fā)現(xiàn)執(zhí)行的是 ls -l -t忽媒,即 Dockerfile 中的 CMD 原參數(shù)被覆蓋了:

ls -l -t

因此推薦的使用方式是:

  • 使用exec格式的 ENTRYPOINT指令 設(shè)置固定的默認(rèn)命令和參數(shù)

  • 使用 CMD指令 設(shè)置可變的參數(shù)



不推薦在 Dockerfile中 做端口映射

Dockerfile 可以通過(guò) EXPOSE指令 將容器端口映射到主機(jī)端口上,但這樣會(huì)導(dǎo)致鏡像在一臺(tái)主機(jī)上僅能啟動(dòng)一個(gè)容器腋粥!

所以應(yīng)該在 docker run 命令中來(lái)用 -p 參數(shù)來(lái)指定端口映射晦雨,而不要將該工作置于 Dockerfile 之中:

#盡量避免這種方式
EXPOSE 8080:8899

#僅僅暴露端口
EXPOSE 8080


使用 Dockerfile 來(lái)共享鏡像

推薦通過(guò)共享 Dockerfile 的方式來(lái)共享鏡像,優(yōu)點(diǎn)多多:

  • 通過(guò) Dockerfile 構(gòu)建的鏡像用戶可以清楚地看到構(gòu)建的過(guò)程

  • 就像 Jenkinsfile 可以加入版本控制從而追蹤C(jī)I系統(tǒng)的變遷和步驟的回滾一樣隘冲,Dockerfile 作為一個(gè)編排文件同樣可以入庫(kù)做版本控制闹瞧,這樣也可以回溯

  • 使用 Dockerfile 構(gòu)建的鏡像具有確定性,沒有玄學(xué)的成分



后記

如果有興趣奥邮,也可以抽點(diǎn)時(shí)間看看作者一些關(guān)于容器化、微服務(wù)化方面的文章:

作者相關(guān)的SpringBt實(shí)踐文章在此:



CodeSheep · 程序羊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末罗珍,一起剝皮案震驚了整個(gè)濱河市洽腺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌覆旱,老刑警劉巖蘸朋,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異扣唱,居然都是意外死亡度液,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門画舌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)堕担,“玉大人,你說(shuō)我怎么就攤上這事曲聂∨海” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵朋腋,是天一觀的道長(zhǎng)齐疙。 經(jīng)常有香客問我,道長(zhǎng)旭咽,這世上最難降的妖魔是什么贞奋? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮穷绵,結(jié)果婚禮上轿塔,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好勾缭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布揍障。 她就那樣靜靜地躺著,像睡著了一般俩由。 火紅的嫁衣襯著肌膚如雪毒嫡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天幻梯,我揣著相機(jī)與錄音兜畸,去河邊找鬼。 笑死碘梢,一個(gè)胖子當(dāng)著我的面吹牛膳叨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播痘系,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼菲嘴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了汰翠?” 一聲冷哼從身側(cè)響起龄坪,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎复唤,沒想到半個(gè)月后健田,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佛纫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年妓局,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呈宇。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡好爬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出甥啄,到底是詐尸還是另有隱情存炮,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布蜈漓,位于F島的核電站穆桂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏融虽。R本人自食惡果不足惜享完,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望有额。 院中可真熱鬧般又,春花似錦彼绷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)句狼。三九已至笋熬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腻菇,已是汗流浹背胳螟。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筹吐,地道東北人糖耸。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像丘薛,于是被迫代替她去往敵國(guó)和親嘉竟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載自 http://blog.opskumu.com/docker.html 一洋侨、Docker 簡(jiǎn)介 Docke...
    極客圈閱讀 10,473評(píng)論 0 120
  • Docker — 云時(shí)代的程序分發(fā)方式 要說(shuō)最近一年云計(jì)算業(yè)界有什么大事件舍扰?Google Compute Engi...
    ahohoho閱讀 15,508評(píng)論 15 147
  • 一、Docker創(chuàng)建鏡像的方式有兩種: 一種通過(guò)commit的方式:把做了一系列操作的容器關(guān)閉希坚,然后利用docke...
    jie0112閱讀 3,821評(píng)論 0 3
  • 從2000年堅(jiān)持寫日記到現(xiàn)在整整16年边苹,但都是自嗨式,正是因?yàn)樗矫懿蒙钥梢阅_踩西瓜个束,滑到哪就到哪。那時(shí)候?qū)?..
    基長(zhǎng)Rayson閱讀 312評(píng)論 2 1
  • 我們也只是偶然擦肩 僅此而已 我卻不自覺 追逐你的身影 我欣喜 以為你的迷離的目光看向了我 我落寞 因?yàn)槟阃字杏?..
    辛末閱讀 284評(píng)論 2 1