如何利用docker部署springboot应用
目录
- 前言
- 构建jar包
- 可执行Fat jar组成结构
- 构建springboot应用镜像
- docker容器化部署
- 验证部署
前言
在这篇博客中,我将分享如何在Linux环境下通过Docker部署SpringBoot项目。主要内容包括:
- 正确构建JAR包及其组成结构
- 使用Dockerfile构建镜像
- 通过Docker容器进行项目部署
对docker不熟悉的朋友可以看我这篇博客docker
构建jar包
-
目前Boot项目通常通过IntelliJ IDEA和Maven进行构建。在打包时,我们可以在IDEA右侧Maven面板的生命周期中直接执行package命令。需要注意的是,Maven默认的打包方式会生成一个仅包含项目自身代码的标准JAR包,该包不包含项目依赖的第三方库,因此无法直接运行。
-
boot项目,我们一般会构建可以直接运行、包含所有依赖的jar包,可以直接在pom文件中添加一下配置,指定
spring-boot-maven-plugin
插件作为jar包构建的工具。<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.msun.hospitaldictmapping.MsunHospitaldictMappingApplication</mainClass></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins> </build>
-
上述配置有两个关键配置的作用如下:
配置项 作用说明 <mainClass> 指定 Spring Boot 应用的入口主类,即包含 main方法的类。repackage目标会将它写入 MANIFEST.MF 文件的 Start-Class属性 <goal>repackage</goal> 插件的核心目标。它会在 Maven 默认打包后,将原始的普通 JAR 包重新打包为包含所有依赖的可执行jar包 -
配置好
spring-boot-maven-plugin
这个插件后,我们现在执行package指令,Spring Boot Maven 插件会按照以下步骤工作
4.1 Maven 默认打包:首先,Maven 的 maven-jar-plugin会执行,生成一个普通的、只包含你项目自身编译代码的 JAR 包(通常被命名为 your-app-version.jar.original)。
4.2 Repackage(重新打包):接着,spring-boot-maven-plugin
的 repackage目标会启动。它会将这个普通的 JAR 包和所有依赖的第三方库(来自你的本地 Maven 仓库)一起,重新打包成一个特殊的 Fat JAR(即可执行 JAR),并覆盖掉最初生成的那个 JAR 文件
可执行Fat jar组成结构
-
一个典型的Spring Boot Fat JAR解压后,我们会看到类似这样的结构
myapp-1.0.jar ├─ BOOT-INF/ │ ├─ classes/ # 你的应用类文件 (.class) 和资源文件 (如 application.yml) │ └─ lib/ # 所有的第三方依赖 JAR 文件 ├─ META-INF/ │ └─ MANIFEST.MF # 清单文件,这是启动的关键 └─ org/└─ springframework/boot/loader/ # Spring Boot 的启动器类 (如 JarLauncher)
-
下面表格详细展示了这些内部结构存放的文件内容
目录 存放内容 BOOT-INF/classes/ 存放我们项目的编译类文件和资源文件 BOOT-INF/lib/ 存放所有依赖的 JAR 文件 org/springframework/boot/loader/ 存放 Spring Boot 自定义的类加载器(如 JarLauncher) META-INF/MANIFEST.MF 清单文件,其中关键属性 Main-Class指向 类加载器org.springframework.boot.loader.JarLauncher,而 Start-Class指向我们的 com.msun…Application启动类 -
这样,当我们运行 java -jar your-app.jar时,JVM 会首先启动 JarLauncher类加载器,由它负责加载 BOOT-INF/lib下的所有依赖和 BOOT-INF/classes下的应用代码,最后通过反射调用 Start-Class指定的Application启动类 main方法
构建springboot应用镜像
打好项目jar包后,接下来我们构建应用的docker镜像
-
首先,将 Spring Boot JAR 包(例如 myapp.jar)上传到 Linux 服务器的某个目录,比如 /home/project。然后在该目录下创建 Dockerfile文件。
# 进入你存放JAR包的目录 cd /home/project # 创建Dockerfile touch Dockerfile
-
编写 Dockerfile 文件,构建boot应用镜像“图纸”,将your-project-name.jar替换为我们的实际jar包名称即可,注意,要将你的jar包放到Dockerfile同级目录下
# 使用一个轻量级的Java运行环境作为基础镜像 FROM openjdk:8-jre-slim# 在镜像内设置一个工作目录,影响run/cmd/copy等指令 WORKDIR /app# 将宿主机的JAR包复制到镜像的工作目录中。注意替换JAR包文件名。由于设置了工作目录,实际复制到/app/app.jar COPY your-project-name.jar app.jar # 声明容器运行时需要暴露的端口(与你的Spring Boot应用端口一致) EXPOSE 8080# 指定容器启动时运行的命令 ENTRYPOINT ["java", "-jar", "app.jar"]
openjdk:8-jre-slim就是一个专为运行Java程序而优化的、轻量且高效的java程序运行的基础镜像,提供了java程序运行所需的最小环境,包含了一个非常轻量级的Linux发行版-Debian的“slim”系统、java8运行时环境,即 OpenJDK 8的JRE(JVM+核心类库)
-
最后,执行下面docker命令构建我们的boot应用镜像。
docker build -t 镜像名称 .
注意后面有个.,意思是从当前目录寻找Dockerfile文件,构建镜像。
执行命令后,如果控制台最后出现success标识,说明镜像分层构建成功
此时,我们执行docker images
就可以看到我们创建的镜像
docker容器化部署
-
镜像构建完成后,我们直接通过docker进行容器化部署即可,直接使用 docker run命令启动一个容器来启动应用
docker run -d \ # -d:让容器在后台以"分离模式"运行 -p 8080:8080 \ # -p 8080:8080:将宿主机的8080端口映射到容器的8080端口。如果你的应用端口不是8080,请相应调整 --name my-app-container\ # 为容器指定名称 my-spring-boot-app:1.0 # 我们的应用镜像名称
这里要注意的是,最后指定的镜像名称,我们可以通过
docker images
查询,创建容器时指定镜像名称格式为repository:tag,以下面这个截图为例,镜像名称就是drug_test:latest
验证部署
容器启动后,可以通过以下方式验证应用是否成功运行:
- 查看容器状态:使用
docker ps
命令查看容器是否在运行 - 查看日志:如果应用无法访问,使用
docker logs -f 容器名
命令查看启动日志,这通常是排查问题最快的方法