首先為什么要使用 Docker?
Docker 是一個強大的工具,它允許開發者將他們的應用程序打包到容器中,以便可以在任何平臺上輕松部署和運行。當涉及到對 Spring Boot 應用程序進行 Docker 化時,每個開發人員都應該遵循一些最佳實踐,以確保應用程序平穩高效地運行。
在本文中,我們將探討這些最佳實踐,并提供代碼示例和說明,以幫助您對 Spring Boot 應用程序進行 Docker 化。
作為一個 java 開發者,有很多用于支持 spring-boot 應用程序的基礎官方鏡像,我們需要關注鏡像的大小,特別是當項目變大時。
使用正確的基礎鏡像
當對 Spring Boot 應用程序進行 Docker 化時,為您的應用程序選擇正確的基礎鏡像非常重要。您可能知道 Docker 中的所有鏡像都有 Linux 內核的基礎層,因此我們不需要將這部分添加到我們的鏡像中,因為我們的基礎鏡像提供了您的應用程序所需的底層內核和依賴項。選擇正確的基礎鏡像有助于確保您的應用程序在 Docker 容器中平穩高效地運行。
對于 Spring Boot 應用程序,建議使用 OpenJDK 基礎映像。OpenJDK 是 Java 開發工具包 (JDK) 的開源實現,提供 Java 運行時環境和 Java 開發工具。OpenJDK 基礎映像有不同版本,例如 Java 8、Java 11 和 Java 16。以下是使用 OpenJDK 11 基礎映像的 Dockerfile 示例:
FROM openjdk:17-jdk-slim
COPY target/springBootDockerized-0.0.1-SNAPSHOT.jar springBootDockerized-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java" , "-jar" , "/springBootDockerized-0.0.1-SNAPSHOT.jar"]
但非常重要的是,我們不需要 JDK,我們只需要 JRE java 運行時環境 我建議在 OpenJDK 官方鏈接中使用 JRE 層,您可以找到以下內容:
eclipse-temurin
作為示例 spring-boot 應用程序,添加一個 Dockerfile 到 root,如下所示:
#dockerized 使用 JDK 的不好做法
#FROM openjdk:17-jdk-slim
#COPY target/springBootDockerized-0.0.1-SNAPSHOT.jar springBootDockerized-0.0.1-SNAPSHOT.jar
#ENTRYPOINT ["java" , "-jar" , "/springBootDockerized-0.0.1-SNAPSHOT.jar"]FROM eclipse-temurin:17.0.5_8-jre-focal as builder
WORKDIR extracted
ADD ./target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extractFROM eclipse-temurin:17.0.5_8-jre-focal
WORKDIR application
COPY --from=builder extracted/dependencies/ ./
COPY --from=builder extracted/spring-boot-looder/ ./
COPY --from=builder extracted/snapshot-dependencies/ ./
COPY --from=builder extracted/application/ ./EXPOSE 8085#在 springboot 3.2 之前使用它
#ENTRYPOINT ["java" , "org.springframework.boot.loader.JarLauncher"]
#在 springboot 3.2 之后使用它ENTRYPOINT ["java" , "org.springframework.boot.loader.launch.JarLauncher"]
在此示例中,第一階段使用 Maven 基礎映像來構建 Spring Boot 應用程序并生成 jar 文件。第二階段使用 OpenJDK slim 基礎鏡像,它是基礎鏡像的較小版本,僅包含 Java 運行時環境。
該COPY --from=build
指令將 jar 文件從第一階段復制到第二階段,該ENTRYPOINT
指令指定容器啟動時應該運行的命令。
第一部分指令的含義:
-
java: 這是運行 Java 應用程序或執行 Java 字節碼的命令。
-
-Djarmode=layertools: 這是一個系統屬性,它使用 - D 標志指定。它將 HRIMARMODE 屬性的值設置為更高級的 LayerTools。這是啟用 “layertools” 模式來操作模塊化 JAR 文件中的 “層” 的另一種方法。
-
-jar app.jar: 指定要執行的 JAR 文件名為 “app.jar”。該
-jar
選項指示指定的文件是可執行的 JAR 文件。 -
extract: 這是在 JAR 文件中傳遞給應用程序的參數或命令。它指示應用程序執行特定操作,在本例中是提取 JAR 文件的內容。
通過這種方式使用多階段構建,我們可以創建一個精簡的 Docker 映像,其中僅包含運行 Spring Boot 應用程序所需的依賴項和文件。通過這樣做,我們可以減小圖像的大小并提高應用程序的性能。
另一種方法是使用 Build-pack.io,它會在您的 pom 中自動為您生成圖像,并將其添加到插件標簽中:
<build><plugins><plugin><configuration><image><name>kia/test</name></image></configuration><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>
之后運行此命令:
mvn?spring-boot:build-image
使用這個命令 spring boot 可以完美地為你制作鏡像。
使用環境變量
當對 Spring Boot 應用程序進行 Docker 化時,使用環境變量來配置應用程序非常重要。使用環境變量允許您更改應用程序的配置,而無需重建 Docker 映像。
Spring Boot 應用程序可以使用application.properties
或application.yml
文件來指定配置屬性。這些屬性可以在運行時使用環境變量覆蓋,Spring Boot 會自動將其映射到屬性。下面是一個示例 Dockerfile,它設置一個環境變量來配置 Spring Boot 應用程序的活動配置文件:
FROM openjdk:11
ENV SPRING_PROFILES_ACTIVE=production
COPY target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
在本例中,我們將SPRING_PROFILES_ACTIVE
環境變量設置為生產環境變量,這將激活 Spring Boot 應用程序中的生產配置文件。
當容器啟動時,ENTRYPOINT
指令中指定的 java 命令將與-jar
選項一起運行,以啟動 Spring Boot 應用程序。由于我們設置了SPRING_PROFILES_ACTIVE
環境變量,應用程序將自動使用生產環境。
使用健康檢查
對 Spring Boot 應用程序進行 Docker 化時,使用運行狀況檢查來監控應用程序的運行狀況并確保其正確運行非常重要。健康檢查可用于檢測應用程序何時不健康,并根據應用程序的健康狀況自動執行恢復或擴展。
要在 Docker 映像中添加健康檢查,您可以使用 Dockerfile 中的HEALTHCHECK
指令。HEALTHCHECK
指令告訴 Docker 如何檢查應用程序的運行狀況。下面是一個示例 Dockerfile,它為 Spring Boot 應用程序添加了健康檢查:
FROM openjdk:11
COPY target/my-application.jar app.jar
HEALTHCHECK --interval=5s \--timeout=3s \CMD curl -f http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "/app.jar"]
在此示例中,我們使用HEALTHCHECK
指令來檢查 Spring Boot 應用程序的運行狀況。該--interval
選項指定運行狀況檢查的頻率,以及--timeout
指定等待響應的時間。該CMD
指令運行健康檢查命令,這是 curl 檢查/actuator/health
應用程序端點的命令。
運行容器時,可以使用docker ps
命令查看容器的健康狀態:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8e1a6440e5e my-application:1.0 "java -jar /app.jar" 5 seconds ago Up 4 seconds 0.0.0.0:8080->8080/tcp my-application
$ docker inspect --format='{{json .State.Health}}' my-application
{"Status":"healthy","FailingStreak":0,"Log":[{"Start":"2023-03-25T09:21:08.272130387Z","End":"2023-03-25T09:21:08.310105965Z","ExitCode":0,"Output":"\n"}]}
在此示例中,該docker ps
命令顯示容器已啟動并在端口 8080 上運行。該docker inspect
命令顯示容器的健康狀態,當前為 healthy。如果健康檢查失敗,容器將被標記為 unhealthy,您可以使用 Docker Compose 或 Kubernetes 等工具自動恢復或擴展容器。
使用 Docker 緩存
當對 Spring Boot 應用程序進行 Docker 化時,使用 Docker 緩存來加快構建過程并減少構建新 Docker 映像所需的時間非常重要。Docker 緩存允許您重用之前構建的 Docker 鏡像層,從而避免每次構建新鏡像時都需要重建這些層。下面是一個使用 Docker 緩存來加速構建過程的 Dockerfile 示例:
FROM openjdk:11 as builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offlineCOPY src/ ./src/
RUN mvn package -DskipTestsFROM openjdk:11
COPY --from=builder /app/target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
每一步都假設一個緩存在 Docker 注冊表層的階段,
在此示例中,我們使用多階段構建,首先在單獨的層中構建 Spring Boot 應用程序,然后將構建的 jar 文件復制到最終鏡像中。通過在構建過程中使用單獨的層,我們可以利用 Docker 緩存來避免每次構建新鏡像時重建依賴項。
-
構建過程的第一階段使用
openjdk:11
基礎鏡像并復制 pom.xml 文件到容器。然后它運行mvn dependency:go-offline
命令下載應用程序所需的所有依賴項。該命令確保所有必需的依賴項在本地可用,這將加快后續構建的速度。 -
構建過程的第二階段使用
openjdk:11
基礎映像并將源代碼復制到容器中。然后它運行mvn package
命令來構建應用程序 jar 文件。由于我們在上一階段已經下載了依賴項,因此 Docker 將使用緩存層并跳過依賴項下載步驟。 -
最后,該
COPY --from=builder
指令將構建的 jar 文件從構建器階段復制到最終映像,并且該ENTRYPOINT
指令指定容器啟動時應運行的命令。
使用 .dockerignore 文件
當對 Spring Boot 應用程序進行 Docker 化時,使用.dockerignore
文件從 Docker 構建上下文中排除不必要的文件和目錄非常重要。通過使用.dockerignore
文件,您可以排除 Docker 鏡像不需要的文件和目錄,從而減少構建上下文的大小并提高構建性能。以下是 Spring Boot 應用程序的 .dockerignore
示例文件:
# 忽略根目錄下的所有文件
*
# 包含 src 目錄
!src/
# 包含 pom.xml 文件
!pom.xml
# 排除目標目錄及其內容
target/
在此示例中,我們使用該.dockerignore
文件排除根目錄 (*
) 中的所有文件,除了構建 Spring Boot 應用程序所需的src/
目錄和pom.xml
文件。我們還排除了target/
目錄,該目錄包含構建的工件,Docker 映像不需要該目錄。
通過使用.dockerignore
文件,我們可以減少構建上下文的大小并提高構建性能。Docker 只會復制.dockerignore
構建上下文中包含的文件和目錄,并且會忽略文件中排除的文件和目錄。
使用
.dockerignore
文件是對 Spring Boot 應用程序進行 Docker 化的良好實踐,因為它有助于確保盡可能高效、快速地構建 Docker 映像。
此外,使用.dockerignore
文件還可以幫助提高 Docker 鏡像的安全性。通過排除不必要的文件和目錄,您可以減少 Docker 映像的攻擊面,并最大限度地降低暴露敏感信息或憑據的風險。例如,如果您在構建目錄中存儲了配置文件或憑據,則將它們排除在.dockerignore
文件中將阻止它們包含在 Docker 映像中。
還值得注意的是,該
.dockerignore
文件遵循與.gitignore
文件類似的語法,用于從 Git 存儲庫中排除文件和目錄。如果您熟悉該.gitignore
文件,.dockerignore
文件的使用是零學習成本。
總之,使用.dockerignore
文件是 Docker 化 Spring Boot 應用程序的良好實踐。它可以幫助減少構建上下文的大小、提高構建性能并提高 Docker 映像的安全性。
使用標簽
對 Spring Boot 應用程序進行 Docker 化時,使用標簽將元數據添加到 Docker 映像非常重要。標簽是鍵值對,可以添加到 Docker 映像中以提供有關映像的附加信息,例如版本、維護者或構建日期。下面是一個示例 Dockerfile,它使用標簽將元數據添加到 Spring Boot 應用程序:
FROM openjdk:11
LABEL maintainer="John Doe <john.doe@example.com>"
LABEL version="1.0"
LABEL description="My Spring Boot application"
COPY target/my-application.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
在此示例中,我們使用LABEL
指令將元數據添加到 Docker 映像。我們為鏡像的維護者、版本和描述添加了標簽。這些標簽提供有關 Docker 映像的附加信息,并幫助用戶了解映像包含的內容及其構建方式。
您可以使用docker inspect
命令查看 Docker 鏡像的標簽:
$ docker inspect my-application
[{"Id": "sha256:...","RepoTags": ["my-application:latest"],"Labels": {"maintainer": "John Doe <john.doe@example.com>","version": "1.0","description": "My Spring Boot application"},...}
]
在本例中,docker inspect
命令顯示my-application
Docker 鏡像的標簽。標簽提供有關鏡像的其他信息,可以幫助用戶了解鏡像是如何構建的以及如何使用它。
以這種方式使用標簽可以幫助提高 Docker 鏡像的可用性和可維護性。通過向 Docker 映像添加元數據,您可以幫助用戶了解鏡像包含的內容及其構建方式。隨著時間的推移,此信息對于調試、故障排除和維護 Docker 鏡像非常有用。