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