1. 程式人生 > >小米在Docker上最佳實踐:5個方法精簡映象

小米在Docker上最佳實踐:5個方法精簡映象

精簡Docker映象的好處很多,不僅可以節省儲存空間和頻寬,還能減少安全隱患。優化映象大小的手段多種多樣,因服務所使用的基礎開發語言不同而有差異。本文將介紹精簡Docker映象的幾種通用方法。

精簡Docker映象大小的必要性

Docker映象由很多映象層(Layers)組成(最多127層),映象層依賴於一系列的底層技術,比如檔案系統(filesystems)、寫時複製(copy-on-write)、聯合掛載(union mounts)等技術,你可以檢視Docker社群文件以瞭解更多有關Docker儲存驅動的內容,這裡就不再贅述技術細節。總的來說,Dockerfile中的每條指令都會建立一個映象層,繼而會增加整體映象的尺寸。
下面是精簡Docker映象尺寸的好處:
1、減少構建時間
2、減少磁碟使用量
3、減少下載時間
4、因為包含檔案少,攻擊面減小,提高了安全性
5、提高部署速度

五點建議減小Docker映象尺寸

一、優化基礎映象

優化基礎映象的方法就是選用合適的更小的基礎映象,常用的 Linux 系統映象一般有 Ubuntu、CentOs、Alpine,其中Alpine更推薦使用。大小對比如下:

[email protected] ~/s> docker images
REPOSITORY       TAG           IMAGE ID          CREATED           SIZE
ubuntu          latest       74f8760a2a8b      8 days ago         82.4MB
alpine          latest       11cd0b38bc3c      2 weeks ago        4.41MB
centos            7          49f7960eb7e4      7 weeks ago        200MB
debian          latest       3bbb526d2608      8 days ago         101MB
[email protected]
~/s>

Alpine是一個高度精簡又包含了基本工具的輕量級Linux發行版,基礎映象只有4.41M,各開發語言和框架都有基於Alpine製作的基礎映象,強烈推薦使用它。Alpine映象各個語言和框架支援情況,可以參考《優化Docker映象、加速應用部署,教你6個小竅門》
檢視上面的映象尺寸對比結果,你會發現最小的映象也有4.41M,那麼有辦法構建更小的映象嗎?答案是肯定的,例如 gcr.io/google_containers/pause-amd64:3.1 映象僅有742KB。為什麼這個映象能這麼小?在為大家解密之前,再推薦兩個基礎映象:
1、scratch映象


scratch是一個空映象,只能用於構建其他映象,比如你要執行一個包含所有依賴的二進位制檔案,如Golang程式,可以直接使用scratch作為基礎映象。現在給大家展示一下上文提到的Google pause映象Dockerfile:

FROM scratch
ARG ARCH
ADD bin/pause-${ARCH} /pause
ENTRYPOINT ["/pause"]

Google pause映象使用了scratch作為基礎映象,這個映象本身是不佔空間的,使用它構建的映象大小几乎和二進位制檔案本身一樣大,所以映象非常小。當然在我們的Golang程式中也會使用。對於一些Golang/C程式,可能會依賴一些動態庫,你可以使用自動提取動態庫工具,比如ldd、linuxdeployqt等提取所有動態庫,然後將二進位制檔案和依賴動態庫一起打包到映象中。
2、busybox映象
scratch是個空映象,如果希望映象裡可以包含一些常用的Linux工具,busybox映象是個不錯選擇,映象本身只有1.16M,非常便於構建小映象。


二、串聯 Dockerfile 指令

大家在定義Dockerfile時,如果太多的使用RUN指令,經常會導致映象有特別多的層,映象很臃腫,而且甚至會碰到超出最大層數(127層)限制的問題,遵循 Dockerfile 最佳實踐,我們應該把多個命令串聯合併為一個 RUN(通過運算子&&和/ 來實現),每一個 RUN 要精心設計,確保安裝構建最後進行清理,這樣才可以降低映象體積,以及最大化的利用構建快取。
下面是一個優化前Dockerfile:

FROM ubuntu

ENV VER     3.0.0  
ENV TARBALL http://download.redis.io/releases/redis-$VER.tar.gz  
# ==> Install curl and helper tools...
RUN apt-get update  
RUN apt-get install -y  curl make gcc  
# ==> Download, compile, and install...
RUN curl -L $TARBALL | tar zxv  
WORKDIR  redis-$VER  
RUN make  
RUN make install  
#...
# ==> Clean up...
WORKDIR /  
RUN apt-get remove -y --auto-remove curl make gcc  
RUN apt-get clean  
RUN rm -rf /var/lib/apt/lists/*  /redis-$VER  
#...
CMD ["redis-server"]


構建映象,名稱叫 test/test:0.1。
我們對Dockerfile做優化,優化後Dockerfile:

FROM ubuntu

ENV VER     3.0.0  
ENV TARBALL http://download.redis.io/releases/redis-$VER.tar.gz

RUN echo "==> Install curl and helper tools..."  && \  
    apt-get update                      && \
    apt-get install -y  curl make gcc   && \
    echo "==> Download, compile, and install..."  && \
    curl -L $TARBALL | tar zxv  && \
    cd redis-$VER               && \
    make                        && \
    make install                && \
    echo "==> Clean up..."  && \
    apt-get remove -y --auto-remove curl make gcc  && \
    apt-get clean                                  && \
    rm -rf /var/lib/apt/lists/*  /redis-$VER
#...
CMD ["redis-server"]


構建映象,名稱叫 test/test:0.2。
對比兩個映象大小:

[email protected]:/tmp/iops# docker images
REPOSITORY       TAG           IMAGE ID            CREATED             SIZE
test/test        0.2         58468c0222ed        2 minutes ago       98.1MB
test/test        0.1         e496cf7243f2        6 minutes ago       307MB
[email protected]:/tmp/iops#

可以看到,將多條RUN命令串聯起來構建的映象大小是每條命令分別RUN的三分之一。

提示:為了應對映象中存在太多映象層,Docker 1.13版本以後,提供了一個壓扁映象功能,即將 Dockerfile 中所有的操作壓縮為一層。這個特性還處於實驗階段,Docker預設沒有開啟,如果要開啟,需要在啟動Docker時新增-experimental 選項,並在Docker build 構建映象時候新增 --squash 。我們不推薦使用這個辦法,請在撰寫 Dockerfile 時遵循最佳實踐編寫,不要試圖用這種辦法去壓縮映象。

三、使用多階段構建

Dockerfile中每條指令都會為映象增加一個映象層,並且你需要在移動到下一個映象層之前清理不需要的元件。實際上,有一個Dockerfile用於開發(其中包含構建應用程式所需的所有內容)以及一個用於生產的瘦客戶端,它只包含你的應用程式以及執行它所需的內容。這被稱為“建造者模式”。Docker 17.05.0-ce版本以後支援多階段構建。使用多階段構建,你可以在Dockerfile中使用多個FROM語句,每條FROM指令可以使用不同的基礎映象,這樣您可以選擇性地將服務元件從一個階段COPY到另一個階段,在最終映象中只保留需要的內容。
下面是一個使用COPY —from 和 FROM … AS … 的Dockerfile:

# Compile
FROM golang:1.9.0 AS builder
WORKDIR /go/src/v9.git...com/.../k8s-monitor
COPY . .
WORKDIR /go/src/v9.git...com/.../k8s-monitor
RUN make build
RUN mv k8s-monitor /root

# Package
# Use scratch image
FROM scratch
WORKDIR /root/
COPY --from=builder /root .
EXPOSE 8080
CMD ["/root/k8s-monitor"]

構建映象,你會發現生成的映象只有上面COPY 指令指定的內容,映象大小隻有2M。這樣在以前使用兩個Dockerfile(一個Dockerfile用於開發和一個用於生產的瘦客戶端),現在使用多階段構建就可以搞定。

四、構建業務服務映象技巧

Docker在build映象的時候,如果某個命令相關的內容沒有變化,會使用上一次快取(cache)的檔案層,在構建業務映象的時候可以注意下面兩點:

不變或者變化很少的體積較大的依賴庫和經常修改的自有程式碼分開;

因為cache快取在執行Docker build命令的本地機器上,建議固定使用某臺機器來進行Docker build,以便利用cache。

下面是構建Spring Boot應用映象的例子,用來說明如何分層。其他型別的應用,比如Java WAR包,Nodejs的npm 模組等,可以採取類似的方式。
1、在Dockerfile所在目錄,解壓縮maven生成的jar包

$ unzip <path-to-app-jar>.jar -d app

2、Dockerfile 我們把應用的內容分成4個部分COPY到映象裡面:其中前面3個基本不變,第4個是經常變化的自有程式碼。最後一行是解壓縮後,啟動spring boot應用的方式。

FROM openjdk:8-jre-alpine

LABEL maintainer "[email protected]"
COPY app/BOOT-INF/lib/ /app/BOOT-INF/lib/
COPY app/org /app/org
COPY app/META-INF /app/META-INF
COPY app/BOOT-INF/classes /app/BOOT-INF/classes
EXPOSE 8080
CMD ["/usr/bin/java", "-cp", "/app", "org.springframework.boot.loader.JarLauncher"]

這樣在構建映象時候可大大提高構建速度。

五、其他優化辦法

1、RUN命令中執行apt、apk或者yum類工具技巧
如果在RUN命令中執行apt、apk或者yum類工具,可以藉助這些工具提供的一些小技巧來減少映象層數量及映象大小。舉幾個例子:
(1)在執行apt-get install -y 時增加選項— no-install-recommends ,可以不用安裝建議性(非必須)的依賴,也可以在執行apk add 時新增選項—no-cache 達到同樣效果;
(2)執行yum install -y 時候, 可以同時安裝多個工具,比如yum install -y gcc gcc-c++ make …。將所有yum install 任務放在一條RUN命令上執行,從而減少映象層的數量;
(3)元件的安裝和清理要串聯在一條指令裡面,如 apk —update add php7 && rm -rf /var/cache/apk/ ,因為Dockerfile的每條指令都會產生一個檔案層,如果將apk add … 和 rm -rf … 命令分開,清理無法減小apk命令產生的檔案層的大小。 Ubuntu或Debian可以使用 rm -rf /var/lib/apt/lists/ 清理映象中快取檔案;CentOS等系統使用yum clean all 命令清理。

2、壓縮映象
Docker 自帶的一些命令還能協助壓縮映象,比如 export 和 import

$ docker run -d test/test:0.2 
$ docker export 747dc0e72d13 | docker import - test/test:0.3


使用這種方式需要先將容器執行起來,而且這個過程中會丟失映象原有的一些資訊,比如:匯出埠,環境變數,預設指令。
檢視這兩個映象history資訊,如下,可以看到test/test:0.3 丟失了所有的映象層資訊:

[email protected]:/tmp/iops# docker history test/test:0.3
IMAGE               CREATED             CREATED BY          SIZE                COMMENT
6fb3f00b7a72        15 seconds ago                          84.7MB              Imported from -
[email protected]:/tmp/iops# docker history test/test:0.2
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
58468c0222ed        2 hours ago         /bin/sh -c #(nop)  CMD ["redis-server"]         0B       
1af7ffe3d163        2 hours ago         /bin/sh -c echo "==> Install curl and helper…   15.7MB   
8bac6e733d54        2 hours ago         /bin/sh -c #(nop)  ENV TARBALL=http://downlo…   0B       
793282f3ef7a        2 hours ago         /bin/sh -c #(nop)  ENV VER=3.0.0                0B       
74f8760a2a8b        8 days ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B       
<missing>           8 days ago          /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B
<missing>           8 days ago          /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$…   2.76kB
<missing>           8 days ago          /bin/sh -c rm -rf /var/lib/apt/lists/*          0B
<missing>           8 days ago          /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B    
<missing>           8 days ago          /bin/sh -c #(nop) ADD file:5fabb77ea8d61e02d…   82.4MB   
[email protected]:/tmp/iops#

社群裡還有很多壓縮工具,比如Docker-squash ,用起來更簡單方便,並且不會丟失原有映象的自帶資訊,大家有興趣可以試試。

總結

Docker映象的精簡手段和精簡效果值得深入探討和實踐,希望本文能為大家帶來幫助。如果你有更好的方法和經驗,歡迎與我們交流。

相關推薦

小米Docker最佳實踐5方法精簡映象

精簡Docker映象的好處很多,不僅可以節省儲存空間和頻寬,還能減少安全隱患。優化映象大小的手段多種多樣,因服務所使用的基礎開發語言不同而有差異。本文將介紹精簡Docker映象的幾種通用方法。 精簡Docker映象大小的必要性 Docker映象由很多映象層(Layers)

運行容器的最佳實踐 - 每天5分鐘玩轉 Docker 容器技術(24)

oat add vertical poi can size 執行命令 後臺 運行 按用途容器大致可分為兩類:服務類容器和工具類的容器。 1. 服務類容器以 daemon 的形式運行,對外提供服務。比如 web server,數據庫等。通過 -d 以後臺方式啟動這類容器是非常

最佳實踐IDC雙專線靜態路由冗余雲方案

技術分享 雲解決方案 ado size col 上進 tex shadow 沖突 摘要: 通過介紹專線接入和雲企業網組合應用的方式,提供客戶IDC冗余鏈路專線接入靜態路由配置的混合雲解決方案。 大家好,我是雲企業網產品經理辰城。之前為大家介紹了專線通過BGP結合雲企業網主備

華為雲資料庫最佳實踐智慧化和自動化支撐企業雲無憂

在剛過去的 2018 華為全聯接大會上,與會者可謂渡過了一個狂歡盛宴。從火到爆炸的 +AI、到紅得發紫的+智慧,從理論、到實踐;各路大咖把當下網際網路最熱門的產品和方案盡數拆解個遍。其中華為雲資料庫帶來的一系列主題演講和最佳實踐,更是成為眾多企業上雲的指路牌。 《華

iOS7 最佳實踐一個天氣應用案例(

在這個兩部分的系列教程中,您將探索如何使用以下工具和技術來建立自己的App: 本教程專為熟悉基本知識的、但還沒有接觸到太多高階主題的中級開發者而設計。本教程也是想要去探索Objective-C函式程式設計一個很好的開始。 開始 開啟Xcode並執行File\New\Proj

Istio最佳實踐在K8s通過Istio服務網格進行灰度釋出

Istio是什麼? Istio是Google繼Kubernetes之後的又一開源力作,主要參與的公司包括Google,IBM,Lyft等公司。它提供了完整的非侵入式的微服務治理解決方案,包含微服務的管理、網路連線以及安全管理等關鍵能力,無需修改任何程式碼就能夠實現微服務的負

Docker 架構介紹docker安全最佳實踐

簡介 docker 賴以生存的“Secure by Default”,docker EE 預設的配置和策略提供基礎雄厚的安全環境,因此,他們可以非常容易的修改來適應不同組織的特殊需求。 docker 把重點放到了容器安全的三個關鍵領域:安全訪問、安全內容、安

遊戲運維的最佳實踐搜狐暢遊自動化運維之旅!

運維 遊戲 搜狐暢遊 搜狐黎誌剛見證了暢遊遊戲自動化運維平臺的從無到有,通過在其中踩過的坑、解過的結,他向大家來闡述遊戲運維的進階之路。本文主要圍繞暢遊遊戲管理體系與運維自動化的演變歷程、運維自動化的實現及未來運維四方面展開。暢遊運維管理體系與運維自動化的演變歷程暢遊運維管理體系演變歷程從 200

Oracle數據庫測試和優化最佳實踐 OTest介紹 (轉)

1-1 log 數據 bsp 下載 pan alt style 發送 當前Oracle數據庫最佳測試工具OTest * Otest是用於Oracle數據庫測試、優化、監控軟件。 * Otest是免費提供給Oracle客戶和廣大DBA工程師使用的軟件。由原廠技

分布式學習最佳實踐從分布式系統的特征開始(附思維導圖)

擴展 問題 sca ref 調度 這也 集中 技術 park     我的探索歷程   這一部分,與分布式不大相關,記錄的是我是如何在分布式學習這條道路上摸索的,不感興趣的讀者請直接跳到下一章。   過去的一年,我在分布式學習這條道路上苦苦徘徊,始終沒有找到一個好的學

Git 最佳實踐分支管理

數據 ken 參考 更新 讓其 vincent 兼容 ucc 足夠 5月份,為統一團隊git分支管理規範,剛開始準備自己寫,在網上搜了下,發現不少不錯的git分支管理實踐。最後我為團隊選擇了這個git分支管理實踐 A successful Git branchi

最佳實踐使用負載均衡SLB IPv6搞定蘋果AppStore審核

iyu ini 商家 市場 1.5 san 情況 sdn 能力 摘要: 1.Greetings HI,大家好,我是負載均衡SLB產品經理添毅,今天我們來聊一聊蘋果的IPv6審核,以及使用阿裏雲負載均衡SLB(IPv6)搞定AppStore IPv6審核。 2.Appstor

最佳實踐負載均衡SLB支持自定義VPC實例IP地址

vpd 添加 reg mark 設置 結束 tin 通過 等待 摘要: 1.Greetings 大家好,我是負載均衡SLB產品經理添毅,今天教大家自定義負載均衡SLB VPC實例的IP地址,下面開始 2.負載均衡SLB的VPC實例 阿裏雲負載均衡SLB同時提供給了公網實例和

Kubernetes 最佳實踐映射外部服務

password googl 最終 重構 選擇 spec 差異 計算 簡單 文 / 開發技術推廣工程師 Sandeep Dinesh 大多數 Kubernetes 用戶都有可能用到集群外部的服務。例如,您可能使用 Twillio API 發送短信,或使用 Google

分散式儲存系統的最佳實踐系統發展路徑

分散式儲存系統從整體架構的角度看大同小異,實現起來卻困難重重。自主研發的 分散式儲存系統往往需要兩到三年才能逐步成熟起來,其中的難點在於如何把系統做穩定。系統開發過程中涉及架構設計、關鍵演算法實現、質量控制、團隊成員成長、線上運維、應用合作等,任何一個環節出現問題都可能導致整個專案失敗。本文章介紹通用分散式儲

綜評5方面看剛剛釋出的Kubernetes 1.12

    Kubernetes專案在過去幾年中發展迅速,並且作為容器編排和管理解決方案的領導者而備受尊重。有了這個地位,Kubernetes開發者有責任提供經過充分測試,易於維護,高效能和可擴充套件的API和工具。在即將到來的每個釋出週期中,大家都希望繼續看到社群

RubyonRails是WebDev最佳選擇的5原因

90年代,日本軟體工程師松本幸雄(YukihirioMatsumoto)在努力尋找一種功能強大、易於使用的程式語言後,決定自己開發一種程式語言。那時紅寶石1995年首次公開露面。十年後,當DavidHeinemeierHansson建立了RubyonRails並構建了一個自定義的Web框架來加速這個過程時

Android效能最佳實踐為您的APK進行瘦身

大家都知道開發中應用程式的效能是非常重要的,但是這也是優化提升的難點,本章針對 Android效能實踐——從減少APK的大小開始,提升使用者的體驗。 原文地址 https://developer.android.com/topic/performance/reduce-apk-

分散式學習最佳實踐從分散式系統的特徵開始(附思維導圖)

什麼是分散式系統 回到頂部   分散式系統是由一組通過網路進行通訊、為了完成共同的任務而協調工作的計算機節點組成的系統。分散式系統的出現是為了用廉價的、普通的機器完成單個計算機無法完成的計算、儲存任務。其目的是利用更多的機器,處理更多的資料。   首先需要明確的是,只

《TableStore最佳實踐GEO索引打造店鋪搜尋系統》

一、方案背景對於一套GEO管理系統,其核心點與瓶頸在於資料庫的儲存效能與查詢能力;一方面,儲存服務需要應對海量資料的低延遲存、讀,另一方面,儲存服務也要提供高效的GEO+多維度資料檢索。表格儲存(TableStore),作為一款Serverless分散式NoSQL資料庫,完全具備該系統的需求。下面我們將基於T