作者丨Pavan Kumar
譯者 | 崔瑩峰
策劃丨諾亞
編寫Dockerfile看起來很容易,除非你最終編寫了大小為0.5GB的Docker鏡像。是的,沒錯(cuò)。我最近在做一個(gè)ReactJS項(xiàng)目,在那里我正在構(gòu)建一個(gè)前端應(yīng)用程序。React JS項(xiàng)目沒有什么新鮮的。我使用了與典型前端應(yīng)用程序相同的package.json,相同的依賴集?,F(xiàn)在,我決定將應(yīng)用程序遷移到Kubernetes。所以我將Docker鏡像推送到DockerHub并嘗試在Kubernetes部署Pod。
我使用的是一個(gè)本地集群,Pod花了5分零7秒啟動(dòng)。我很驚訝。然后我將其部署到AKS集群(Azure Kubernetes集群)。令人驚訝的是,它花了3分40秒。這可是件大事。我嘗試對(duì)Pod進(jìn)行壓測(cè)以觸發(fā)Kubernetes HPA(Horizontal Pod Autoscaler)。新的Pod需要同樣的3分鐘才能出現(xiàn),最終應(yīng)用程序被太多的請(qǐng)求淹沒,不堪重負(fù)以致崩潰不斷重啟。經(jīng)過調(diào)查,我發(fā)現(xiàn)鏡像的大小是瓶頸,當(dāng)然,你不會(huì)想要如此巨大的Docker鏡像(0.5GB)。那時(shí)我意識(shí)到我必須對(duì)Docker鏡像大小做些什么。因此,我使用了Docker多階段構(gòu)建的概念。
Docker構(gòu)建:
這是我最初的一個(gè)Dockerfile,它是為一個(gè)典型的ReactJS應(yīng)用程序提供的。如果你打開查看,你就可以看到第一行代碼,我使用了node:alpine作為基礎(chǔ)鏡像,如下是鏡像構(gòu)建完成后的尺寸。
非多階段構(gòu)建
這是構(gòu)建鏡像的典型方法,編寫這樣的Docker文件似乎很容易。但是從Kubernetes的角度來看,使用這種方法存在一些缺點(diǎn)如下
a)鏡像的大小直接影響Pod啟動(dòng)時(shí)間。
b)鏡像越小,Pod啟動(dòng)越快。
Docker多階段構(gòu)建:
Dockerfile中的多階段構(gòu)建特性使你能夠創(chuàng)建具有更好緩存和占用更小安全空間的較小容器鏡像。使用多階段構(gòu)建,你可以在Dockerfile中使用多個(gè)FROM語句。每個(gè)FROM指令可以使用不同的基礎(chǔ)鏡像,并且每個(gè)FROM指令都會(huì)開始構(gòu)建一個(gè)新的階段。你可以有選擇地將一個(gè)階段構(gòu)建好的內(nèi)容復(fù)制到另一個(gè)階段,對(duì)于那些不需要出現(xiàn)在在最終鏡像里的內(nèi)容就留在上一個(gè)階段好了。
似乎不一樣?好吧,讓我們了解一下這個(gè)文件。
第一行稱為階段。這些階段沒有命名,你通過它們的整數(shù)來引用它們,從0開始表示第一條FROM指令?;蛘撸阋部梢酝ㄟ^向FROM指令添加AS來命名階段。
然后其余的步驟保持不變。改變游戲規(guī)則的一個(gè)步驟是COPY——來自(第18行)。使用多階段生成時(shí),可以在Docker文件中使用多個(gè)FROM語句。每個(gè)FROM指令都可以使用不同的基礎(chǔ)鏡像,并且每個(gè)指令都開始構(gòu)建一個(gè)新的階段。你可以有選擇地將一個(gè)階段構(gòu)建好的內(nèi)容復(fù)制到另一個(gè)階段,對(duì)于那些不需要出現(xiàn)在在最終鏡像里的內(nèi)容就留在上一個(gè)階段好了。
現(xiàn)在讓我們開始構(gòu)建鏡像。
多階段構(gòu)建鏡像尺寸
哇,是的!圖像大小壓縮了95%。圖像大小現(xiàn)在是27.2MB。
我的本地集群花了25秒來拉取鏡像并開始使用。我的AKS集群花了10秒鐘來拉取鏡像并開始使用。
這就是如何利用Docker中的多階段構(gòu)建來壓縮Docker鏡像的大小。
原文鏈接:
??https://levelup.gitconnected.com/how-i-reduced-the-size-of-my-docker-image-by-95-520a05439300??
譯者簡(jiǎn)介
崔瑩峰,51CTO社區(qū)編輯,一名70后程序員,擁有10多年工作經(jīng)驗(yàn),長(zhǎng)期從事 Java開發(fā),架構(gòu)設(shè)計(jì),容器化等相關(guān)工作。