1. 程式人生 > >Docker 映象優化與最佳實踐

Docker 映象優化與最佳實踐

摘要: 雲棲TechDay41期,阿里雲高階研發工程師御阪帶來Docker映象優化與最佳實踐。從Docker映象儲存的原理開始,針對映象的儲存、網路傳輸,介紹如何在構建中對這些關鍵點進行優化。並介紹Docker最新的多階段構建的功能,以解決構建依賴的中間產物問題。

以下是精彩內容整理:

映象概念
圖片描述

映象是什麼?從一個比較具體的角度去看,映象就是一個多層儲存的檔案,相較於普通的ISO系統映象來說,分層儲存會帶來兩個優點,一個是分層儲存的映象比較容易擴充套件,比如我們可以基於一個Ubuntu映象去構建我們的Nginx映象,這樣我們只需要在Ubuntu映象的基礎上面做一些Nginx的安裝配置工作,一個Nginx映象工作就算製作完成了,我們不需要從頭開始去製作各種映象。另一點我們可以優化映象儲存空間,假如我們有兩個映象,Tag1.0映象和 Tag2.0映象,我們如果以傳統方式去傳這兩個映象,每個映象大概130多兆,但如果我們以分層的方式去儲存兩個映象,我們通過下面兩個紫色的才能共享,可以節約大量的空間,兩個映象加起來只需要140多兆的空間就可以存下來。這樣一是節省了儲存空間,二是可以減少網路上的開銷,比如我們已經把下面映象下載了,我們要去下載上面映象的時候,我們只需要去下10M的部分。

如果從抽象的角度去看,Docker映象其實是Docker提供的一種標準化的交付手段,傳統應用在交付的時候其實是交付一個可執行檔案,這個可執行檔案不包括它的執行環境,我們可能會因為32位系統或64位系統,或者開發測試使用1.0軟體,結果交付時候發現使用者的環境是2.0等各種各樣的問題,導致我們要去花時間去排查,如果我們以Docker映象的標準化形式去交付,我們就會避免掉這些問題。

映象基本操作與儲存方式

圖片描述

我們的一個映象會有一個座標,一個映象座標基本上會由四個部分組成,前面會有一個映象服務域名,每一個服務提供商都會有不同的域名,當我們確定服務提供商給我們的域名之後,我們一般會要到服務提供商那裡去申請自己的名稱空間,倉庫名稱一般是標識映象的用途,比如說Ubuntu映象、CentOS映象,標籤一般是用於去區分映象版本,比如我們對Ubuntu映象可能會打一些16.04的包,在我們確定了一個映象服務域名以及在雲服務商申請名稱空間之後,我們就可以對映象做一些操作了。

首先我們需要去登陸,我們會用第一條命令去登陸,然後,當我們在本地準備好一個映象想要上傳的時候,我們先要對這個映象進行打標,把它的座標變成我們現在需要上傳映象的座標,然後再去做一些推送拉取的動作,最後針對Docker還提供兩個額外命令去做映象交付,如果我們是特殊的環境,沒有辦法網路連通的時候,我們可以將這個映象打包成一個普通檔案進行傳輸。比如我們和公安合作,他們沒有辦法通過我們的Registry下載映象,我們可能要把它打成一個普通檔案,然後以U盤的方式去交付。

映象儲存細節

圖片描述

Docker映象是存在聯合檔案系統的,每一個映象其實是分層儲存的,比如在第一層我們添加了三個新檔案,然後在這一層基礎上我們又增加了一層,添加了一個檔案,第三層可能會需要做一些修改,我們把File3做了一個修改移到上面來,然後刪掉了File4,這裡就會引到聯合檔案系統裡面的寫時複製機制,當我們要去修改一個檔案的時候,映象依賴底層都是隻讀的,我們不能去直接修改,比如我們想去修改File3,我們不能直接去修改這個檔案,我們需要在修改的時候把檔案複製到當前這一層,比如說L3層,然後再去修改它。

一個映象做好之後,當我們想要知道映象裡面有哪一些內容的時候,我們其實會有一個檢視概念,我們從聯合檔案系統的角度去看映象的時候,其實我們不會看到L1、L2、L3,我們會最後看到結果,File1、File2、File3,File4就看不到了,然後在我們瞭解原理之後,我們就可以去理解容器執行起來是一個什麼樣的情況。容器執行起來和上面形成是類似的,圖中下半部分,同樣也是L1、L2、L3的三層映象,當容器執行起來的時候,Docker daemon會動態生成一層可寫層作為容器的執行層,然後當容器裡面需要去修改一些檔案,比如File2,也是copy on write機制把檔案複製上來,然後做一些修改,新增檔案的時候也是一樣,然後容器在執行的時候也會有一個檢視,當我們把容器停掉的時候,檢視一層就沒有了,它會被銷燬,但是容器層讀寫層還會保留,所以我們把容器停掉再啟動的時候,我們依舊會看到我們之前在容器裡面的一些操作。

常見的儲存驅動主要有AUFS、OverlayFS,還有Device Mapper,前兩種驅動都是基於檔案,它的原理就是需要修改一個檔案的時候把整個檔案複製上去做修改, Device Mapper更偏底層一點,它是基於塊裝置的,它的好處在於當我想要修改一個檔案的時候,我不會將整個檔案拷上去,我會將檔案修改的一些儲存塊拷上去做一些修改,當我有一些大檔案想要修改的時候,Device Mapper會比AUFS、OverlayFS好很多。所以AUFS和OverlayFS就比較適合傳統的WEB應用,它的檔案操作不會很多,但是它可能對我們的應用啟動速度會有一些要求,比如我可能經常要釋出,我希望能夠啟動比較快,但是對於檔案修改的一些效率我不是很關心,那可以使用基於檔案的驅動,當我們是一些計算密集型的應用時候,我們就可以選擇Device Mapper,雖然啟動比較慢,但是它的執行效率相對錶現要好一些。

映象自動化構建

圖片描述

我們構建一個映象的時候,Docker其實提供了一個標準化的構建指令集,當我們去用這些構建指令去寫類似於指令碼,這種指令碼我們稱之為DockerFile,Docker可以自動解析DockerFile,並將其構建成一個映象,所以你就可以簡單的認為這是一個標準化的指令碼。DockerFile在做一些什麼?首先第一行FROM指令表示要以哪一個映象作為基礎映象進行構建,我們用了openJDK的官方映象,以JAVA環境作為基礎,我們在映象上面準備跑一個JAVA應用,然後接下來兩條LABLE是對映象進行打標,標下映象版本和構建日期,然後接下來的六個RUN是做了一個maven安裝,maven是JAVA的一個生命週期管理工具,接下來將一些原始碼從外面的環境新增到映象裡面,然後兩條RUN命令做了打包工作,最後寫了一個啟動命令。

圖片描述

總的來說DockerFile寫的還可以,至少思路是很清晰的,一步一步從基礎映象選擇到編譯環境,再把原始碼加進去,然後再到最後的構建,啟動命令寫好,可讀性、可維護性都可以,但是還是可以進行優化的。

我們可以減少映象的層數, Docker對於Docker映象的層數是有一定要求的,除掉最上面在容器執行時候的讀寫層以外,我們一個映象最多隻能有127層,如果超過可能會出現問題,所以第二行命令LABLE就可以把它合成一層,減少了層數,下面六個RUN命令做了maven的安裝工作,我們也可以把它做成一層,把這些命令串起來,後面的構建我們也可以把它合成一層,這樣我們一下就把映象層數從14層減少到7層,減掉了一半。

我們在做映象優化的時候,我們希望能夠儘量減少映象的層數,但是和它相對應的是我們DockerFile的可讀性,我們需要在這兩者之間做折中,我們在保證可讀性不受很大影響的情況下去儘量減少它,其實六條RUN命令在做一件事,就是做maven環境打結,做編譯環境的準備工作。

圖片描述

接下來我們繼續對映象進行優化,我們可以做一些什麼工作呢?在安裝maven構建工具的時候我們多加了一行,我們把安裝包和展開目錄刪掉了,我們清理了構建的中間產物,我們要去注意每一個構建指令執行的時候,儘量把垃圾清理掉,我們通過apt-get去裝一些軟體的時候,我們也可以去做這樣的清理工作,就是把這些軟體包裝完之後就可以把它刪掉了,這樣可以儘量減少空間,通過增加一行命令,我們可以把映象的大小從137M削減到119M。

通過apt-get去裝軟體或者命令基本上是所有編寫DockerFile的人都去寫的,所以官方已經在debian、Ubuntu的倉庫映象裡面預設加了Hack,它會去幫助你在install自動去把原始碼刪掉。

圖片描述

我們可以利用構建的快取,Docker構建預設會開啟快取,快取生效有三個關鍵點,映象父層沒有發生變化,構建指令不變,新增檔案校驗和一致。只要一個構建指令滿足這三個條件,這一層映象構建就不會再執行,它會直接利用之前構建的結果,根據構建快取特性我們可以加一行RUN,這裡是以JAVA應用為例,一般一個JAVA應用的pom檔案都是描述JAVA的一些依賴,而在我們平常的開發過程中這些依賴包發生變化的頻率比較低,那麼我們就可以把POM加進來,把POM檔案依賴全部都準備好,然後再去下原始碼,再去做構建工作,只要我們沒有把快取關掉,我們每次構建的時候就不需要重新下安裝包,這樣可以節省大量時間,也可以節省一些網路流量。

圖片描述

現在阿里雲的容器映象服務其實已經提供了構建功能,我們在統計使用者失敗案例的時候就會發現,網路原因導致的失敗佔90%,比如如果使用者通過node開發NPM在安裝一些軟體包的時候經常卡在中間。所以我們建議加一個軟體源,我們把阿里雲maven地址加到裡面去,我們把配置項加到阿里雲的軟體地址,加阿里雲的maven源作為軟體包的下載目標,時間直接少了40%,這樣對一個映象構建的成功率也是有幫助的。

多階段構建

圖片描述

DockerFile最終需要做到的產物其實是JAVA應用,我們對於構建、編譯、打包或者安裝這些事情都不關心,我們要的其實是最後的產物。所以,我們可以採取分步的方式去做映象構建,首先我們將之前遇到的所有問題全部都做成基礎映象,上面FROM映象其實已經改了新的,映象裡面已經把軟體源的地址改成了Maven,快取都已經做好了。我們會去利用快取,然後新增原始碼,我們把前面構建的事情做成了映象,讓映象去完成構建,然後我們才會去完成把JAVA包拷進去,啟動工作,但是兩個DockerFile其實是兩個映象,所以我們需要一段指令碼去輔助它,第一行的shell指令碼是做第一個構建指令,我們指定以Bulid的DockerFile去啟動構建,然後生成一個APP Bulid映象,接下來兩行指令碼是把映象生成出來,把裡面的構建產物拷出來,然後我們再去做構建,最後把我們需要的JAVA應用給構建出來,這樣我們的DockerFile相比之前就更加清晰了,而且分步很簡單。

圖片描述

Docker在17.05之後官方支援了多階段構建,我們把下面的指令碼去掉了,我們不需要一段輔助指令碼,我們只需要在後面申明基礎映象的地方標記,我們第一階段的構建產物名字叫什麼,我們就可以在第二個構建階段裡面用第一個構建階段的產物。比如我們第一階段把JAVA應用構建好,把Maven包裡面的target下面的JAVA架包拷到新的映象裡面,然後在所有優化做完之後效果如圖,我們在第一次構建的時候,優化前102秒,在Docker構建優化後只花55秒就完成了,主要優化在網路上面。當我們修改了JAVA檔案重新進行構建,第二次構建花了86秒,因為Maven安裝那一塊被快取了,我們利用了構建快取,所以少掉20多秒,優化後只花了8秒,因為所有的原始碼前面的一些軟體包下載全部被快取了,我們直接拉新的映象,然後依賴沒有變,直接進行構建,所以8秒基本上是完整構建時間。

我們再來看一下儲存空間上面的優化,第一次構建我們在優化前把映象打出來有137M,但是在我們整個優化之後,只有81M了,這裡的基礎映象由JDK改成JRE,為什麼?因為之前我們把所有流程都放在一個映象裡面時,我們是需要去做構建的,構建時需要去RUN Maven,這種情況下沒有JDK環境是RUN不起來的,但是如果我們分階段,把構建交給Maven映象來做,把真正執行交給新的映象來做,就沒必要用JDK了,我們直接用JRE,優化之後映象少了將近50%。當我們修改原始碼重新進行構建的時候,由於映象成共享的原因,第二次構建在優化前其實多加了兩層到三層,一共有9M,但是優化後的第二次構建只增加1.93KB,這樣我們針對DockerFile的優化就已經做完了。

映象優化有哪些重要的點呢?具體如下:

減少映象的層數,儘量把一些功能上面統一的命令合到一起來做;
注意清理映象構建的中間產物,比如一些安裝包在裝完之後就把它刪掉;
注意優化網路請求,我們去用一些映象源,去用一些網路比較好的開源站點,這樣可以節約時間、減少失敗率;
儘量去用構建快取,我們儘量把一些不變的東西或者變的比較少的東西放在前面,因為不變的東西都是可以被快取的;
多階段進行映象構建,將我們映象製作的目的做一個明確,把我們的構建和真正的一些產物做分離,構建就用構建的映象去做,最終產物就打最終產物的映象。
容器映象服務

最後介紹一下阿里雲容器映象服務。這個服務已經公測一年了,現在我們的服務公測是全部免費的,現在在全球的12個Region都已經部署了我們的服務,每個Region其實都有內網服務和VPC網路服務,如果ECS也在同樣的Region,那麼它的服務是非常快的。然後團隊管理和組織帳號功能也已經上線了,映象購建和映象訊息通知其實都是一些DevOps能力,針對一些映象優化我們提供了一些映象層資訊瀏覽功能,我們後續也會提供分析,推出映象安全掃描、映象同步。

相關推薦

Docker 映象優化最佳實踐

摘要: 雲棲TechDay41期,阿里雲高階研發工程師御阪帶來Docker映象優化與最佳實踐。從Docker映象儲存的原理開始,針對映象的儲存、網路傳輸,介紹如何在構建中對這些關鍵點進行優化。並介紹Docker最新的多階段構建的功能,以解決構建依賴的中間產物問題

《深入理解Java虛擬機器——JVM高階特性最佳實踐》學習筆記——程式編譯程式碼優化(一)

早期(編譯期)優化 Javac的編譯過程 解析與填充符號表過程 插入式註解處理器的註解處理過程 分析與位元組碼生成過程 Javac編譯動作的入口是com.sun.tools.javac.main.JavaCompiler類,上述3個過程的程式碼

Docker筆記(十一):Dockerfile詳解最佳實踐

Dockerfile是一個文字檔案,包含了一條條指令,每條指令對應構建一層映象,Docker基於它來構建一個完整映象。本文介紹Dockerfile的常用指令及相應的最佳實踐建議。 1. 理解構建上下文(build context) Docker映象通過docker build指令構建,該指令執行時當前的工作目

微服務架構的兩大解耦利器最佳實踐

架構 微服務 沈劍 這幾年,微服務架構這個術語漸成熱門詞匯,但它不是一個全新架構,更不是一個包治百病的架構。那麽,微服務架構究竟能夠解決什麽問題,又帶來哪些痛點?本文將與大家談談這個問題,以及微服務架構的兩大解耦利器配置中心和消息總線的最佳實踐。微服務架構解決的問題與帶來的痛點一互聯網高可用架構為

《深入理解Java虛擬機:JVM高級屬性最佳實踐》讀書筆記(更新中)

pen 內存區域 深度 span 進化 ria 最短 描述 core 第一章:走進Java 概述 Java技術體系 Java發展史 Java虛擬機發展史 1996年 JDK1.0,出現Sun Classic VM HotSpot VM, 它是 Sun JDK 和 Open

php核心技術最佳實踐知識點(上)

mode roc url mys 修改 class null nbsp (上) 一.基礎 1.serialize:序列化一個類,只是保存了類的屬性,所以還需要反序列化unserialize的時候包含該類. 2.對於將array轉為object,這個轉換因為沒有具體的類,所以

php核心技術最佳實踐知識點(下)

清空 倒序 var 統計 apache this is_null 技術 其他 九.緩存 1.緩存三大要素:命中率, 緩存更新策略,緩存最大數據量 2.命中率(mysql為例):mysql提供了一系列的query cache的global status來提現數據庫緩存的情況:

《深入理解Java虛擬機:JVM高級特性最佳實踐》【PDF】下載

構建 實現原理 jvm內存 本地方法棧 人物 lvm 劃分 同時 棧溢出 《深入理解Java虛擬機:JVM高級特性與最佳實踐》【PDF】下載鏈接: https://u253469.pipipan.com/fs/253469-230062566 內容簡介 作為一位j

docker基礎使用入門實踐

docker鏡像 docker容器 docker容器管理常用命令 Dockerfile使用 docker鏡像制作 一、何為docker docker最早基於LXC實現(LinuX Container)從0.7版本以後開始去除LXC轉而使用自行開發的libcontainer,從1.11開始,

Ansible自動化運維:技術最佳實踐

資深運維人員聯手打造。 掌握大規模叢集運維管理的必備參考。 詳細講解Ansible自動化運維方式與技巧。 Ansible是DevOps語言之一,是第一款可以讀/寫跨平臺的“Infrastructure-as-code”工具,從系統管理者到開發者,都可使用Ansible自動化部署並

學習筆記1:深入理解Java虛擬機器——JVM高階特性最佳實踐_OOM(記憶體溢位)_虛擬機器引數設定_MAT

eclipse中設定debug標籤頁的vm引數 1,Run->Debug configurations->Java Application 2,選中已經寫好的專案 3,Arguments->VM arguments 4,在VM arguments 裡面就可以對虛擬機器的

學習筆記1:深入理解Java虛擬機器——JVM高階特性最佳實踐_走進java_java記憶體區域記憶體溢位異常

第一部分:走進java Java虛擬機器 程式碼在華章下載 jdk釋出了六個命令列工具和兩個視覺化故障處理工具。 推薦書籍 設計原本 領域特定語言 現在著名的Java虛擬機器 hotspot vm(預設) jrockit vm j9 vm jdk sun jdk op

溫習《PHP 核心技術最佳實踐》這本書

匹配 9.4 表達式 穩定 處理 變量 mem 分布式 內容 再次看這本書,順手提煉了一下大致目錄,以便後續看見目錄就知道大概講的些什麽內容 PHP 核心技術與最佳實踐 1、面向對象思想的核心概念 1.1 面向對象的『形』與『本』 1.2 魔術方法的應用

MongoDB 應用場景、避坑事項最佳實踐

社群最近組織了交流活動,探討MongoDB適合的應用場景、避坑事項與最佳實踐。由社群專家劉誠傑根據交流內容整理成文,無論是MongoDB零基礎的小夥伴,還是正在應用中的朋友,在此均可以找到有價值的經驗和分享。 劉誠傑,專注於MongoDB、MySQL、Redis等開源資料庫的使用與研究,Mo

Python自動化運維 :技術最佳實踐 [劉天斯著] 完整版pdf 下載

本書在中國運維領域將有“劃時代”的重要意義:一方面,這是國內一本從縱、深和實踐角度探討Python在運維領域應用的著作;一方面本書的作者是中國運維領域的“偶像級”人物,本書是他在天涯社群和騰訊近10年工作經驗的結晶。因為作者實戰經驗豐富,所以能高屋建瓴、直指痛處,圍繞Python自動化運維這個

原始碼系列Spring,Mybatis,Springboot,Netty原始碼深度解析-Spring的整體架構容器的基本實現-mybatis原始碼深度解析最佳實踐

6套原始碼系列Spring,Mybatis,Springboot,Netty原始碼深度解析視訊課程   6套原始碼套餐課程介紹: 1、6套精品是掌櫃最近整理出的最新課程,都是當下最火的技術,最火的課程,也是全網課程的精品;   2、6套資源包含:全套完整

Redux的全家桶最佳實踐

edux 的第一次程式碼提交是在 2015 年 5 月底(也就是一年多前的樣子),那個時候 React 的最佳實踐還不是明晰,作為一個 View 層,有人會用 backbone 甚至是 angular 和它搭配,也有人覺得這層 View 功能已經足夠強大,簡單地搭配一些 utils 就直接上。後來便

《深入理解Java虛擬機器——JVM高階特性最佳實踐(第2版)》pdf

前言 致謝 第一部分 走近Java 第1章 走近Java / 2 1.1 概述 / 2 1.2 Java技術體系 / 3 1.3 Java發展史 / 5 1.4 展望Java技術的未來 / 9 1.4.1 模組化 / 9 1.4.2 混合語言 / 9 1.4.

iOS系統中導航欄的轉場解決方案最佳實踐

背景 目前,開源社群和業界內已經存在一些 iOS 導航欄轉場的解決方案,但對於歷史包袱沉重的美團 App 而言,這些解決方案並不完美。有的方案不能滿足複雜的頁面跳轉場景,有的方案遷移成本較大,為此我們提出了一套解決方案並開發了相應的轉場庫,目前該轉場庫已經成為美

國際化SEO優化最佳實踐

作者:Kristopher Jones 翻譯 :吳祺深 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。  讓我們來說一下hreflang屬性。如果你還沒有關掉這個頁面,那麼你已經完成了這個教程最重要的一步:開始。 為你的國際客戶優化SEO實踐,需要比試圖對本地的暖通空調公司進行排名更多的技術