1. 使用Dockerfile部署
# 使用Java 8基礎鏡像
FROM java:8
LABEL authors="mabh"# 設置時區為Asia/Shanghai,可以根據需要更改
ENV TIME_ZONE=Asia/Shanghai# 更新時區
RUN ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone# 設置容器內的工作目錄
WORKDIR /app# 將構建好的Spring Boot應用jar文件復制到鏡像中
COPY ./${project.build.finalName}.jar /app/COPY ./application.yml /app/
COPY ./application-${activatedProperties}.yml /app/# 暴露端口
EXPOSE 8080# 設置Java虛擬機初始內存和最大內存
#-server: 啟用Java HotSpot虛擬機的服務器模式,該模式針對長時間運行的應用程序進行了優化以提高性能。
#-Xms512m: 設置Java堆的初始大小為512兆字節。
#-Xmx1024m: 設置Java堆的最大大小為1024兆字節。
#-XX:+UseG1GC: 啟用G1垃圾收集器。G1(Garbage-First)是一種相對新的垃圾收集器,旨在提供更可預測的停頓時間和更好的性能。
#-XX:+HeapDumpOnOutOfMemoryError: 在發生內存溢出錯誤時生成堆轉儲文件。這對于分析內存問題非常有用。
#-XX:HeapDumpPath=/dumps/oom_dump.hprof: 指定內存轉儲文件。在這個例子中,堆轉儲文件將被寫入 /dumps/oom_dump.hprof 目錄文件中。
ENV JAVA_OPTS="-server -Xms512m -Xmx1024m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps/oom_dump.hprof"ENV APP_ENV="--spring.profiles.active=${activatedProperties}"
# 創建內存轉儲文件和日志文件存儲目錄
RUN mkdir /app/dumps
RUN mkdir /app/logs# 設置容器啟動時執行的命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dlogging.file=/app/logs/application.log -jar /app/${project.build.finalName}.jar ${APP_ENV}"]
包含如下基本功能:
- 設置時區為Asia/Shanghai
- 自動獲取 maven 應用包名,不需要額外修改即可使用。
- 自動識別 profile 使用的配置文件 不管是 application-dev.yml 、*-test.yml *.prod.yml 都可以識別出來。
- 默認暴漏8080端口
以下是它的主要特點和功能:
- 基礎鏡像:使用了
Java 8
我自定義的鏡像,你們使用dockerhub 上的就行 的基礎鏡像,這適用于許多傳統的 Java 應用程序。 - 時區設置:設置時區為
Asia/Shanghai
。這是一個重要的設置,特別是對于需要關注本地時間的應用程序。如果需要,可以輕松更改為其他時區。 - 工作目錄:在容器內設置了
/app
作為工作目錄。 - 文件復制:將構建的 Spring Boot 應用 jar 文件以及相關的配置文件(
application.yml
和application-${activatedProperties}.yml
)復制到鏡像中,自動識別 profile 使用的配置文件 。 - 端口暴露:默認暴露了 8080 端口,這是 Spring Boot 應用的常用端口。
- Java 虛擬機設置:
- 啟用了服務器模式,優化長時間運行的性能。
- 設置了初始和最大堆大小。
- 啟用了 G1 垃圾收集器,適用于需要更可預測停頓時間和更好性能的應用程序。
- 配置了在內存溢出時生成堆轉儲文件,有助于調試內存問題。
- 環境變量:允許通過
APP_ENV
命令行的應用 配置項。 - 目錄創建:創建了用于存儲內存轉儲文件和日志文件的目錄。
- 啟動命令:定義了容器啟動時執行的命令,包括 Java 虛擬機參數、日志文件設置和應用 jar 文件的執行。
2. 管理 Docker 容器:簡潔高效的腳本方法
管理 Docker 容器有時會顯得復雜。為此,我們使用 Bash 腳本來簡化這一過程。下面是這個腳本的核心要點:
- 安全性優先 - 使用
set -e
確保腳本在出現任何錯誤時立即停止,防止問題擴散。 - 靈活配置 - 通過設置變量
CONTAINER_NAME
和IMAGE_NAME
,腳本可以靈活適應不同的項目需求,會根據maven打包環境替換 - 容器重啟 - 如果容器正在運行,腳本會先停止并刪除它,然后重新構建和啟動,保證環境的干凈和更新。
- 一鍵執行 - 無論是構建新鏡像還是啟動新容器,一切操作都可通過腳本一鍵完成。
restart.sh
#!/bin/bash# 設置腳本在遇到錯誤時立即退出
set -e# 設置容器名稱和鏡像名稱
CONTAINER_NAME="${project.build.finalName}"
IMAGE_NAME="${project.build.finalName}:1.0.0"# 檢查容器是否存在并獲取其運行狀態
running=$(docker inspect --format="{{ .State.Running }}" "${CONTAINER_NAME}" 2>/dev/null || true)# 停止并刪除正在運行的容器
if [ "$running" == "true" ]; thenecho "Stopping running container..."docker stop "${CONTAINER_NAME}"echo "Removing stopped container..."docker rm -f "${CONTAINER_NAME}"
fi# 如果容器不存在或已停止,重新構建并啟動容器
if [ "$running" != "true" ]; then# docker load -i java8.tarecho "Building new image..."docker build -t "${IMAGE_NAME}" .echo "Starting new container..."docker run -d --name "${CONTAINER_NAME}" \--cap-add=SYS_PTRACE \-p 8080:8080 \-v "$(pwd)/dumps:/app/dumps" \-v "$(pwd)/logs:/app/logs" \"${IMAGE_NAME}"echo "Container has been restarted."
fi
docker load -i java8.tar
這一步對于下面Docker-Compose 可能是需要的。
3. 集成 Docker 管理腳本與 Maven:完善構建流程
要將前面提到的 Docker 管理腳本(restart.sh
)以及 Dockerfile 與 Maven 打包工具集成,我們可以利用 Maven 的 maven-resources-plugin
插件。這個插件允許我們在 Maven 的構建過程中復制和處理資源文件。下面是如何配置這個插件,以及它在整個過程中的作用:
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>3.2.0</version><executions><execution><phase>process-resources</phase><goals><goal>resources</goal></goals><configuration><outputDirectory>${project.build.directory}</outputDirectory><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>Dockerfile</include><include>restart.sh</include></includes></resource></resources></configuration></execution></executions>
</plugin>
如果你看過
動態切換 Spring Boot 打包配置:使用 Maven Profiles 管理 JAR 和 WAR
可以跟 profile 結合起來,只有jar包的的時候才用Docker
<profiles><profile><id>jar</id><activation><activeByDefault>true</activeByDefault></activation><properties><packaging.type>jar</packaging.type></properties><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>3.2.0</version><executions><execution><phase>process-resources</phase><goals><goal>resources</goal></goals><configuration><outputDirectory>${project.build.directory}</outputDirectory><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>Dockerfile</include><include>restart.sh</include></includes></resource></resources></configuration></execution></executions></plugin></plugins></build></profile> </profiles>
- 執行階段:
- 插件配置在
process-resources
階段執行,這是 Maven 生命周期中處理項目資源的標準階段。 goal
設置為resources
,表示插件的主要任務是處理資源。
- 插件配置在
- 資源配置:
outputDirectory
設置為${project.build.directory}
,這意味著資源將被復制到 Maven 的構建目錄中。- 在
<resources>
部分,我們定義了要包括的具體資源。directory
指定資源所在的目錄,這里是src/main/resources
。filtering
設置為true
,允許對資源文件進行過濾處理,這對于包含需要替換的 Maven 屬性的文件很有用。includes
標簽下,我們明確列出了要包含的文件:Dockerfile
和restart.sh
。
通過這種方式,Maven 在構建過程中會自動將 Dockerfile
和 restart.sh
腳本復制到指定的輸出目錄。這樣做的好處是,你可以確保在最終的發版物中包含了這些對于部署和管理 Docker 容器至關重要的文件,實現了項目的一體化管理。
4. 從 Dockerfile 到 Docker-Compose:簡化和自動化應用部署
version: '2'services:${project.build.finalName}: # 使用 Dockerfile 中定義的項目名作為服務名稱image: ${project.build.finalName}:1.0.0 # 使用 Dockerfile 中定義的鏡像名和標簽container_name: ${project.build.finalName} # 容器名稱也使用同樣的命名ports:- "8080:8080" # 暴露的端口volumes:- ./${project.build.finalName}.jar:/app/${project.build.finalName}.jar # 掛載 JAR 文件- ./application.yml:/app/application.yml # 掛載配置文件- ./application-${activatedProperties}.yml:/app/application-${activatedProperties}.yml # 掛載特定環境的配置文件- ./dumps:/app/dumps # 掛載內存轉儲目錄- ./logs:/app/logs # 掛載日志目錄environment:- TIME_ZONE=Asia/Shanghai # 設置時區- JAVA_OPTS=-server -Xms512m -Xmx1024m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps/oom_dump.hprof- APP_ENV=-Dapp.log.serviceName=${project.build.finalName} --spring.profiles.active=${activatedProperties}restart: always # 設置容器總是自動重啟logging:driver: json-fileoptions:max-size: "20m"max-file: "1"
動態配置與服務管理
- Maven 屬性集成:
- 利用 Maven 屬性(如
${project.build.finalName}
)實現 Docker 配置與構建過程的緊密集成,使配置動態化和自動化。
- 利用 Maven 屬性(如
- 鏡像和容器名稱:
- 根據 Maven 構建結果動態生成
image
和container_name
,保證鏡像和容器名稱與項目版本一致。
- 根據 Maven 構建結果動態生成
- 端口映射:
ports
配置將容器內的端口(例如 8080)映射到宿主機,使外部訪問成為可能。
數據管理與環境優化
- 卷掛載 (
volumes
):- 掛載包括 JAR 文件、配置文件以及日志和轉儲目錄,確保容器可以訪問所需的所有文件和數據。
- 環境變量 (
environment
):- 設置容器的環境變量,如時區和 Java 運行參數,優化容器的運行環境。
穩定性與日志管理
- 自動重啟 (
restart
):- 配置容器在退出時自動重啟,提高應用的穩定性和可靠性。
- 日志配置 (
logging
):- 設置日志驅動和相關選項(例如最大文件大小和數量),幫助有效管理容器日志。
總的來說,這一套 Docker 化的流程不僅降低了部署復雜性,還提升了效率,為在不同環境中部署應用提供了極大便利。這對于追求快速、可靠且一致的軟件部署流程的現代開發團隊來說,是一種至關重要的實踐。