Spring Boot 应用的 Docker 化:从 Maven 构建到 Docker 部署的完整指南

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}"]

包含如下基本功能:

  1. 设置时区为Asia/Shanghai
  2. 自动获取 maven 应用包名,不需要额外修改即可使用。
  3. 自动识别 profile 使用的配置文件 不管是 application-dev.yml 、*-test.yml *.prod.yml 都可以识别出来。
  4. 默认暴漏8080端口

以下是它的主要特点和功能:

  1. 基础镜像:使用了 Java 8 我自定义的镜像,你们使用dockerhub 上的就行 的基础镜像,这适用于许多传统的 Java 应用程序。
  2. 时区设置:设置时区为 Asia/Shanghai。这是一个重要的设置,特别是对于需要关注本地时间的应用程序。如果需要,可以轻松更改为其他时区。
  3. 工作目录:在容器内设置了 /app 作为工作目录。
  4. 文件复制:将构建的 Spring Boot 应用 jar 文件以及相关的配置文件(application.ymlapplication-${activatedProperties}.yml)复制到镜像中,自动识别 profile 使用的配置文件 。
  5. 端口暴露:默认暴露了 8080 端口,这是 Spring Boot 应用的常用端口。
  6. Java 虚拟机设置
    • 启用了服务器模式,优化长时间运行的性能。
    • 设置了初始和最大堆大小。
    • 启用了 G1 垃圾收集器,适用于需要更可预测停顿时间和更好性能的应用程序。
    • 配置了在内存溢出时生成堆转储文件,有助于调试内存问题。
  7. 环境变量:允许通过 APP_ENV 命令行的应用 配置项。
  8. 目录创建:创建了用于存储内存转储文件和日志文件的目录。
  9. 启动命令:定义了容器启动时执行的命令,包括 Java 虚拟机参数、日志文件设置和应用 jar 文件的执行。

2. 管理 Docker 容器:简洁高效的脚本方法

管理 Docker 容器有时会显得复杂。为此,我们使用 Bash 脚本来简化这一过程。下面是这个脚本的核心要点:

  1. 安全性优先 - 使用 set -e 确保脚本在出现任何错误时立即停止,防止问题扩散。
  2. 灵活配置 - 通过设置变量 CONTAINER_NAMEIMAGE_NAME,脚本可以灵活适应不同的项目需求,会根据maven打包环境替换
  3. 容器重启 - 如果容器正在运行,脚本会先停止并删除它,然后重新构建和启动,保证环境的干净和更新。
  4. 一键执行 - 无论是构建新镜像还是启动新容器,一切操作都可通过脚本一键完成。

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>
  1. 执行阶段:
    • 插件配置在 process-resources 阶段执行,这是 Maven 生命周期中处理项目资源的标准阶段。
    • goal 设置为 resources,表示插件的主要任务是处理资源。
  2. 资源配置:
    • outputDirectory 设置为 ${project.build.directory},这意味着资源将被复制到 Maven 的构建目录中。
    • <resources>部分,我们定义了要包括的具体资源。
      • directory 指定资源所在的目录,这里是 src/main/resources
      • filtering 设置为 true,允许对资源文件进行过滤处理,这对于包含需要替换的 Maven 属性的文件很有用。
      • includes 标签下,我们明确列出了要包含的文件:Dockerfilerestart.sh

通过这种方式,Maven 在构建过程中会自动将 Dockerfilerestart.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"
动态配置与服务管理
  1. Maven 属性集成:
    • 利用 Maven 属性(如 ${project.build.finalName})实现 Docker 配置与构建过程的紧密集成,使配置动态化和自动化。
  2. 镜像和容器名称:
    • 根据 Maven 构建结果动态生成 imagecontainer_name,保证镜像和容器名称与项目版本一致。
  3. 端口映射:
    • ports 配置将容器内的端口(例如 8080)映射到宿主机,使外部访问成为可能。
数据管理与环境优化
  1. 卷挂载 (volumes):
    • 挂载包括 JAR 文件、配置文件以及日志和转储目录,确保容器可以访问所需的所有文件和数据。
  2. 环境变量 (environment):
    • 设置容器的环境变量,如时区和 Java 运行参数,优化容器的运行环境。
稳定性与日志管理
  1. 自动重启 (restart):
    • 配置容器在退出时自动重启,提高应用的稳定性和可靠性。
  2. 日志配置 (logging):
    • 设置日志驱动和相关选项(例如最大文件大小和数量),帮助有效管理容器日志。

总的来说,这一套 Docker 化的流程不仅降低了部署复杂性,还提升了效率,为在不同环境中部署应用提供了极大便利。这对于追求快速、可靠且一致的软件部署流程的现代开发团队来说,是一种至关重要的实践。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/167032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

堆的实现(C语言版)

文章目录 概述堆的实现初始化销毁插入删除取堆顶元素求堆的长度判断堆是否为空 完整代码 概述 如果有一个关键码的集合K {k0,k1,k2…kn-1}&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足&#xff1a;Ki <K2*i1 且 Ki<K2…

Python Opencv实践 - 全景图片拼接stitcher

做一个全景图片切片的程序Spliter 由于手里没有切割好的全景图片资源&#xff0c;因此首先写了一个切片的程序spliter。 如果有现成的切割好的待拼接的切片文件&#xff0c;则不需要使用spliter。 对于全景图片的拼接&#xff0c;需要注意一点&#xff0c;各个切片图片之间要有…

NX二次开发UF_CSYS_map_point 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_map_point Defined in: uf_csys.h int UF_CSYS_map_point(int input_csys, double input_point [ 3 ] , int output_csys, double output_point [ 3 ] ) overview 概述 Ma…

Android11编译第七弹:串口文件读写

问题&#xff1a;需要对SIM卡进行管理&#xff0c;支持APP切换SIM卡。此功能需要访问串口文件&#xff0c;并且对串口文件进行读写。APP操作串口文件/dev/ttyUSB1时&#xff0c;串口文件打开失败。 2023-11-23 10:59:44.092 14264-14264 MULTI_CARD_SerialHandle com.wellnkio…

三分钟快速理解 ChatGPT 背后的大模型技术

在过去的十年中&#xff0c;人工智能领域取得了重大突破&#xff0c;其中自然语言处理&#xff08;NLP&#xff09;是其重要子领域之一。NLP使用的模型之一是大型语言模型&#xff08;LLMs&#xff09;。LLMs被设计用于处理大量文本数据&#xff0c;采用先进的神经网络架构&…

nodejs 文件目录监听 chokidar watchpack

文件监听实现&#xff0c;推荐使用chokidar&#xff1a; chokidar 默认是基于事件监听文件 const chokidar require("chokidar"); const folderToWatch path.join(__dirname, "lib"); const watcher chokidar.watch(folderToWatch, { ignored: /(^|[…

在Vue中使用Echarts

文章目录 Echarts1. 介绍2. 体验NPM 安装 Echarts定义 Echarts 容器引入 Echarts 3. 基础配置 Echarts 1. 介绍 常见的数据可视化库&#xff1a; D3.js 目前 Web 端评价最高的 Javascript 可视化工具库(入手难)ECharts.js 百度出品的一个开源 Javascript 数据可视化库Highch…

鼠标拖拽问题,不选中文本不触发单击事件

文章目录 1. 为什么鼠标单击的时候触发了mousemove事件&#xff1f;明明鼠标没有移动2. 鼠标拖拽元素怎么能不触发单击事件&#xff1f;怎么处理鼠标在元素内的相对定位&#xff0c;而不是每次定位到左上角&#xff1f;方式一&#xff1a;拖拽的元素没有注册click监听就不会触发…

10年测试老鸟,自动化测试经验10条建议,一路狂飙...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、哪一刻&#x…

Java面试题(每天10题)-------连载(37)

目录 Mysql篇 1、Mysql如何优化DISTINCT&#xff1f; 2、如何输入字符为十六进制数字&#xff1f; 3、如何显示前50行&#xff1f; 4、可以使用多少列创建索引&#xff1f; 5、NOW()和CURRENT_DATE()有什么区别&#xff1f; 6、什么样的对象可以使用CREATE语句创建&…

Postman如何使用(二):Postman Collection的创建/使用/导出分享等

一、什么是Postman Collection&#xff1f; Postman Collection是可让您将各个请求分组在一起。 您可以将这些请求组织到文件夹中。中文经常将collection翻译成收藏夹。如果再下文中看到这样的翻译不要觉得意外。Postman Collection会使你的工作效率更上一层楼。Postman Colle…

【洛谷 B2080】计算多项式的值 题解(顺序结构+四则运算)

计算多项式的值 题目描述 假定多项式的形式为 x n x ( n − 1 ) x^nx^{(n-1)} xnx(n−1) … x 2 x 1 x^2x1 x2x1&#xff0c;请计算给定单精度浮点数 x x x 和正整数 n n n 值的情况下这个多项式的值。多项式的值精确到小数点后两位&#xff0c;保证最终结果在 doub…

NFS 速度变慢问题排查 性能优化

NFS 使用 RPC 来进行客户端和服务器之间的通信。而在 RPC 的底层&#xff0c;NFS 使用 TCP 来进行数据的可靠传输&#xff0c;以便客户端和服务器之间能够有效地传输文件和进行远程调用&#xff08;默认为TCP,也可调整为udp&#xff09; 1.首先服务器端启动RPC服务portmap&…

教师工作就业前景

在这个知识爆炸的时代&#xff0c;当老师无疑是社会发展的重要基石。随着科技的进步和社会的发展&#xff0c;教育行业的需求也在不断增长。那么&#xff0c;教师工作的就业前景如何呢&#xff1f; 我们来看看教师工作的市场需求。随着国家对教育的重视和投入的增加&#xff0c…

C/C++ 实现Socket交互式服务端

在 Windows 操作系统中&#xff0c;原生提供了强大的网络编程支持&#xff0c;允许开发者使用 Socket API 进行网络通信&#xff0c;通过 Socket API&#xff0c;开发者可以创建、连接、发送和接收数据&#xff0c;实现网络通信。本文将深入探讨如何通过调用原生网络 API 实现同…

「Java开发中文指南」IntelliJ IDEA插件安装(一)

IntelliJ IDEA是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的Java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 插件扩展了Intel…

【分布式】分布式中的时钟

一、物理时钟 vs 逻辑时钟 时钟的存在主要是为了标识事件的发生顺序。 分布式系统不使用物理时钟记录事件&#xff0c;分布式系统中每个节点记录的时间并不一样&#xff0c;即使设置了 NTP 时间同步节点间也存在毫秒级别的偏差 所以需要有另外的方法记录事件顺序关系&#x…

vue2中使用echarts

1,安装echarts npm install --save echarts 2&#xff0c;具体页面 <template><div class"app-container"><div class"aa" id"main" style"width: 500px; height: 400px;"></div></div> </te…

PDF 批量处理软件BatchOutput PDF mac中文版介绍

BatchOutput PDF mac是一款适用于 Mac 的 PDF 批量处理软件。它可以帮助用户将多个 PDF 文件进行异步处理&#xff0c;提高工作效率。 BatchOutput PDF 可以自动化执行许多任务&#xff0c;包括 PDF 文件的打印、转换、分割、压缩、加密、重命名等&#xff0c;而且它还可以将自…

Elasticsearch知识

目录 Elasticsearch逻辑设计和物理设计 逻辑设计物理设计Elasticsearch原理 倒排索引文档的分析过程保存文档搜索文档写数据的底层原理 数据刷新&#xff08;fresh&#xff09;事务日志的写入ES在大数据量下的性能优化 文件系统缓存优化数据预热文档&#xff08;Document&…