国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

最小化 Java 鏡像的常用技巧

MudOnTire / 2385人閱讀

摘要:本文將介紹精簡容器鏡像的必要性并以基于的應用為例描述最小化容器鏡像的常用技巧。經過這一優化,最終鏡像的大小為。

背景

隨著容器技術的普及,越來越多的應用被容器化。人們使用容器的頻率越來越高,但常常忽略一個基本但又非常重要的問題 - 容器鏡像的體積。本文將介紹精簡容器鏡像的必要性并以基于 spring boot 的 java 應用為例描述最小化容器鏡像的常用技巧。

精簡容器鏡像的必要性

精簡容器鏡像是非常必要的,下面分別從安全性和敏捷性兩個角度進行闡釋。

安全性

基于安全方面的考慮,將不必要的組件從鏡像中移除可以減少攻擊面、降低安全風險。雖然 docker 支持用戶通過?Seccomp?限制容器內可以執行操作或者使用?AppArmor?為容器配置安全策略,但它們的使用門檻較高,要求用戶具備安全領域的專業素養。

敏捷性

精簡的容器鏡像能提高容器的部署速度。假設某一時刻訪問流量激增,您需要通過增加容器副本數以應對突發壓力。如果某些宿主機不包含目標鏡像,需要先拉取鏡像,然后啟動容器,這時使用體積較小的鏡像能加速這一過程、縮短擴容時間。另外,鏡像體積越小,其構建速度也越快,同時還能減少存儲和傳輸的成本。

常用技巧

將一個 java 應用容器化所需的步驟可歸納如下:

編譯 java 源碼并生成 jar 包。

將應用 jar 包和依賴的第三方 jar 包移動到合適的位置。

本章所用的樣例是一個基于 spring boot 的 java 應用?spring-boot-docker,所用的未經優化的?dockerfile?如下:

FROM maven:3.5-jdk-8
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
RUN mvn -f /usr/src/app/pom.xml clean package
ENTRYPOINT ["java","-jar","/usr/src/app/target/spring-boot-docker-1.0.0.jar"]

由于應用使用 maven 構建,dockerfile 中指定maven:3.5-jdk-8作為基礎鏡像,該鏡像的大小為 635MB。通過這種方式最終構建出的鏡像非常大,達到了 719MB,這是因為一方面基礎鏡像本身就很大,另一方面 maven 在構建過程中會下載許多用于執行構建任務的 jar 包。

多階段構建

Java 程序的運行只依賴 JRE,并不需要 maven 或者 JDK 中眾多用于編譯、調試、運行的工具,因此一個明顯的優化方法是將用于編譯構建 java 源碼的鏡像和用于運行 java 應用的鏡像分開。為了達到這一目的,在 docker 17.05 版本之前需要用戶維護 2 個 dockerfile 文件,這無疑增加了構建的復雜性。好在自 17.05 開始,docker 引入了多階段構建的概念,它允許用戶在一個 dockerfile 中使用多個 From 語句。每個 From 語句可以指定不同的基礎鏡像并將開啟一個全新的構建流程。您可以選擇性地將前一階段的構建產物復制到另一個階段,從而只將必要的內容保留在最終的鏡像里。優化后的?dockerfile?如下:

FROM maven:3.5-jdk-8 AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
RUN mvn -f /usr/src/app/pom.xml clean package

FROM openjdk:8-jre
ARG DEPENDENCY=/usr/src/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

該 dockerfile 選用maven:3.5-jdk-8作為第一階段的構建鏡像,選用openjdk:8-jre作為運行 java 應用的基礎鏡像并且只拷貝了第一階段編譯好的.claass文件和依賴的第三方 jar 包到最終的鏡像里。通過這種方式優化后的鏡像大小為 459MB。

使用 distroless 作為基礎鏡像

雖然通過多階段構建能減小最終生成的鏡像的大小,但 459MB 的體積仍相對過大。經調查發現,這是因為使用的基礎鏡像openjdk:8-jre體積過大,到達了 443MB,因此下一步的優化方向是減小基礎鏡像的體積。

Google 開源的項目?distroless?正是為了解決基礎鏡像體積過大這一問題。Distroless 鏡像只包含應用程序及其運行時依賴項,不包含包管理器、shell 以及在標準 Linux 發行版中可以找到的任何其他程序。目前,distroless 為依賴?java、python、nodejs、dotnet?等環境的應用提供了基礎鏡像。

使用 distroless 的?dockerfile?如下:

FROM maven:3.5-jdk-8 AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java
ARG DEPENDENCY=/usr/src/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

該 dockerfile 和上一版的唯一區別在于將運行階段依賴的基礎鏡像由openjdk:8-jre(443 MB)替換成了gcr.io/distroless/java(119 MB)。經過這一優化,最終鏡像的大小為 135MB。

使用 distroless 的唯一不便是您無法 attach 到一個正在運行的容器上排查問題,因為鏡像中不包含 shell。雖然 distroless 的?debug 鏡像提供 busybox shell,但需要用戶重新打包鏡像、部署容器,對于那些已經基于非 debug 鏡像部署的容器無濟于事。 但從安全角度來看,無法 attach 容器并不完全是壞事,因為攻擊者無法通過 shell 進行攻擊。

使用 alpine 作為基礎鏡像

如果您確實有 attach 容器的需求,又希望最小化鏡像的大小,可以選用?alpine?作為基礎鏡像。Alpine 鏡像的特點是體積非常下,基礎款鏡像的體積僅 4 MB 左右。

使用 alpine 后的?dockerfile?如下:

FROM maven:3.5-jdk-8 AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
RUN mvn -f /usr/src/app/pom.xml clean package

FROM openjdk:8-jre-alpine
ARG DEPENDENCY=/usr/src/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

這里并未直接繼承基礎款 alpine,而是選用從 alpine 構建出的包含 java 運行時的openjdk:8-jre-alpine(83MB)作為基礎鏡像。使用該 dockerfile 構建出的鏡像體積為 99.2MB,比基于 distroless 的還要小。

執行命令docker exec -ti sh可以成功 attach 到運行的容器中。

distroless vs alpine

既然 distroless 和 alpine 都能提供非常小的基礎鏡像,那么在生產環境中到底應該選擇哪一種呢?如果安全性是您的首要考慮因素,建議選用 distroless,因為它唯一可運行的二進制文件就是您打包的應用;如果您更關注鏡像的體積,可以選用 alpine。

其他技巧

除了可以通過上述技巧精簡鏡像外,還有以下方式:

將 dockerfile 中的多條指令合并成一條,通過減少鏡像層數的方式達到精簡鏡像體積的目的。

將穩定且體積較大的內容置于鏡像下層,將變動頻繁且體積較小的內容置于鏡像上層。雖然該方式無法直接精簡鏡像體積,但充分利用了鏡像的緩存機制,同樣可以達到加快鏡像構建和容器部署的目的。

想了解更多優化 dockerfile 的小竅門可參考教程?Best practices for writing Dockerfiles。

總結

本文通過一系列的優化,將 java 應用的鏡像體積由最初的 719MB 縮小到 100MB 左右。如果您的應用依賴其他環境,也可以用類似的原則進行優化。

針對 java 鏡像,google 提供的另一款工具?jib?能為您屏蔽鏡像構建過程中的復雜細節,自動構建出精簡的 java 鏡像。使用它您無須編寫 dockerfile,甚至不需要安裝 docker。

對于類似 distroless 這樣無法 attach 或者不方便 attach 的容器,建議您將它們的日志中心化存儲,以便問題的追蹤和排查。具體方法可參考文章面向容器日志的技術實踐。



本文作者:吳波bruce_wu

閱讀原文

本文為云棲社區原創內容,未經允許不得轉載。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11444.html

相關文章

  • 在 Docker 中使用 mysql 一些技巧

    摘要:今天我寫一點在容器中使用的要不要在生產環境使用運行數據庫這么深奧的問題,等我踩足夠的坑再來寫吧。這是日常使用的狀態,此處省略了別的服務。初始化容器在首次啟動的時候,必須指定一個密碼才能啟動,指定的方式是聲明環境變量。 今天我寫一點在 Docker 容器中使用 MYSQL 的 tips.要不要在生產環境使用 Docker 運行數據庫這么深奧的問題,等我踩足夠的坑再來寫吧。但是至少在開發和...

    617035918 評論0 收藏0
  • 都9102年了,還不會Docker?10分鐘帶你從入門操作到實戰上手

    摘要:聯調測試,無需依賴他人。針對以上問題,有兩種解決方法,一個是自己搭建私有服務,另一個是用云服務的鏡像管理平臺如阿里云的容器鏡像服務。利用,先對阿里云的服務進行登錄。推送后,就能在阿里云的倉庫上看到這個鏡像。 Docker簡述 Docker是一種OS虛擬化技術,是一個開源的應用容器引擎。它可以讓開發者將應用打包到一個可移植的容器中,并且該容器可以運行在幾乎所有linux系統中(Windo...

    sf_wangchong 評論0 收藏0
  • 后端好書閱讀與推薦(續)

    摘要:續前文后端好書閱讀與推薦,幾十天過去了,又看了兩本好書還有以前看過的書,這里依然把它們總結歸納一下,加入一些自己的看法有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。 續前文 后端好書閱讀與推薦 - Mageek`s Wonderland ,幾十天過去了,又看了兩本好書(還有以前看過的書),這里依然把它們總結歸納一下,加入一些自己的看法、有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。...

    劉福 評論0 收藏0
  • 后端好書閱讀與推薦(續)

    摘要:續前文后端好書閱讀與推薦,幾十天過去了,又看了兩本好書還有以前看過的書,這里依然把它們總結歸納一下,加入一些自己的看法有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。 續前文 后端好書閱讀與推薦 - Mageek`s Wonderland ,幾十天過去了,又看了兩本好書(還有以前看過的書),這里依然把它們總結歸納一下,加入一些自己的看法、有用的鏈接和可能的延伸閱讀,并推薦給需要的同學。...

    OnlyLing 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<