寫好Dockerfile的12個(gè)技巧

Docker鏡像由只讀層組成,每個(gè)層都代表一個(gè)Dockerfile指令勃救。這些層是堆疊的邦蜜,每一層都是前一層變化的增量独泞。示例Dockerfile

FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py

每條指令創(chuàng)建一個(gè)層:

  • FROMubuntu:15.04Docker鏡像創(chuàng)建一個(gè)圖層啰挪。
  • COPY 從Docker客戶端的當(dāng)前目錄添加文件。
  • RUN用你的應(yīng)用程序構(gòu)建make嘲叔。
  • CMD 指定在容器中運(yùn)行的命令亡呵。

運(yùn)行圖像并生成容器時(shí),可以 在基礎(chǔ)圖層的頂部添加新的可寫層(“容器圖層”)硫戈。對(duì)正在運(yùn)行的容器所做的所有更改(例如寫入新文件锰什,修改現(xiàn)有文件和刪除文件)都將寫入此可寫容器層。

1.使用標(biāo)簽

? 給鏡像打上標(biāo)簽丁逝,易讀的鏡像標(biāo)簽可以幫助了解鏡像的功能汁胆。

2.使用統(tǒng)一的Base鏡像,比如busybox或者alpine霜幼,謹(jǐn)慎選擇基礎(chǔ)鏡像嫩码,盡量選擇當(dāng)前官方的鏡像庫(kù)中的鏡像。

? 很多教程中建議大家使用alpine鏡像罪既,更建議大家使用centos铸题,Ubuntu這樣的鏡像。同時(shí)琢感,在構(gòu)建自己的Docker鏡像時(shí)丢间,只安裝和更新必須使用的包,FROM指令應(yīng)該包含的參數(shù)tag猩谊,比如使用centos:7.5.1504而不是FROM centos千劈。

3.充分利用緩存

? 在鏡像的構(gòu)建過(guò)程中,Docker 會(huì)遍歷 Dockerfile 文件中的指令牌捷,然后按順序執(zhí)行墙牌。在執(zhí)行每條指令之前,Docker 都會(huì)在緩存中查找是否已經(jīng)存在可重用的鏡像暗甥,如果有就使用現(xiàn)存的鏡像喜滨,不再重復(fù)創(chuàng)建。如果你不想在構(gòu)建過(guò)程中使用緩存撤防,你可以在 docker build 命令中使用 --no-cache=true 選項(xiàng)虽风。

但是,如果你想在構(gòu)建的過(guò)程中使用緩存寄月,你得明白什么時(shí)候會(huì)辜膝,什么時(shí)候不會(huì)找到匹配的鏡像,遵循的基本規(guī)則如下:

  • 從一個(gè)基礎(chǔ)鏡像開始(FROM 指令指定)漾肮,下一條指令將和該基礎(chǔ)鏡像的所有子鏡像進(jìn)行匹配厂抖,檢查這些子鏡像被創(chuàng)建時(shí)使用的指令是否和被檢查的指令完全一樣。如果不是克懊,則緩存失效忱辅。
  • 在大多數(shù)情況下七蜘,只需要簡(jiǎn)單地對(duì)比 Dockerfile 中的指令和子鏡像。然而墙懂,有些指令需要更多的檢查和解釋橡卤。
  • 對(duì)于 ADDCOPY 指令,鏡像中對(duì)應(yīng)文件的內(nèi)容也會(huì)被檢查损搬,每個(gè)文件都會(huì)計(jì)算出一個(gè)校驗(yàn)和碧库。文件的最后修改時(shí)間和最后訪問(wèn)時(shí)間不會(huì)納入校驗(yàn)。在緩存的查找過(guò)程中场躯,會(huì)將這些校驗(yàn)和和已存在鏡像中的文件校驗(yàn)和進(jìn)行對(duì)比谈为。如果文件有任何改變,比如內(nèi)容和元數(shù)據(jù)踢关,則緩存失效伞鲫。
  • 除了 ADDCOPY 指令,緩存匹配過(guò)程不會(huì)查看臨時(shí)容器中的文件來(lái)決定緩存是否匹配签舞。例如秕脓,當(dāng)執(zhí)行完 RUN apt-get -y update 指令后,容器中一些文件被更新儒搭,但 Docker 不會(huì)檢查這些文件吠架。這種情況下,只有指令字符串本身被用來(lái)匹配緩存搂鲫。

一旦緩存失效傍药,所有后續(xù)的 Dockerfile 指令都將產(chǎn)生新的鏡像,緩存不會(huì)被使用魂仍。

4.正確使用ADD和COPY指令

這兩者很相似拐辽,推薦有限選擇 COPY,它比 ADD 透明度更高擦酌。

  • COPY俱诸,只支持將本地文件復(fù)制到容器中
  • ADD,除了 COPY 的功能外赊舶,還支持遠(yuǎn)程 URL睁搭。但最好的用途是將本地 tar 文件提取到鏡像中 ADD rootfs.tar.xz /

如果在 Dockerfile 中使用不用的文件笼平,那么 COPY 它們可以單獨(dú)使用园骆。這樣,特定文件的更改寓调,將確保每一步的構(gòu)建緩存無(wú)效遇伞,如:

DOCKERFILECOPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/

COPY . /tmp/ 放在后面,這能夠使 RUN 的緩存無(wú)效的數(shù)量減少捶牢。盡量使用docker volume共享文件鸠珠,而不是用ADD指令添加文件。

5. 不要在 Dockerfile 中單獨(dú)修改文件的權(quán)限

? 因?yàn)?docker 鏡像是分層的秋麸,任何修改都會(huì)新增一個(gè)層渐排,修改文件或者目錄權(quán)限也是如此。如果有一個(gè)命令單獨(dú)修改大文件或者目錄的權(quán)限灸蟆,會(huì)把這些文件復(fù)制一份驯耻,這樣很容易導(dǎo)致鏡像很大。

? 解決方案也很簡(jiǎn)單炒考,要么在添加到 Dockerfile 之前就把文件的權(quán)限和用戶設(shè)置好可缚,要么在容器啟動(dòng)腳本(entrypoint)做這些修改,或者拷貝文件和修改權(quán)限放在一起做(這樣最終也只是增加一層)斋枢。

6. 版本控制和自動(dòng)構(gòu)建

? 最好把 Dockerfile 和對(duì)應(yīng)的應(yīng)用代碼一起放到版本控制中帘靡,然后能夠自動(dòng)構(gòu)建鏡像。這樣的好處是可以追蹤各個(gè)版本鏡像的內(nèi)容瓤帚,方便了解不同鏡像有什么區(qū)別描姚,對(duì)于調(diào)試和回滾都有好處。

? 另外戈次,如果運(yùn)行鏡像的參數(shù)或者環(huán)境變量很多轩勘,也要有對(duì)應(yīng)的文檔給予說(shuō)明,并且文檔要隨著 Dockerfile 變化而更新怯邪,這樣任何人都能參考著文檔很容易地使用鏡像绊寻,而不是下載了鏡像不知道怎么用。

7.RUN指令

? 為了使Dockerfile易讀悬秉、易理解和可維護(hù)澄步,在使用比較長(zhǎng)的RUN指令是可以使用反斜杠\分隔多行。將多行參數(shù)按字母順序排序(比如要安裝多個(gè)包時(shí))搂捧。這可以幫助你避免重復(fù)包含同一個(gè)包驮俗,更新包列表時(shí)也更容易。也便于 PRs 閱讀和審查允跑。建議在反斜杠符號(hào) \ 之前添加一個(gè)空格王凑,以增加可讀性。

示例:

RUN yum update && yum install -y \
  vim \
  ntpdate \
  git \
  nginx

6.CMD和ENTRYPOINT指令

? CMD和ENTRYPOINT指令指定了容器運(yùn)行的默認(rèn)命令聋丝,推薦二者結(jié)合使用索烹。使用exec格式ENTRYPOINT指令設(shè)置固定的默認(rèn)命令和參數(shù),然后使用CMD指令設(shè)置可變的參數(shù)弱睦。

7.不要在Dockerfile中做端口映射

? Docker的兩個(gè)核心概念是可重復(fù)性和可移植性百姓,鏡像應(yīng)該可以在任何主機(jī)上運(yùn)行多次。映射端口會(huì)破壞鏡像的可移植性况木,且這樣的鏡像只能在一臺(tái)主機(jī)上啟動(dòng)一個(gè)容器垒拢。所以端口映射應(yīng)在docker run命令中用-p參數(shù)指定旬迹。

# 不要在Dockerfile中做如下映射
EXPOSE 80:8080
# 僅僅暴露80端口,需要另做映射
EXPOSE 80

8.使用多階段構(gòu)建

Docker 17.05 以上版本中求类,你可以使用 多階段構(gòu)建 來(lái)減少所構(gòu)建鏡像的大小奔垦。

9.避免安裝不必要的包

? 為了降低復(fù)雜性、減少依賴尸疆、減小文件大小椿猎、節(jié)約構(gòu)建時(shí)間,你應(yīng)該避免安裝任何不必要的包寿弱。例如犯眠,不要在數(shù)據(jù)庫(kù)鏡像中包含一個(gè)文本編輯器。

10.一個(gè)容器只運(yùn)行一個(gè)進(jìn)程

? 應(yīng)該保證在一個(gè)容器中只運(yùn)行一個(gè)進(jìn)程症革。將多個(gè)應(yīng)用解耦到不同容器中筐咧,保證了容器的橫向擴(kuò)展和復(fù)用。例如 web 應(yīng)用應(yīng)該包含三個(gè)容器:web應(yīng)用地沮、數(shù)據(jù)庫(kù)嗜浮、緩存。

? 如果容器互相依賴摩疑,你可以使用 Docker 自定義網(wǎng)絡(luò) 來(lái)把這些容器連接起來(lái)危融。

12.鏡像層數(shù)盡可能少

? 你需要在 Dockerfile 可讀性(也包括長(zhǎng)期的可維護(hù)性)和減少層數(shù)之間做一個(gè)平衡。

參考資料:

? Best practices for writing Dockerfiles

? How to write excellent Dockerfiles

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雷袋,一起剝皮案震驚了整個(gè)濱河市吉殃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌楷怒,老刑警劉巖蛋勺,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鸠删,居然都是意外死亡抱完,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門刃泡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)巧娱,“玉大人,你說(shuō)我怎么就攤上這事烘贴〗恚” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵桨踪,是天一觀的道長(zhǎng)老翘。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么铺峭? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任墓怀,我火速辦了婚禮,結(jié)果婚禮上逛薇,老公的妹妹穿的比我還像新娘捺疼。我一直安慰自己,他們只是感情好永罚,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卧秘,像睡著了一般呢袱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上翅敌,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天羞福,我揣著相機(jī)與錄音,去河邊找鬼蚯涮。 笑死治专,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遭顶。 我是一名探鬼主播张峰,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼棒旗!你這毒婦竟也來(lái)了喘批?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铣揉,失蹤者是張志新(化名)和其女友劉穎饶深,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逛拱,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡敌厘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朽合。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俱两。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖旁舰,靈堂內(nèi)的尸體忽然破棺而出锋华,到底是詐尸還是另有隱情,我是刑警寧澤箭窜,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布毯焕,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纳猫。R本人自食惡果不足惜婆咸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芜辕。 院中可真熱鬧尚骄,春花似錦、人聲如沸侵续。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)状蜗。三九已至需五,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間轧坎,已是汗流浹背宏邮。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缸血,地道東北人蜜氨。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捎泻,于是被迫代替她去往敵國(guó)和親飒炎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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

  • Docker — 云時(shí)代的程序分發(fā)方式 要說(shuō)最近一年云計(jì)算業(yè)界有什么大事件族扰?Google Compute Engi...
    ahohoho閱讀 15,508評(píng)論 15 147
  • 轉(zhuǎn)載自 http://blog.opskumu.com/docker.html 一厌丑、Docker 簡(jiǎn)介 Docke...
    極客圈閱讀 10,475評(píng)論 0 120
  • docker基本概念 1. Image Definition 鏡像 Image 就是一堆只讀層 read-only...
    慢清塵閱讀 8,725評(píng)論 1 21
  • 2018.3.25 星期日 晴 春暖花開、萬(wàn)物復(fù)蘇渔呵、陽(yáng)光明媚怒竿、和風(fēng)習(xí)習(xí),最舒適的季節(jié)...
    郭姿含閱讀 392評(píng)論 2 4
  • 只給你救生圈扩氢,而你沒本領(lǐng)耕驰,也游不到你想到的地方… 五歲,十歲录豺,十一歲朦肘,經(jīng)濟(jì)有基礎(chǔ)的家庭都會(huì)將自己孩紙送到國(guó)外,適早...
    崎零壹閱讀 336評(píng)論 0 1