# Jenkins教程 - 7 部署SpringBoot到docker容器中

现在使用 Jenkin 来部署 SpringBoot 项目,将项目部署到 Docker 容器中。

这里为了保持本章内容的独立性,之前已经配置的步骤,也重新复制了过来,如果你从前面看过来的,就当重新温习了一遍,我将之前的构建任务删掉了,重新创建了一遍。

# 7.1 准备SpringBoot项目

# 1 新建一个SpringBoot 项目

新建一个 SpringBoot 项目,这里我就在 SpringBoot 中新建一个 Controller。

只提供了一个接口,证明 SpringBoot 能访问运行就好了。

package com.doubibiji.hellospringboot.controller;

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

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String sayHello() {
        return "Hello www.doubibiji.com";
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

同时在项目下创建一个 docker 文件夹,并编写 Dockerfile 文件,后面用来生成 Docker 镜像。

Dockerfile 文件内容如下:

# 使用基础的 Java 11镜像
FROM openjdk:11

# 对外暴露的端口
EXPOSE 9000

# 设置环境变量来指定时区
ENV TZ=Asia/Shanghai
# 将时区文件复制到容器中的特定路径
RUN ln -sf /usr/share/zoneinfo/{TZ} /etc/localtime && echo "{TZ}" > /etc/timezone

# 将jar包添加到容器中并更名为app.jar
ADD hello-springboot-0.0.1-SNAPSHOT.jar app.jar

# 运行jar包
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

项目结构如下:

这里还有一个 deploy.sh ,用来执行停止、删除、启动容器等操作,后面介绍。

# 2 将SpringBoot项目托管码云

Jenkins 服务后面需要从 git 仓库拉取代码进行构建,这里使用 gitee 码云来托管代码,所以这里将 SpringBoot 项目托管到码云。

这里细节就不介绍了,git 不太会的,可以学习本站的 git教程 (opens new window)

# 7.2 配置插件和工具

# 1 安装Maven插件

我们现在构建项目需要使用 Maven,所以还需要安装一个 Maven 插件。


在可用的插件中,搜索 maven,在搜索结果中选中 Maven Integration 进行安装。

拉到最下面,查看安装进度

# 2 配置Maven工具

我们的自动化构建任务是使用 Maven 构建的,需要告诉 Jenkins Maven的安装位置。


配置 Maven 的路径:

使用 mvn -v 可以查看 maven 安装的路径。

# 3 安装SSH插件

这个插件的作用就是将 Jenkins 构建的 SpringBoot 项目的 jar 包发布的业务服务器上。

还是刚才安装插件的步骤:

# 4 配置业务服务器

后面需要将构建的 SpringBoot 的 jar 包发布到业务服务器,所以在这里配置一下要发布到的业务服务器的信息。

我也不知道选项为啥突然变成中文了,就是之前的 Manage Jenkins 下的 System

拉到最下面找到 Publish over SSH,安装完 SSH 插件才有这个选项。


Server是可以有多个的,新增一个 SSH Server。


配置上面几个选项就可以了,配置完成,在最下面有个测试的按钮,可以测试一下配置有没有问题,没有问题,保存配置。

# 7.3 创建构建任务

# 1 新建任务

在 Jenkins 管理页面,新建Item,也就是新建构建任务。

填写任务名称:

# 2 源码管理

分支配置:

# 3 构建配置

上面使用默认配置即可。

  • Pre Steps :表示构建前的工作,例如要执行一些脚本,这里我们不需要;
  • Post Steps :表示构建后的工作;
  • Root POM :指定构建使用的 pom.xml,这里表示在远程仓库的根目录下,如果远程仓库中,pom.xml不在根目录下,例如在 demo 目录下,则这里需要配置 demo/pom.xml

# 7.4 执行构建

任务创建了,先不部署到docker服务器,先测试一下能不能构建成功。点击任务后面的按钮,手动执行构建。

执行后,在构建执行状态列表,可以看到构建的进度。

可以点击进去查看构建的控制台信息:


如果已经构建完成,也可以点击任务进入任务信息页面,查看构建失败的原因:

摸索一下页面的功能就好了。

第一次构建需要的时间可能比较久,因为要下载很多项目依赖的 jar 包。


构建如果成功,会显示成功,并在 jenkins 的工作空间下构建出 SpringBoot 项目的 jar 包。

如果没有成功,可以看一下日志,失败的原因是什么。

# 7.5 部署到业务服务器

上面的步骤只是在 Jenkins 服务器上生成了 jar 包,还没有一条龙执行到自动部署到业务服务器的 Docker 容器中。下面继续。

# 1 配置传输

重新进入到构建任务的配置页面,对 Post Steps 进行配置,也就是构建后的操作。

选择 Send files or execute commands over SSH

因为 Jenkins 服务和 业务服务不是在同一个服务器上,所以才使用 Send files or execute commands over SSH ,如果在一台服务器 上,直接选择 执行 shell 就可以了,都不用将文件推送到别的服务器,直接使用shell命令 mv 去移动文件就可以了。


这里传输三个文件,一个 jar包、Dockerfile文件、执行发布的脚本文件,脚本文件也通过 Jenkins 传到业务服务器上,主要负责打包镜像,停止并删除之前的容器,启动当前的容器。

在构建任务的 Post Steps 的SSH Server填写如下配置:

  • SSH Server:选择要传输的业务服务器。

  • Source files :在 Jenkins 服务器上,构建的 jar 包在 Jenkins 的工作空间下,也就 ~/.jenkins/workspace ,我这里构建的任务名称叫 hello-jenkins ,所以 jar 包的地址是 /home/doubi/.jenkins/workspace/hello-jenkins/target/hello-springboot-0.0.1-SNAPSHOT.jar。这里填写的地址是从构建的任务所在的文件夹开始算的,也就是 /home/doubi/.jenkins/workspace/hello-jenkins 算起,所以这里我填写了 target/*.jar ,使用了通配符,表示 target 目录下所有的 jar 包。

  • Remote directory :表示传输到的远程服务器的路径,也是从家目录 ~ 开始算起,表示传输到 ~/projects/hello-springboot 目录下,也就是传输到 /home/doubi/projects/hello-springboot 目录下,则传输完成,在业务服务器上 jar 包的路径是 /home/doubi/projects/hello-springboot/hello-springboot-0.0.1-SNAPSHOT.jar ,如果路径不存在,会自动创建。

  • Remove prefix :这个表示删除的路径的前缀,如果不填写,则复制到远程后,会将 target 目录一起复制,会变成 /home/doubi/projects/hello-springboot/target/hello-springboot-0.0.1-SNAPSHOT.jar ,这里将 target 路径删掉。

  • Exec command :表示上传完成执行的命令。


再添加一个传输配置,将 Dockerfile 和 deploy.sh 也传输到业务服务器。

Dockerfile 在准备 SpringBoot 的时候已经看到脚本了。

下面编写一下 deploy.sh,如下:

#!/bin/bash

# 项目名称
projectName=hello-springboot
# 年月日时分的时间戳
timestamp=$(date +%Y%m%d%H%M)
# 新镜像的名称
newImageName=$projectName-$timestamp

# 1.首先使用Dockerfile打镜像
docker build -t $newImageName .

# 2.停止并删除之前运行的容器
runningContainerId=$(docker ps | grep "$projectName" | awk '{print $1}')
# 如果有运行中的容器,停止它,并删除它
if [ -n "$runningContainerId" ]; then
  docker stop "$runningContainerId"
  docker rm "$runningContainerId"
fi
# 万一新的镜像有问题,为了恢复,就不删除之前的镜像了

# 在宿主机上创建logs目录,用于容器挂载,这样查看日志可以直接在宿主机查看,比较方便
mkdir -p ~/projects/$projectName/logs

# 3.运行新的镜像
docker run -d -p 9000:9000 --restart=always -v ~/projects/$projectName/logs:/logs $newImageName

# 运行的时候可以指定application-*.yaml配置文件,例如指定测试环境
# docker run -d -e SPRING_PROFILES_ACTIVE=test -p 9000:9000 --restart=always -v ~/projects/$projectName/logs:/logs $newImageName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

deploy.sh 主要是构建镜像,并停止和删除之前的镜像,运行新的镜像。

# 2 重新构建

除了可以点击 Dashboard 页面,任务列表后面的构建按钮,可以构建。


还可以在任务详情页面,点击 立即构建 按钮。


在 Jekins 的控制台页面,可以查看构建日志:

可以看到是否构建和传输成功,根据提示信息修改即可,如果传输成功,运行不成功,可以查看业务服务器上 jar 包有没有传输到对应的目录。

Post StepsSend files or execute commands over SSH 的高级中,有一个 Exec timeout 选项,表示执行超时时间,默认是2分钟,如果任务构建时间比较长,可以将时间设置的长一些。

# 3 访问SpringBoot项目

访问 SpringBoot 项目测试的接口,发现可以访问。

重新修改代码,并推送到 gitee,然后重新使用 Jekins 重新执行构建,发现自动构建更新完成。

至此,完成了整个 SpringBoot 项目的自动构建。