javascript
容器化 Spring Boot 代码的 9 个技巧
目錄
一、前言
1、為什么容器化 Spring Boot 應用程序很重要?
2、一個簡單的“Hello World”Spring Boot 應用程序
二、容器化 Spring Boot 代碼的 9 個技巧
1、自動化所有手動步驟
2、使用特定的基礎圖像標簽,而不是最新的
3、如果可能,使用 Eclipse Temurin 而不是 JDK
4、 使用多階段構建
5、使用 .dockerignore
6、支持多架構 Docker 鏡像
7、出于安全考慮,以非 root 用戶身份運行
8、修復 Java 映像中的安全漏洞
9、使用 OpenTelemetry API 測量 Java 性能
結論
一、前言
大量開發人員使用 Docker 容器來打包他們的Spring Boot應用程序。根據VMWare 的 2021 年春季狀況報告,運行容器化 Spring 應用程序的組織數量飆升至 57%,而 2020 年為 44%。
是什么推動了這一顯著增長?對減少 Web 應用程序的啟動時間和優化資源使用的需求不斷增長,這極大地提高了開發人員的工作效率。
1、為什么容器化 Spring Boot 應用程序很重要?
在 Docker 容器中運行 Spring Boot 應用程序有很多好處。首先,Docker 友好的、基于 CLI 的工作流程允許開發人員為所有技能水平的其他開發人員構建、共享和運行容器化的 Spring 應用程序。其次,開發人員可以從一個包中安裝他們的應用程序,并在幾分鐘內啟動并運行。第三,Spring 開發者可以在本地編碼和測試,同時保證開發和生產的一致性。
將 Spring Boot 應用程序容器化很容易。您可以通過將.jaror.war文件直接復制到 JDK 基礎映像中,然后將其打包為 Docker 映像來執行此操作。網上有很多文章可以幫助您有效地打包您的應用程序。然而,許多重要的問題,如 Docker 鏡像漏洞、鏡像膨脹、缺少鏡像標簽和糟糕的構建性能都沒有得到解決。我們將解決這些常見問題,同時分享九個容器化 Spring Boot 代碼的技巧。
2、一個簡單的“Hello World”Spring Boot 應用程序
為了更好地理解無人關注的問題,讓我們構建一個示例“Hello World”應用程序。通過下載這個預先初始化的項目并生成一個 ZIP 文件來應用程序。然后解壓縮并完成以下步驟以運行該應用程序。
在該目錄下,您可以使用以下內容src/main/java/com/example/dockerapp/修改您的文件:DockerappApplication.java
package com.example.dockerapp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;@RestController @SpringBootApplication public class DockerappApplication {@RequestMapping("/")public String home() {return "Hello World!";}public static void main(String[] args) {SpringApplication.run(DockerappApplication.class, args);}}以下命令獲取您編譯的代碼并將其打包成可分發的格式,例如 JAR:
./mvnw package java -jar target/*.jar現在,您應該可以通過http://localhost:8080訪問“Hello World” 。
為了 Dockerize 這個應用程序,你需要使用Dockerfile.?ADockerfile是一個文本文檔,其中包含用戶可以在命令行上調用以組裝 Docker 映像的每條指令。一個 Docker 鏡像由一堆層組成,每個層代表Dockerfile.?每個后續層都包含對其底層的更改。
通常,開發人員使用以下Dockerfile模板來構建 Docker 映像。
FROM eclipse-temurin ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app.jar"]第一行定義了大約 457 MB 的基本映像。ARG指令指定可用于COPY指令的? 變量。COPY將JAR 文件從target/文件夾復制到 Docker 映像的根目錄。EXPOSE指令通知 Docker 容器在運行時偵聽指定的網絡端口。最后,ENTRYPOINT允許您配置作為可執行文件運行的容器。它對應于您的命令。java -jar target/*.jar?
您將使用docker build命令構建圖像,如下所示:
$ docker build -t spring-boot-docker . Sending build context to Docker daemon 15.98MB Step 1/5 : FROM eclipse-temurin---a3562aa0b991 Step 2/5 : ARG JAR_FILE=target/*.jar---Running in a8c13e294a66 Removing intermediate container a8c13e294a66---aa039166d524 Step 3/5 : COPY ${JAR_FILE} app.jar COPY failed: no source files were specified上述示例的一個主要缺點是它沒有完全容器化。./mvnw您必須首先通過在主機系統上運行package命令來?創建 JAR 文件。這需要您手動安裝 Java、設置??JAVA_HOME?環境變量并安裝 Maven。簡而言之,你的 JDK 必須駐留在你的 Docker 容器之外——這給你的構建環境增加了更多的復雜性。一定有更好的方法。
二、容器化 Spring Boot 代碼的 9 個技巧
1、自動化所有手動步驟
建議在您自己的構建過程中構建 JAR?Dockerfile。以下RUN說明觸發解決所有項目依賴項的目標,包括插件、報告及其依賴項:
FROM eclipse-temurin WORKDIR /appCOPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offlineCOPY src ./srcCMD ["./mvnw", "spring-boot:run"]💡 避免在編寫 Dockerfile 時手動復制 JAR 文件
2、使用特定的基礎圖像標簽,而不是最新的
在構建 Docker 鏡像時,始終建議指定有用的標簽來編碼版本信息、預期目標(例如產品或測試)、穩定性或其他有用的信息,以便在不同環境中部署應用程序。不要依賴自動創建的latest標簽。使用latest是不可預測的,可能會導致意外行為。每次拉取最新映像時,它都可能包含可能破壞您的應用程序的新版本或未經測試的版本。
例如,使用eclipse-temurin:latestDocker 鏡像作為基礎鏡像并不理想。相反,您應該使用特定的標簽,例如eclipse-temurin:17-jdk-jammy?, eclipse-temurin:8u332-b09-jre-alpin etc.
💡避免FROM eclipse-temurin:latest在你的Dockerfile
3、如果可能,使用 Eclipse Temurin 而不是 JDK
在 OpenJDK?Docker Hub 頁面上,您將找到推薦的 Docker 官方鏡像列表,您應該在構建 Java 應用程序時使用這些鏡像。上游的 OpenJDK 鏡像不再提供 JRE,因此沒有生成官方的 JRE 鏡像。官方 OpenJDK 映像僅包含Oracle或相關項目負責人提供的 OpenJDK 的“香草”版本。
具有構建價值的 JDK 的最受歡迎的官方鏡像之一是 Eclipse Temurin。Eclipse Temurin 項目提供了支持構建運行時二進制文件和相關技術的代碼和流程。這些是高性能、企業級和跨平臺的。
FROM eclipse-temurin:17-jdk-jammyWORKDIR /appCOPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offlineCOPY src ./srcCMD ["./mvnw", "spring-boot:run"]4、 使用多階段構建
通過多階段構建,Docker 構建可以使用一個基礎鏡像進行編譯、打包和單元測試。另一個圖像保存應用程序的運行時。這使得最終圖像更安全且尺寸更小(因為它不包含任何開發或調試工具)。多階段Docker 構建是確保構建 100% 可重復且盡可能精簡的好方法。您可以在 a 中創建多個階段Dockerfile并控制構建該映像的方式。
您可以使用多層方法將 Spring Boot 應用程序容器化。每一層都可能包含應用程序的不同部分,例如依賴項、源代碼、資源,甚至快照依賴項。或者,您可以將任何應用程序構建為與包含可運行應用程序的最終映像不同的映像。為了更好地理解這一點,考慮以下內容Dockerfile:
FROM eclipse-temurin:17-jdk-jammy ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app.jar"]Spring Boot 使用“胖 JAR”作為其默認打包格式。當檢查胖 JAR 時,可以看到應用程序只占整個 JAR 的一小部分。這部分變化最頻繁。其余部分包含 Spring Framework 依賴項。優化通常涉及將應用程序與 Spring Framework 依賴項隔離到一個單獨的層中。您只需下載依賴層(構成胖 JAR 的主體)一次,并將其緩存在主機系統中。
以上Dockerfile假設胖 JAR 已經在命令行上構建。您也可以在 Docker 中使用多階段構建并將結果從一個映像復制到另一個映像來執行此操作。除了使用 Maven 或 Gradle 插件,還可以使用Dockerfile.?在使用 Docker 時,必須再執行兩個步驟來提取圖層并將其復制到最終圖像中。
在第一階段,將提取依賴項。在第二階段,將提取的依賴項復制到最終圖像中:
FROM eclipse-temurin:17-jdk-jammy as builder WORKDIR /opt/app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline COPY ./src ./src RUN ./mvnw clean installFROM eclipse-temurin:17-jre-jammy WORKDIR /opt/app EXPOSE 8080 COPY --from=builder /opt/app/target/*.jar /opt/app/*.jar ENTRYPOINT ["java", "-jar", "/opt/app/*.jar" ]第一個圖像被標記為builder。使用它來運行eclipse-temurin:17-jdk-jammy、構建胖 JAR 并解壓縮它。
請注意,這Dockerfile已分為兩個階段。后面的層包含構建配置和應用程序的源代碼,前面的層包含完整的 Eclipse JDK 映像本身。這個小優化還使免于將target目錄復制到 Docker 映像——甚至是用于構建的臨時映像。與第一階段構建的 450MB 大小相比,最終圖像只有 277 MB。
5、使用 .dockerignore
為了提高構建性能,建議.dockerignore在您的Dockerfile.?對于本教程,您的.dockerignore文件應該只包含一行:
target此行從 Docker 構建上下文中排除了包含來自 Maven 的輸出的目標目錄。仔細構建文件有很多充分的理由.dockerignore,但這個簡單的文件現在已經足夠了。現在解釋它build context以及為什么它是必要的。該命令從一個和一個“上下文”docker build構建 Docker 映像。Dockerfile此上下文是位于您指定的 PATH 或 URL 中的文件集。構建過程可以引用任何這些文件。
同時,編譯上下文是開發人員工作的地方。它可以是 Mac、Windows 或 Linux 目錄上的文件夾。該目錄包含所有必要的應用程序組件,如源代碼、配置文件、庫和插件。通過該.dockerignore文件,可以確定在構建新映像時要排除以下哪些元素,例如源代碼、配置文件、庫、插件等。
.dockerignore如果您選擇從構建中排除conf、libraries和,您的文件可能如下所示:plugins directory
6、支持多架構 Docker 鏡像
您的 CPU 只能運行其本機架構的二進制文件。例如,為 x86 系統構建的 Docker 映像無法在基于 Arm 的系統上運行。隨著 Apple 完全過渡到其定制的基于 Arm 的芯片,您的 x86(英特爾或 AMD)Docker 映像可能無法與 Apple 最近的 M 系列芯片一起使用。因此,始終建議構建多架構容器映像。下面是mplatform/mqueryDocker 鏡像,可讓您在任何公共注冊表中查詢任何公共鏡像的多平臺狀態:
docker run --rm mplatform/mquery eclipse-temurin:17-jre-alpine Image: eclipse-temurin:17-jre-alpine (digest: sha256:ac423a0315c490d3bc1444901d96eea7013e838bcf7cc09978cf84332d7afc76)* Manifest List: Yes (Image type: application/vnd.docker.distribution.manifest.list.v2+json)* Supported platforms:- linux/amd64
這里介紹了docker buildx幫助您構建多架構映像的命令。Buildx是一個 Docker 組件,它支持許多強大的構建功能和熟悉的 Docker 用戶體驗。通過 Buildx 執行的所有構建都通過Moby BuildKit構建器引擎運行。BuildKit 旨在擅長多平臺構建,或者不僅僅是針對用戶本地平臺的構建。當您調用構建時,您可以設置--platform標志來指定構建輸出的目標平臺,(如linux/amd64、linux/arm64或darwin/amd64):
7、出于安全考慮,以非 root 用戶身份運行
以用戶權限運行應用程序更安全,因為它有助于降低風險。這同樣適用于 Docker 容器。默認情況下,Docker 容器及其運行的應用程序具有 root 權限。因此,最好以非 root 用戶身份運行 Docker 容器。您可以通過USER在Dockerfile.?該USER指令在運行映像時設置首選用戶名(或 UID)和可選的用戶組(或 GID) - 以及任何后續RUN、CMD或ENTRYPOINT指令:
FROM eclipse-temurin:17-jdk-alpine RUN addgroup demogroup; adduser --ingroup demogroup --disabled-password demo USER demoWORKDIR /appCOPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offlineCOPY src ./srcCMD ["./mvnw", "spring-boot:run"]8、修復 Java 映像中的安全漏洞
今天的開發人員在構建他們的服務時依賴第三方代碼和應用程??序。不小心使用外部軟件,您的代碼可能更容易受到攻擊。利用受信任的圖像并持續監控您的容器對于解決這個問題至關重要。每當您構建“Hello World”Docker 映像時,Docker Desktop 都會提示您運行映像的安全掃描以檢測任何已知漏洞,例如 Log4Shell:
exporting to image 0.0s== exporting layers 0.0s== writing image sha256:cf6d952a1ece4eddcb80c8d29e0c5dd4d3531c1268291 0.0s== naming to docker.io/library/spring-boot1 0.0sUse 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them使用Snyk Extension for Docker Desktop來檢查Spring Boot 應用程序。首先,在您的Mac、Windows或Linux機器上安裝Docker Desktop 4.8.0+并啟用擴展市場。
Snyk 的擴展允許您快速掃描本地和遠程 Docker 映像以檢測漏洞。
安裝Snyk擴展并提供“Hello World”Docker 鏡像。
Snyk 的工具發現了 70 個不同嚴重程度的漏洞。一旦你意識到這些,你就可以開始修復以激發你的形象。
💡 為了執行漏洞檢查,您可以直接對 : 使用以下命令Dockerfile:docker scan -f Dockerfile spring-helloworld
?
9、使用 OpenTelemetry API 測量 Java 性能
Spring Boot 開發人員如何確保他們的應用程序更快、更高效?通常,開發人員依靠第三方可觀察性工具來衡量其 Java 應用程序的性能。應用程序性能監控對于所有類型的 Java 應用程序都是必不可少的,開發人員必須創造一流的用戶體驗。
可觀察性不僅限于應用程序性能。隨著微服務架構的興起,可觀察性的三大支柱——指標、跟蹤和日志——是前沿和中心。指標可幫助開發人員了解系統出了什么問題,而跟蹤可幫助您發現問題所在。日志會告訴您錯誤的原因,讓開發人員深入研究特定指標或跟蹤以全面了解系統行為。
觀察 Java 應用程序需要通過 JMX、底層主機指標和 Java 應用程序跟蹤來監控您的 Java VM 指標。Java 開發人員應使用Java OpenTelemetry API監控、分析和診斷應用程序性能。OpenTelemetry 提供一組 API、庫、代理和收集器服務,以從您的應用程序中捕獲分布式跟蹤和指標。
結論
在這篇博文中,您看到了通過精心制作 Dockerfile 并使用 Snyk Docker Extension Marketplace 保護您的鏡像來優化 Docker 鏡像的許多方法。
總結
以上是生活随笔為你收集整理的容器化 Spring Boot 代码的 9 个技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用fastcoll生成字符串MD5碰撞
- 下一篇: 豌豆荚市场上一些主流应用的支持版本