Jenkins+Docker实现SpringBoot应用的持续集成

477 阅读3分钟

实现思路

  1. 安装Docker
  2. 安装Docker Jenkins,我更喜欢用Docker来部署环境
  3. 运行Jenkins环境,安装插件:Git、Maven、Config File Provider、SSH。Git用来拉取代码,Maven负责打包,SSH用来上传打包文件到应用服务器
  4. 添加任务,配置信息,让Jenkins生成Jar包
  5. 在应用服务器上编写脚本,将收到的Jar包生成Docker镜像并重新运行。所以应用服务器也是部署的Docker

实现步骤

Docker安装略过

Docker Jenkins

version: "3"
services:
  jenkins:
    image: jenkins/jenkins:lts-centos7-jdk8
    network_mode: mynetwork
    container_name: jenkins
    ports:
      - 8080:8080
      - 50000:50000
    volumes:
      - /etc/localtime:/etc/localtime
      - /home/mycontainers/jenkins/jenkins_home:/var/jenkins_home
      - /home/mycontainers/jenkins/data:/data

执行:

docker-compose -f jenkins.yml up

如果报错:

jenkins    | touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied
jenkins    | Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

那么就给这个jenkins_home文件夹赋予权限:

chmod 777 jenkins_home

容器启动成功会输出以下内容:

jenkins    | Jenkins initial setup is required. An admin user has been created and a password generated.
jenkins    | Please use the following password to proceed to installation:
jenkins    | 
jenkins    | 4e26fb69f5ea42eab61dad85d199c16e
jenkins    | 
jenkins    | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

记住这个密钥:4e26fb69f5ea42eab61dad85d199c16e,登录Jenkins的要用到。

密钥会保存在指定路径下,在这里也可以查看到:

/var/jenkins_home/secrets/initialAdminPassword

访问:http://mylocalhost:8080 进入登录页。

输入密钥后需要等待Jenkins加载一段时间,然后就会出现插件选择页面:

image-20221228105902126

我们不需要安装推荐的插件,只要选择性的安装几个必要的就可以。

点击无,取消所有已勾选的插件,后面再添加:

image-20221228110003933

然后创建管理员用户:

image-20221228110030932

后面一直点确定就可以,这样我们就进来了Jenkins首页,现在页面是英文的,可以根据需要安装中文插件。

Jenkins汉化(可选)

image-20221228110234091

image-20221228110246169

在这里我们可以安装需要的插件:

image-20221228110343125

点击Install without restart进行安装,安装完成是这样的:

image-20221228110929144

注意:汉化需要重启容器才可以生效。

docker restart jenkins

换源(可选)

如果觉得插件的安装太慢,可以修改配置文件换源:

修改hudson.model.UpdateCenter.xml:

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url>
  </site>
</sites>

同样需要重启容器。

Git、Maven、Config File Provider、SSH插件

和汉化插件同理,搜索插件并安装即可:

image-20221228111058747

image-20221228111235440

image-20221228111436990

image-20221228113010554

注意看插件名字哦。

创建SpringBoot项目

来一个最简单的SpringBoot应用:

项目名:mavenDemo

pom.xml
<?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.cc</groupId>
    <artifactId>mavenDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--springboot启动器-->
        <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>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <profiles>
        <!--指定可以用来打包的配置文件1-->
        <profile>
            <!--开发环境-->
            <id>dev</id>
            <properties>
                <activatedProperties>dev</activatedProperties>
            </properties>
            <activation>
                <!--默认情况下使用dev开发配置-->
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <!--生产环境-->
            <id>prod</id>
            <properties>
                <activatedProperties>prod</activatedProperties>
            </properties>
        </profile>
    </profiles>

    <build>
        <!--指定打包的配置文件2-->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>

        <finalName>app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

XML中我们配置了动态环境 (activatedProperties),这样可以很方便的切换打包环境。

配置文件

application.yml:

server:
  port: 8888

spring:
  profiles:
    active: @activatedProperties@

application-dev.yml:

env: dev

application-prod.yml:

env: prod
Application.java
package com.cc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Test Controller
package com.cc.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Value("${env}")
    private String env;

    @GetMapping("/")
    public String env() {
        return env;
    }
}

上传SpringBoot项目到Git上

比如Gitee,新建一个项目,把代码上传到这里,然后我们得到一个Git地址:

gitee.com/xxx/maven-d…

配置Maven

现在需要配置Maven,一般和我们平时开发时用的一致,或者和生产环境一致,我这里用的是Maven3.6.3:

image-20221228112350349

滚到下面找到这个:

image-20221228112842058

配置Maven settings.xml

通常我们都要配置这个,Jenkins中的Maven m2的没有settings.xml的,所以需要上面安装的插件:Config File Provider,安装后就会在Jenkins管理中多出来一个选项:

image-20221228113119454

添加一个Maven settings.xml

image-20221228113148232

image-20221228113201492

下一步就到配置内容了:

image-20221228113253720

提交即可,现在我们就有了一个叫MySetttings.xml的Maven配置文件。

回到刚刚的全局工具配置,设置Maven配置为我们刚创建的settings:

image-20221228113517495

这里有两个,一个默认settings,一个默认全局settings,都搞一样的就可以,这样后面Maven项目会自动选用这个配置文件。

连接宿主机/目标服务器

在用Jenkins打包完成后,我们需要将Jar包上传到目标服务器,所以还需要配置,同上Maven配置的地方,找到Configure System,一直滚下去找到SSH Servers:

image-20221228145801938

准备工作

新建任务

准备工作做好了,现在可以新建任务了:

image-20221228114115256

image-20221228114156451

然后我们需要逐一进行配置:

image-20221228114221395

源码管理

image-20221228114509222

源码在Gitee上,我们把Gitee项目的链接拷贝过来,因为Git项目是私有的,所以会提示报错,我们还需要给一个授权,最简单的就是在Credentials里面配置Gitee的账号密码:

image-20221228114628988

添加完之后就可以选择了:

image-20221228114724490

触发器

可以用Gitee的Hook触发,也可以轮询,这里不配置,就用默认的,需要触发的时候手动点击就好,简单快速入门。

Build

因为创建的任务是Maven类型,所以可以设置Root POM,默认pom.xml即可,然后是Goals and options,用maven打包命令:

image-20221228115048764

构建后操作

结合之前添加的SSH主机,实现在构建后上传Jar包到SSH主机的操作。

image-20221228155828245

宿主机(目标服务器)编写启动应用脚本

生成Jar包后,我们需要制作成镜像并运行容器,所以现在编写脚本放到宿主机里。

宿主机的构建思路是这样的:

  1. 假设工作目录为:/home/projects

  2. Jenkins上传的Jar包放到:/home/project/maveDemo

  3. /home/projects准备脚本:

    • Dockerfile:制作镜像脚本,生成一个Java容器
    • run.sh:光有Java容器还不行,加多个运行脚本,内容是java -jar xxx
    • deploy.sh:部署脚本,整合上面两个的操作,也是Jenkins任务完成后要执行的脚本

    Dockerfile:

    FROM openjdk:8
    RUN mkdir -p /home
    WORKDIR /home
    COPY . .
    ENTRYPOINT ["bash", "run.sh"]
    

    run.sh:

    java -jar app.jar
    

    deploy.sh:

    #!/bin/bash# 应用名,应该和应用目录名一致,且注意docker镜像不能用大写
    projectName=$1echo "进入拷贝Dockerfile和run.sh到应用目录中..."
    cp Dockerfile $1
    cp run.sh $1echo "进入应用目录,删除旧镜像和旧容器..."
    cd $1
    docker stop $1
    docker rm -f $1
    ​
    imageName=$projectName:latest
    docker rmi $imageNameecho "获取容器路径..."
    containerPath="/home/mycontainers"echo "制作新镜像并运行新容器..."
    echo $imageName
    docker build -t $imageName .
    docker run --name $projectName -itd -p 8888:8888 --restart=always -v /etc/localtime:/etc/localtime -v $containerPath/$projectName/data:/data  $imageName
    echo "部署完成。"
    
保存

最后保存即可,以上是最简单的配置方式,这里没有时间和篇幅来完全讲述。

运行任务

回到Dashboard,点击运行按钮:

image-20221228115213819

在这里有工作列表,点进去可以查看运行日志:

image-20221228115237844

第一次执行有很多依赖需要加载,所以会慢一些。

看输出:

[JENKINS] Archiving /var/jenkins_home/workspace/mavenDemo/pom.xml to com.cc/mavenDemo/1.0-SNAPSHOT/mavenDemo-1.0-SNAPSHOT.pom
[JENKINS] Archiving /var/jenkins_home/workspace/mavenDemo/target/app.jar to com.cc/mavenDemo/1.0-SNAPSHOT/mavenDemo-1.0-SNAPSHOT.jar
channel stopped
SSH: Connecting from host [89d37b7b64ad]
SSH: Connecting with configuration [local] ...
SSH: EXEC: completed after 11,451 ms
SSH: Disconnecting configuration [local] ...
SSH: Transferred 1 file(s)
Finished: SUCCESS

成功生成了Jar包,并且将Jar包上传到了目标服务器,EXEC: completed after 11,451 ms指在目标服务器上脚本的执行时间,现在可以到目标服务器上看看日志,或者查看应用是否成功部署。