使用Docker构建、发布Spring Boot应用

作者: garyond | 来源:发表于2018-11-29 16:54 被阅读67次

    1. 简介

    Docker 是一个开源的应用容器引擎,让开发人员可以将应用打包部署到一个可移植的容器中,然后发布到任何流行的Linux服务器上,容器是完全使用沙箱机制,相互之间不会有任何接口。

    一个完整的Docker有以下几个部分组成:

    1. Docker Client 客户端
    2. Docker Daemon 守护进程
    3. Docker Image 镜像
    4. Docker Container 容器

    2. 准备工作

    为了通过Docker来构建与部署Spring Boot应用, 我们需要有一个安装过 Docker 环境的服务器来打包 Spring Boot 项目, 因此在进行项目构建时, 需要安装Java、Maven和Docker的应用环境,建议使用Linux系统来构建Docker镜像。 Java与Maven环境安装与配置在这就不详细介绍了,Docker环境安装与配置可以参考之前写过的文章《Docker容器安装与部署》。

    环境配置

    • Java版本: JDK1.8+
    • Maven版本: Maven3.0+
    • Docker版本: Docker 17.06+

    3. 构建Spring Boot项目

    1. 配置Maven项目依赖文件pom.xml

    • 添加Spring Boot项目依赖
     <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.0</version>
            <relativePath/>
    </parent>
    
    • 添加Spring Boot项目相关的依赖包
    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <!-- Java Mail -->
            <dependency>
                <groupId>com.sun.mail</groupId>
                <artifactId>javax.mail</artifactId>
                <version>1.6.1</version>
            </dependency>
    </dependencies>
    
    • 创建Controller, 提供服务接口, 此处提供一个测试接口
    @RestController
    public class HelloController {
        
        @RequestMapping("/sayHello")
        public String sayHello() {
            return "Hello Spring Boot!";
        }
    }
    
    • 创建Spring Boot启动类
    @SpringBootApplication
    public class HelloApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(HelloApplication.class, args);
        }
    }
    
    

    添加完毕后启动项目,启动成功后浏览器访问:http://localhost:8080/sayHello,调用接口页面返回:Hello Spring Boot!,说明 Spring Boot 项目工作正常。

    4. Spring Boot项目中添加Docker构建组件

    支持Spring Boot项目Docker容器构建的组件有许多个, 此处选择com.spotify:docker-maven-plugin组件进行构建。

    • 修改pom.xml文件, 添加Docker编译支持组件
    <properties>
          <docker.image.prefix>myProject</docker.image.prefix>
    </properties>
    <build>
          <plugins>
              <!-- Spring Boot Build Plugin -->
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
              <!-- Docker maven plugin -->
              <plugin>
                  <groupId>com.spotify</groupId>
                  <artifactId>docker-maven-plugin</artifactId>
                  <version>1.2.0</version>
                  <configuration>
                      <imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
                      <dockerDirectory>src/main/docker</dockerDirectory>
                      <resources>
                          <resource>
                              <targetPath>/</targetPath>
                              <directory>${project.build.directory}</directory>
                              <include>${project.build.finalName}.jar</include>
                          </resource>
                      </resources>
                  </configuration>
              </plugin>
              <!-- Docker maven plugin -->
          </plugins>
    </build>
    

    说明 :

    1. ${docker.image.prefix}为pom文件中properties中添加的配置;
    2. ${project.artifactId}为pom文件中的artifactId属性,${project.version}为pom文件中的version属性;
    3. dockerDirectory属性配置dockerfile文件的存放路径/src/main/docker
    4. resources属性中配置复制 jar 包到 docker 容器指定目录配置,将target下编译的Jar包复制到docker目录下。

    我们也可以通过spotify的docker-maven-plugin组件配置, 自动创建Docker镜像,绕过下面创建Dockerfile的步骤, 直接生成Docker镜像:

    <properties>
          <docker.image.prefix>myProject</docker.image.prefix>
    </properties>
    <build>
          <plugins>
              <!-- Spring Boot Build Plugin -->
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
              <!-- Docker maven plugin -->
              <plugin>
                  <groupId>com.spotify</groupId>
                  <artifactId>docker-maven-plugin</artifactId>
                  <version>1.2.0</version>
                  <configuration>
                      <imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName>
                      <baseImage>docker.io/cemmersb/centos-jdk8:latest</baseImage>
                      <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
                      <resources>
                          <resource>
                              <targetPath>/</targetPath>
                              <directory>${project.build.directory}</directory>
                              <include>${project.build.finalName}.jar</include>
                          </resource>
                      </resources>
                  </configuration>
              </plugin>
              <!-- Docker maven plugin -->
          </plugins>
    </build>
    

    说明:

    1. 使用baseImage属性配置Docker容器依赖的基础镜像信息;
    2. 使用entryPoint属性配置Docker容器的入口命令。
    • src/main/docker下创建Dockerfile
    FROM docker.io/cemmersb/centos-jdk8:latest
    MAINTAINER garyond
    VOLUME /tmp
    ADD hello-service:0.0.1-SNAPSHOT.jar app.jar
    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
    

    关于Dockerfile的相关命令可以参考我的文章《使用Dockerfile构建Docker镜像》, 这里我就不详细讲解了。

    • 编译项目, 进行Docker镜像打包, 执行命令mvn clean package docker:build
    $ mvn clean package docker:build
    ...
    Step 1/5 : FROM docker.io/cemmersb/centos-jdk8:latest
     ---> ccba23a213f2
    Step 2/5 : MAINTAINER zhangjiayang <zhangjiayang@sczq.com.cn>
     ---> 0de52ae244d4
    Step 3/5 : VOLUME /tmp
     ---> 3d25b5f60bb8
    Step 4/5 : ADD hello-service-0.0.1-SNAPSHOT.jar app.jar
     ---> a02fcec9904c
    Step 5/5 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
     ---> Running in a5cf7c699a3f
    Removing intermediate container a5cf7c699a3f
     ---> 2177684b649d
    ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
    Successfully built 2177684b649d
    Successfully tagged hello-service:0.0.1-SNAPSHOT
    ...
    

    由于Docker构建时需要下载基础镜像信息, 所以过程会比较长, 所以我只粘贴了最后一部分编译的信息。编译完成后, 查看主机的镜像信息。

    $ docker images
    REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
    hello-service                    0.0.1-SNAPSHOT      2177684b649d        13 minutes ago      875MB
    rabbitmq                         3-management        75472a5c510b        2 months ago        149MB
    cemmersb/centos-jdk8             latest              ccba23a213f2        3 years ago         858MB
    
    • Docker镜像生成后, 运行Docker容器
    $ docker run -d -p 8080:8080 hello-service:0.0.1-SNAPSHOT
    

    通过docker ps命令查询Docker容器是否正常启动

    $ docker ps
    

    容器成功启动后,打开浏览器访问:http://localhost:8080/sayHello,调用接口页面返回:Hello Spring Boot!,说明 Spring Boot 项目Docker容器工作正常。

    5. 构建Spring Boot多模块依赖工程

    由于Spring Boot项目开发中经常会遇见多模块的应用, 比如下面有一个应用sword, 应用中包含以下几个模块, 其中需要部署三个应用sword-api、sword-job、sword-admin

    • sword-common 公共模块(基础依赖)
    • sword-util 常用工具模块(基础依赖)
    • sword-api 接口模块(独立部署)
    • sword-job 应用采集模块(独立部署)
    • sword-admin 管理后台模块(独立部署)

    5.1 准备工作

    • 配置总体项目POM
    <?xml version="1.0" encoding="UTF-8"?>  
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
        <modelVersion>4.0.0</modelVersion>  
        <groupId>com.garyond</groupId>  
        <artifactId>sword</artifactId>  
        <version>2.0.0</version>  
        <packaging>pom</packaging>  
      
        <modules>  
            <module>sword-common</module> <!--核心业务 -->  
            <module>sword-admin</module><!-- 后台 -->  
            <module>sword-api</module><!-- API -->
            <module>sword-job</module><!-- 定时采集程序 -->  
            <module>sword-util</module><!-- 常用工具 -->  
        </modules>  
      
        <parent>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-parent</artifactId>  
            <version>2.0.4.RELEASE</version>  
            <relativePath/> <!-- lookup parent from repository -->  
        </parent>  
          
    </project>  
    
    • 配置sword-common等基础依赖模块
    <?xml version="1.0" encoding="UTF-8"?>  
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
        <modelVersion>4.0.0</modelVersion>  
      
        <artifactId>sword-common</artifactId>  
        <packaging>jar</packaging>  
      
        <parent>  
            <groupId>com.garyod</groupId>  
            <artifactId>sword</artifactId>  
            <version>2.0.0</version>  
            <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->  
        </parent>  
      
        <properties>  
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
            <java.version>1.8</java.version>  
            <relativePath/>  
        </properties>  
      
        <dependencies>  
            ......  
        </dependencies>  
      
        <build>  
            <plugins>  
                <plugin>  
                    <groupId>org.springframework.boot</groupId>  
                    <artifactId>spring-boot-maven-plugin</artifactId>  
                    <configuration>  
                        <classifier>exec</classifier>  
                    </configuration>  
                </plugin>           
            </plugins>  
        </build>  
      
    </project>  
    
    • 配置sword-api、sword-admin等应用模块
    <?xml version="1.0" encoding="UTF-8"?>  
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
        <modelVersion>4.0.0</modelVersion>  
      
        <artifactId>sword-api</artifactId>  
        <packaging>jar</packaging>  
      
        <parent>  
            <groupId>com.garyond</groupId>  
            <artifactId>sword</artifactId>  
            <version>2.0.0</version>  
            <relativePath>../pom.xml</relativePath>   
        </parent>  
      
        <properties>  
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
            <java.version>1.8</java.version>  
        </properties>  
      
        <dependencies>  
            ......  
        </dependencies>  
      
        <build>  
            <plugins>  
                <plugin>  
                    <groupId>org.springframework.boot</groupId>  
                    <artifactId>spring-boot-maven-plugin</artifactId>  
                    <configuration>  
                        <executable>true</executable>  
                    </configuration>  
                </plugin>  
                  
                <!-- Docker maven plugin -->  
                <plugin>  
                    <groupId>com.spotify</groupId>  
                    <artifactId>docker-maven-plugin</artifactId>  
                    <version>1.2.0</version>  
                    <configuration>  
                        <imageName>${project.groupId}/${project.artifactId}:${project.version}</imageName>  
                        <baseImage>java:8</baseImage>
                        <maintainer>garyond</maintainer>
                        <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
                        <resources>  
                            <resource>  
                                <targetPath>/</targetPath>  
                                <directory>${project.build.directory}</directory>  
                                <include>${project.build.finalName}.jar</include>  
                            </resource>  
                        </resources>  
                    </configuration>  
                </plugin>  
                <!-- Docker maven plugin -->  
            </plugins>  
        </build>  
    </project>  
    

    5.2 应用部署

    1. 进入父工程(sword)pom文件所在目录,打包编译,将依赖包放至本地仓库
    mvn clean install package -Dmaven.test.skip
    
    1. 分别进入各模块(sword-api/sword-admin/sword-job)目录,使用 Docker构建镜像
    mvn package docker:build -Dmaven.test.skip
    
    1. 运行Docker容器
    docker run -d -p 8080:8080 --name=sword-admin sword-admin:2.0.0
    

    相关文章

      网友评论

        本文标题:使用Docker构建、发布Spring Boot应用

        本文链接:https://www.haomeiwen.com/subject/xzkcrftx.html