MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Java Spring Boot与Docker的结合应用

2021-08-072.4k 阅读

Java Spring Boot基础概述

Spring Boot简介

Spring Boot是由Pivotal团队提供的全新框架,它基于Spring框架,目的是简化Spring应用的初始搭建以及开发过程。它遵循“约定大于配置”(Convention over Configuration)的原则,使得开发者能够快速地创建基于Spring的独立、生产级别的应用程序。Spring Boot内嵌了诸如Tomcat、Jetty等Servlet容器,这意味着可以将Spring Boot应用打包成一个可执行的JAR或WAR文件,直接通过Java命令来运行,而无需手动部署到外部的应用服务器。

例如,一个简单的Spring Boot Hello World应用:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class HelloWorldApplication {

    @GetMapping("/")
    public String hello() {
        return "Hello, World!";
    }

    public static void main(String[] args) {
        SpringApplication.run(HelloWorldApplication.class, args);
    }
}

在上述代码中,@SpringBootApplication注解开启了Spring Boot的自动配置,@RestController注解表明该类是一个RESTful风格的控制器。@GetMapping("/")映射了根路径的HTTP GET请求到hello方法,该方法返回“Hello, World!”字符串。main方法通过SpringApplication.run启动Spring Boot应用。

Spring Boot核心特性

  1. 自动配置:Spring Boot能根据项目中引入的依赖自动配置Spring应用。比如,如果项目中引入了spring - boot - starter - jdbc依赖,Spring Boot会自动配置数据源、JdbcTemplate等相关的Bean,开发者无需手动编写大量的XML配置或Java配置类。
  2. 起步依赖(Starter Dependencies):起步依赖是一种特殊的Maven或Gradle依赖描述符,它聚合了一组相关的依赖。例如,spring - boot - starter - web起步依赖包含了Spring Web MVC、Tomcat等构建Web应用所需的依赖。这样开发者只需要引入一个起步依赖,就可以快速获取相关功能的所有依赖。
  3. 命令行界面(CLI):Spring Boot CLI允许开发者使用Groovy语言快速编写Spring应用,而无需创建一个完整的项目结构。例如,可以创建一个简单的app.groovy文件:
@RestController
class HelloWorld {
    @RequestMapping("/")
    String hello() {
        return "Hello, World!"
    }
}

然后通过spring run app.groovy命令就可以运行这个应用。

  1. Actuator:Actuator为Spring Boot应用提供了生产级别的特性,如健康检查、审计、指标收集等。通过引入spring - boot - starter - actuator依赖,应用会自动暴露一系列的端点(Endpoint),如/health端点可以查看应用的健康状态,/metrics端点可以查看应用的各种指标数据。

Docker基础概述

Docker是什么

Docker是一个开源的应用容器引擎,基于Go语言开发并遵循Apache 2.0协议开源。Docker可以让开发者将应用程序及其依赖打包到一个可移植的容器中,然后发布到任何支持Docker的操作系统环境中运行。容器是一个轻量级、可执行的独立软件包,包含了运行应用程序所需的所有内容:代码、运行时环境、系统工具、系统库和设置。

与传统的虚拟机相比,Docker容器更加轻量级。虚拟机需要模拟整个操作系统,包括内核、文件系统等,占用大量的系统资源。而Docker容器共享宿主机的内核,只包含应用及其依赖,启动速度更快,资源消耗更少。

Docker核心概念

  1. 镜像(Image):镜像是一个只读的模板,用于创建容器。它包含了运行应用所需的一切,如代码、运行时环境、库等。可以将镜像看作是一个应用的“快照”。例如,官方的tomcat镜像包含了Tomcat服务器以及运行Java Web应用所需的环境。镜像可以从Docker Hub等镜像仓库中下载,也可以通过Dockerfile自定义构建。
  2. 容器(Container):容器是镜像的运行实例。可以把容器看作是一个轻量级的沙盒,应用在其中独立运行。容器与容器之间相互隔离,并且可以在宿主机上同时运行多个容器。容器可以通过docker run命令从镜像创建并启动,也可以通过docker startdocker stop等命令对容器进行管理。
  3. 仓库(Repository):仓库是存储镜像的地方。Docker Hub是Docker官方提供的公共仓库,其中包含了大量的官方镜像和用户上传的镜像。除了Docker Hub,企业也可以搭建自己的私有仓库,用于存储企业内部开发的镜像。

Docker基本操作

  1. 镜像操作
    • 拉取镜像:使用docker pull命令从镜像仓库拉取镜像。例如,拉取官方的java镜像:docker pull java:8
    • 查看镜像:使用docker images命令查看本地已有的镜像列表。
    • 删除镜像:使用docker rmi命令删除本地镜像。例如,删除名为java:8的镜像:docker rmi java:8
  2. 容器操作
    • 创建并启动容器:使用docker run命令从镜像创建并启动容器。例如,从java镜像创建一个容器并在容器中运行一个Java程序:docker run -it java:8 java -version。其中,-it参数表示以交互模式运行容器,java -version是在容器中执行的命令。
    • 列出容器:使用docker ps命令列出正在运行的容器,使用docker ps -a命令列出所有容器(包括已停止的容器)。
    • 停止容器:使用docker stop命令停止正在运行的容器。例如,停止名为my - container的容器:docker stop my - container
    • 启动容器:使用docker start命令启动已停止的容器。例如,启动名为my - container的容器:docker start my - container
    • 删除容器:使用docker rm命令删除已停止的容器。例如,删除名为my - container的容器:docker rm my - container

Spring Boot与Docker结合的优势

环境一致性

在开发和部署过程中,环境不一致是一个常见的问题。不同的开发人员可能使用不同版本的依赖库,开发环境与生产环境也可能存在差异,这可能导致“在我机器上能运行,到了服务器上就不行”的情况。通过将Spring Boot应用打包到Docker容器中,容器内包含了应用运行所需的所有依赖和环境配置,确保了开发、测试和生产环境的一致性。无论在哪个环境中运行,只要有Docker环境,应用都能以相同的方式运行。

例如,假设Spring Boot应用依赖于特定版本的MySQL驱动,如果在开发环境和生产环境中安装的MySQL驱动版本不一致,可能会导致数据库连接问题。但如果将应用及其依赖打包到Docker容器中,容器内的MySQL驱动版本是固定的,就不会出现因版本不一致而导致的问题。

快速部署与扩展

Docker容器的启动速度非常快,通常只需要几秒钟。这使得Spring Boot应用可以快速部署到多个服务器上。在生产环境中,如果需要应对高并发的请求,可以通过快速启动多个Spring Boot应用的Docker容器来实现水平扩展。例如,当网站流量突然增加时,可以通过脚本快速启动多个Spring Boot应用的容器,将请求负载均衡到这些容器上,提高应用的处理能力。

易于管理与维护

将Spring Boot应用与Docker结合后,可以使用Docker提供的一系列管理工具对容器进行统一管理。例如,可以使用Docker Compose来定义和管理多个相关容器的应用,通过一个简单的docker - compose.yml文件就可以启动、停止和管理整个应用栈。这使得应用的部署和维护变得更加简单和高效。同时,Docker的镜像管理机制也使得应用的版本管理更加方便,开发者可以轻松地回滚到之前的版本。

Spring Boot应用打包成Docker镜像

创建Spring Boot项目

首先,使用Spring Initializr(https://start.spring.io/)创建一个Spring Boot项目。在Spring Initializr页面中,选择项目的构建工具(如Maven或Gradle)、Spring Boot版本、项目元数据等,并添加所需的依赖。例如,如果要创建一个简单的Web应用,可以添加Spring Web依赖。

下载生成的项目压缩包并解压后,项目结构如下(以Maven项目为例):

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── demo
│   │   │               ├── DemoApplication.java
│   │   │               └── controller
│   │   │                   └── HelloController.java
│   │   └── resources
│   │       ├── application.properties
│   │       └── static
│   │           └── index.html
│   └── test
│       └── java
│           └── com
│               └── example
│                   └── demo
│                       └── DemoApplicationTests.java
└── pom.xml

其中,pom.xml文件管理项目的依赖和构建配置,src/main/java目录存放Java代码,src/main/resources目录存放资源文件,src/test/java目录存放测试代码。

编写Spring Boot应用代码

HelloController.java文件中编写一个简单的RESTful接口:

package com.example.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello from Spring Boot in Docker!";
    }
}

在上述代码中,@RestController注解表明该类是一个RESTful风格的控制器,@GetMapping("/hello")映射了/hello路径的HTTP GET请求到hello方法,该方法返回“Hello from Spring Boot in Docker!”字符串。

构建Spring Boot项目

使用Maven或Gradle构建项目,生成可执行的JAR文件。如果使用Maven,可以在项目根目录下执行以下命令:

mvn clean package

构建成功后,在target目录下会生成一个以项目名称命名的JAR文件,如demo - 0.0.1 - SNAPSHOT.jar

创建Dockerfile

在项目根目录下创建一个名为Dockerfile的文件,用于构建Docker镜像。以下是一个简单的Dockerfile示例:

# 使用官方的Java 8镜像作为基础镜像
FROM openjdk:8-jdk-alpine

# 将当前目录下的target/demo-0.0.1-SNAPSHOT.jar复制到容器中的/app目录下
COPY target/demo-0.0.1-SNAPSHOT.jar /app/

# 切换到/app目录
WORKDIR /app

# 暴露8080端口,Spring Boot应用默认运行在8080端口
EXPOSE 8080

# 定义容器启动时执行的命令,运行JAR文件
CMD ["java", "-jar", "demo-0.0.1-SNAPSHOT.jar"]

在上述Dockerfile中:

  • FROM openjdk:8 - jdk - alpine指定了基础镜像为官方的OpenJDK 8镜像,alpine是一个轻量级的Linux发行版,基于它构建的镜像体积更小。
  • COPY target/demo - 0.0.1 - SNAPSHOT.jar /app/将本地构建生成的JAR文件复制到容器的/app目录下。
  • WORKDIR /app切换工作目录到/app,后续的命令都将在该目录下执行。
  • EXPOSE 8080声明容器将监听8080端口,这只是一个声明,实际映射端口需要在docker run时指定。
  • CMD ["java", "-jar", "demo - 0.0.1 - SNAPSHOT.jar"]定义了容器启动时要执行的命令,即运行JAR文件启动Spring Boot应用。

构建Docker镜像

在项目根目录下执行以下命令构建Docker镜像:

docker build -t my - spring - boot - app:1.0.0.

其中,-t参数用于指定镜像的标签,格式为镜像名称:版本号,这里镜像名称为my - spring - boot - app,版本号为1.0.0。最后的.表示Docker构建上下文为当前目录,即Dockerfile所在的目录。

构建过程中,Docker会根据Dockerfile中的指令逐步构建镜像,并输出构建日志。构建成功后,可以使用docker images命令查看本地已有的镜像列表,应该可以看到my - spring - boot - app:1.0.0镜像。

在Docker中运行Spring Boot应用

运行容器

使用以下命令从my - spring - boot - app:1.0.0镜像创建并启动容器:

docker run -d -p 8080:8080 my - spring - boot - app:1.0.0

其中,-d参数表示以守护进程模式运行容器,容器在后台运行;-p 8080:8080表示将宿主机的8080端口映射到容器的8080端口,这样就可以通过宿主机的8080端口访问容器内运行的Spring Boot应用;my - spring - boot - app:1.0.0是要运行的镜像名称和版本号。

访问应用

容器启动后,可以在浏览器中访问http://localhost:8080/hello,应该可以看到“Hello from Spring Boot in Docker!”的输出,表明Spring Boot应用在Docker容器中成功运行。

容器管理与日志查看

  1. 查看容器日志:使用docker logs命令查看容器的日志输出。例如,查看名为my - container的容器的日志:docker logs my - container。这对于排查应用启动过程中的问题或运行时的错误非常有用。
  2. 进入容器:使用docker exec命令进入正在运行的容器。例如,进入名为my - container的容器并启动一个bash shell:docker exec -it my - container bash。在容器内,可以查看文件系统、执行命令等,方便进行调试和故障排查。
  3. 停止和删除容器:如果需要停止容器,可以使用docker stop命令;如果要删除容器,可以使用docker rm命令。例如,停止名为my - container的容器:docker stop my - container,然后删除该容器:docker rm my - container

使用Docker Compose管理Spring Boot应用

Docker Compose简介

Docker Compose是一个用于定义和运行多个Docker容器应用的工具。通过一个docker - compose.yml文件,就可以定义应用的各个服务(容器)及其依赖关系、网络配置、卷挂载等。它使得管理复杂的容器化应用变得更加简单和高效。例如,一个Spring Boot应用可能依赖于数据库服务,使用Docker Compose可以轻松地将Spring Boot应用容器和数据库容器一起启动和管理。

安装Docker Compose

在不同的操作系统上安装Docker Compose的方法略有不同。以Linux系统为例,可以通过以下命令安装:

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker - compose - $(uname - s)-$(uname - m)" -o /usr/local/bin/docker - compose
sudo chmod +x /usr/local/bin/docker - compose

安装完成后,可以使用docker - compose --version命令查看安装的版本。

编写docker - compose.yml文件

假设Spring Boot应用依赖于MySQL数据库,以下是一个简单的docker - compose.yml文件示例:

version: '3.8'
services:
  spring - boot - app:
    build:
      context:.
      dockerfile: Dockerfile
    ports:
      - 8080:8080
    depends_on:
      - mysql
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=mydb
      - MYSQL_USER=myuser
      - MYSQL_PASSWORD=mypassword
    volumes:
      - mysql - data:/var/lib/mysql
volumes:
  mysql - data:

在上述docker - compose.yml文件中:

  • version: '3.8'指定了Docker Compose文件的版本。
  • services部分定义了两个服务:spring - boot - appmysql
    • spring - boot - app服务:
      • build指定了从当前目录(.)的Dockerfile构建镜像。
      • ports将宿主机的8080端口映射到容器的8080端口。
      • depends_on表示该服务依赖于mysql服务,即mysql服务会先启动。
    • mysql服务:
      • image指定使用官方的mysql:8.0镜像。
      • environment设置了MySQL数据库的相关环境变量,包括root密码、数据库名称、用户名和密码。
      • volumes将容器内的/var/lib/mysql目录挂载到名为mysql - data的卷上,这样可以保证容器重启后数据不会丢失。
  • volumes部分定义了mysql - data卷。

使用Docker Compose启动应用

docker - compose.yml文件所在的目录下执行以下命令启动应用:

docker - compose up -d

-d参数表示以守护进程模式运行容器,容器在后台运行。执行该命令后,Docker Compose会根据docker - compose.yml文件的定义构建并启动spring - boot - appmysql两个容器。可以使用docker - compose ps命令查看正在运行的容器列表,使用docker - compose logs命令查看容器的日志输出。

使用Docker Compose停止和删除应用

使用以下命令停止并删除由Docker Compose启动的容器:

docker - compose down

该命令会停止所有容器并删除容器,同时还会删除docker - compose.yml文件中定义的网络和卷(默认情况下,卷需要手动删除)。

持续集成与持续部署(CI/CD)与Spring Boot和Docker的结合

持续集成(CI)简介

持续集成是一种软件开发实践,团队成员频繁地将代码集成到共享仓库中,每次集成都会通过自动化的构建和测试流程。其目的是尽早发现代码集成过程中的问题,提高软件质量。常见的CI工具包括Jenkins、GitLab CI/CD、Travis CI等。

持续部署(CD)简介

持续部署是在持续集成的基础上,将通过测试的代码自动部署到生产环境。它实现了从代码提交到生产部署的全自动化流程,使得软件能够快速、可靠地发布。

使用Jenkins实现Spring Boot和Docker的CI/CD

  1. 安装Jenkins:在服务器上安装Jenkins,可以通过官方提供的安装包或Docker镜像进行安装。例如,使用Docker安装Jenkins:
docker run -d -p 8080:8080 -p 50000:50000 --name jenkins -v jenkins - home:/var/jenkins_home jenkins/jenkins:lts

其中,-p 8080:8080将宿主机的8080端口映射到Jenkins容器的8080端口,通过浏览器访问http://服务器IP:8080可以打开Jenkins的Web界面;-p 50000:50000用于与Jenkins代理进行通信;-v jenkins - home:/var/jenkins_home将Jenkins的数据目录挂载到宿主机的jenkins - home目录,以保证数据持久化。

  1. 配置Jenkins:首次打开Jenkins Web界面时,需要根据提示解锁Jenkins并安装插件。安装完成后,创建一个新的自由风格的软件项目。
  2. 配置项目的源代码管理:如果项目托管在Git仓库中,在项目配置页面的“源代码管理”部分选择Git,并填写仓库的URL、凭证等信息。
  3. 配置构建环境:在“构建环境”部分,可以选择设置构建代理等相关配置。
  4. 配置构建步骤
    • 构建Spring Boot项目:在“构建”部分选择“Execute shell”(如果是Windows系统,则选择“Execute Windows batch command”),并在命令框中输入构建Spring Boot项目的命令,如mvn clean package
    • 构建Docker镜像:继续在“Execute shell”中添加构建Docker镜像的命令,如docker build -t my - spring - boot - app:${BUILD_NUMBER}.。这里使用${BUILD_NUMBER}作为镜像的版本号,每次构建版本号会自动递增。
    • 推送Docker镜像到仓库:如果有私有镜像仓库,需要配置仓库的认证信息,并添加推送镜像的命令,如docker push my - registry/my - spring - boot - app:${BUILD_NUMBER}
  5. 配置部署步骤:在生产服务器上,可以编写一个脚本,通过拉取最新的镜像并启动容器来实现部署。例如,在“构建后操作”部分选择“Execute shell”,并输入以下命令:
docker pull my - registry/my - spring - boot - app:${BUILD_NUMBER}
docker stop my - spring - boot - container || true
docker rm my - spring - boot - container || true
docker run -d -p 8080:8080 --name my - spring - boot - container my - registry/my - spring - boot - app:${BUILD_NUMBER}

上述命令首先拉取最新的镜像,然后停止并删除旧的容器,最后启动新的容器。

通过以上配置,每次代码提交到Git仓库时,Jenkins会自动触发构建、测试、镜像构建和部署流程,实现Spring Boot应用的持续集成和持续部署。

总结

将Spring Boot与Docker结合应用,能够带来环境一致性、快速部署与扩展、易于管理与维护等诸多优势。通过将Spring Boot应用打包成Docker镜像,并使用Docker和Docker Compose进行管理,以及结合持续集成与持续部署流程,可以实现高效、可靠的软件开发和部署。无论是小型项目还是大型企业级应用,这种结合方式都能提升开发和运维的效率,是现代软件开发中值得推广和应用的技术方案。在实际应用中,还需要根据项目的具体需求和场景,进一步优化和调整配置,以达到最佳的效果。同时,随着技术的不断发展,如Kubernetes等容器编排工具的兴起,将为Spring Boot和Docker的结合应用带来更多的可能性和优化空间。开发者需要不断学习和跟进新技术,以更好地适应不断变化的软件开发环境。

通过以上对Spring Boot与Docker结合应用的详细介绍,希望读者能够掌握相关技术,并在实际项目中灵活运用,提升项目的开发和部署效率,打造更加稳定、可靠的应用系统。在实践过程中,可能会遇到各种问题,需要结合具体的错误信息和技术文档进行排查和解决。同时,也鼓励读者进一步探索Spring Boot和Docker的更多高级特性和应用场景,以充分发挥它们的潜力。