Jenkins使用pipeline部署Springboot项目到本地Docker容器

376 阅读6分钟

1. 概述

本文的步骤适用于单个/本地机器上的Jenkins新安装, 也是本人翻阅大量资料
之后摸索出来的配置比较简单且可行的教程,可直接部署。如果本文对你有用,请务必给个👍!!

如果有自己的想法请查阅官网教程

各位看官请坐稳扶好,接下来我们即将发车~

2. Docker手动部署

在使用流水线部署之前我们先看一下传统的SpringBoot是怎么制作镜像部署到Docker容器中
的,这对后续pipeline操作有一定的引导作用!
此外需要各位读者需要熟悉或者了解Docker容器,本文默认都懂。

2.1 准备jar包

  1. 准备SpringBoot项目(没有项目你部署什么?闹呢?这里我将项目上传到了gitee,为后续流水线拉取做准备)我随便创建了一个,具体如下图,请先忽略根目录下的Dockerfile和Jenkinsfile:

image.png

  1. pom也很简单

image.png

  1. 然后打开我们大名鼎鼎的...额 黑窗口输入 mvn clean package进行打包

  2. 得到的jar包如下

image.png

2.2 制作Dockerfile文件

创建名称为Dockerfile 的文件

FROM openjdk:8
VOLUME /app
EXPOSE 8900
COPY ./target/springboot-demo-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar","&"]

解释一下:

  • FROM: 该镜像基于什么基础镜像创建,这里基于Java8
  • VOLUME: 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷
    • 避免重要的数据,因容器重启而丢失
    • 避免数据逐渐变大
  • EXPOSE: 声明端口,方便配置映射
  • COPY: 复制指令,从上下文目录中复制文件或者目录到容器里指定路径
  • ENTRYPOINT: 启动容器时作为根命令执行

(这里我是直接放到项目根节点制作的,单独创建的话copy节点需要修改一下)

2.3 制作Docker镜像

  1. 准备好以上两个东西之后我们把它们上传到服务器的指定目录下(可以自己创建一个)

image.png

  1. 使用docker命令将Springboot项目制作成Docker images(前提是你服务器已经安装了Docker)
docker build -t springboot-demo .

解释一下:

  • docker 命令大致长这个样docker build [OPTIONS] PATH | URL | -
  • build:构建
  • -t: 镜像的名字及标签,通常 name:tag 或者 name 格式
  1. 构建完成后使用docker images查看镜像信息

image.png

  1. 使用如下命令运行运行镜像,然后docker ps查看运行情况
docker run -p 8900:8900 --name springboot-demo -d springboot-demo

image.png

  1. 访问测试

image.png

到这里,使用Dockerfile手动制作的方式就OK了,结果就是这么个结果,流程就是这么个流程。但是说每次都打包上传到服务器然后手动去执行命令的话跟打个jar包直接丢服务器 nohub java -jar 方式运行有什么区别?(那不是脱裤子放屁嘛)所以要解放双手,果然懒狗是科技进步的推动力~

3.使用Jenkins pipeline 流水线代替

前面说了将Springboot项目制作镜像并打包部署到Docker容器,现在我们借助pipeline来简化上面的流程,让我们一键部署。废话不多说,正片开始!

3.1 安装Jenkins

这里为了避免污染宿主机,我们借助Docker来安装Jenkins

安装之前我们需要在宿主机先创建一个目录来存放Jenkins映射数据卷,同时防止删除容器丢失数据

mkdir -pv /slackoff/jenkins 
# 添加修改权限
chown -R 1000:1000 /slackoff/jenkins

安装Jenkins:

docker run \ 
-u root \ 
-p 8765:8080 -p 50000:50000 \ 
--name jenkins \ 
--restart=always \ 
--privileged=true \ 
-v /var/run/docker.sock:/var/run/docker.sock \ 
-v $(which docker):/bin/docker \ 
-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linuxgnu/libltdl.so.7 \ 
-v /var/lib/docker/tmp:/var/lib/docker/tmp \ 
-v /slackoff/jenkins:/var/jenkins_home \ 
-d jenkins/jenkins

解释一下:

  • -u root: 容器使用宿主机root权限
  • --restart=always:容器每次随着docker重启而启动
  • --privileged=true:给Jenkins添加特权容器!!
  • -v /var/run/docker.sock:/var/run/docker.sock:
    • 表示Docker守护程序通过其监听的基于Unix的套接字。
    • 该映射允许jenkins/jenkins 容器与Docker守护进程通信, 如果jenkins/jenkins容器需要实例化其他Docker容器,则该守护进程是必需的。
    • 说人话就是你在Jenkins容器中要调用宿主机的docker怎么办
  • /slackoff/jenkins:/var/jenkins_home:映射Jenkins数据卷到宿主机

3.2启动Jenkins

[ip]:8765访问Jenkins

image.png

解锁Jenkins:

  1. 第一种:使用docker logs jenkins
  2. 第二种: 使用docker exec -it jenkins /bin/bash,进入容器后使用cat /var/jenkins_home/secrets/initialAdminPassword 查看Jenkins解锁界面上给我们的地址
  3. 第三种:使用cat slackoff/secrets/initialAdminPassword查看宿主机上映射出来的数据卷

第一种是在两个三排 * 号之间,第二第三种直接显示解锁密码,最终的效果是一样的,复制得到的咪咪继续。

image.png

这里我们可以选择安装推荐的插件即可。

image.png

这里可以创建新的用户,我选择使用admin继续(admin的密码就是你刚才复制的那个),下一步点击保存并完成即可

3.3 Jenkins 插件安装

Eclipse Temurin install : 提供从adoptium.net下载JDK的JDK工具安装程序 安装这个插件 [在全局工具设置] -> [JDK] -> [自动安装时] 会多一个选项叫做 install from adoptium.net 的选项。

Blue Ocean : Blue Ocean版本1.27.2

Localization: Chinese : Localization: Chinese (Simplified)版本1.0.24 中文包

Pipeline :Pipeline版本 流水线

SSH :远程命令

3.4 Jenkins全局配置

这里我们需要配置GitLab/Github/Gitee仓库(你不配人家怎么知道去哪里拉你的代码下来打包?) 还需要配置maven,用于执行打包(我看谁敢把项目的target目录上传到代码仓库!)

  1. 进入界面后点击 系统管理 -> 全局工具配置

image.png

  1. 拉到JDK模块,配置Java版本.选择刚才安装插件时提供的install from adoptium.net,然后再选择对应的版本即可。这样就不需要将JDK从宿主机映射到容器内了!!!

image.png 3. 拉到最下面maven模块,配置Maven Name (随便起名,但是后续pipeline要用到),我使用自动安装,当然你也可以选择zip/gar.gz/apache等方式安装。选择完成后选择应用后点击保存即可。

image.png

  1. 回到dashboard后点击 系统管理 -> Manage Credentials添加凭据

image.png

image.png

image.png

进去之后选择username with password类型(你也可以捣鼓其他令牌类型),范围选择全局就行,用户名密码就是你GitLab/Github/Gitee的用户名密码,这个ID可以不填,但是我还是指定一下(这里很重要,因为后面pipeline 会用到这个ID)最后创建即可。

前置条件完成,接下来我们就可以写pipeline了!

3.5 pipeline 语法

可以查看一下pipeline语法 流水线 (jenkins.io)

pipeline {
    agent any 
    stages {
        stage('Build') { 
            steps {
                echo 'Build'
            }
        }
        stage('Test') { 
            steps {
                echo 'Test'
            }
        }
        stage('Deploy') { 
            steps {
                echo 'Deploy'
            }
        }
    }
}

解释一下:

  • agent any:表示Jenkins应该为Pipeline的这一部分分配一个执行者和工作区
  • stage:定义阶段
  • steps:阶段里的每一个步骤
  • echo:就是服务器上的命令

还有另一种脚本式管道的,这里我就不再研究了,各位小伙伴如果想知道可以自行了解,最终的结果是一样的

3.5.1 制作Jenkinsfile

在Springboot项目根节点创建Jenkinsfile文件 文件内容如下:

pipeline {
    agent any

    // Jenkins环境
    environment {
        dockerName='jenkins-demo'
        // 容器端口
        containerPort = '8900'
        // 映射端口
        mappedPort = '8900'
    }

    tools {
        // 注意这里就是你在Jenkins全局配置的Maven Name.
        maven "Maven3.8.6"
        // 如果使用的不是Jenkins默认的JDK版本(默认是11)则引入全局配置中的JDK
        jdk "Java17"
    }

    stages {
        stage("pull") {
            steps {
                git branch: 'master', credentialsId: 'sumchr', url: 'https://gitee.com/xxx.git'
                echo '拉取成功'
            }
        }
        stage("build") {
              steps {
                script {
                    echo "开始打包"
                    sh "mvn -Dmaven.test.failure.ignore=true clean package"
                    try {
                        // 多条命令合并执行
                        sh """
                         docker ps
                         docker images
                        """

                        // 如果不是第一次运行,则清理运行的镜像信息
                        sh "docker stop ${dockerName}"
                        sh "docker rm ${dockerName}"
                        sh "docker rmi ${dockerName}"
                    } catch (Exception err) {
                        echo 'build catch'
                        // 出错处理
                    } finally {
                        sh 'docker ps'
                    }
                }
              }
        }
        stage("publish") {
            steps {
                echo 'publish'
                sh "docker build -t ${dockerName} . "
                sh "docker run -d -p ${mappedPort}:${containerPort} --name ${dockerName} ${dockerName}"
            }
        }
    }

//     post {
//         always{
//             echo 'jenkins完成构建动作之后需要做的事情'
//         }
//     }
}

environment定义环境,你可以修改为自己的东西;

tools里的maven主要就是用来执行项目打包,这里的Maven Name就是刚才在全局配置里配置的名称;

git配置了你的git分支,刚才配置的凭证IDgit仓库地址(这里你需要替换成自己的),当然如果流水线语法你不会配置的话Jenkins也有语法配置(俺也是配出来的,你以为俺会写?)

image.png

image.png

剩下的步骤就是我们刚才演示的手动制作镜像并部署到容器的内容了

3.5.2 制作Dockerfile

在Springboot项目根节点创建Dockerfile文件,文件内容就是刚才制作出来的,这里不再赘述。

3.5.3 上传代码仓库

将刚才制作的两个脚本上传到代码仓库

3.6 部署(重点)

回到Jenkins创建一个流水线

image.png

image.png

进入任务后下拉到流水线部分,定义我们选择Pipeline script form SCM,这是使用代码仓库里的Jenkinsfile,SCM选择git,而后填写项目地址和选择凭证后应用并保存即可,具体如下:

image.png

接下来我们点击立即构建~

image.png

image.png

这样就构建完成了!完结撒花~🎉🎉🎉

(ps:第一次构建会下载maven 拉取pom信息,会比较久)

查看一下docker部署已经是启动了,接下来我们直接访问一下项目接口试一下!

image.png

使用curl http://127.0.0.1:8900/user/11请求,结果如下:

image.png

如果说上面的操作对你来说还是有点懵逼,可以看一下这篇文章Building with Docker Using Jenkins Pipelines, Step-by-Step (liatrio.com)

4. 后续操作

4.1 镜像自动触发

经过上面的操作点击一下按钮即可构建部署了,但是懒狗的究极境界是什么?解放双手啊!当然是推送即触发!哥哥你别动,部署全自动!这部分我就不造轮子了,可以看一下大佬们的文章

pipeline Gitlab通知触发

4.2 镜像部署到其他应用服务器

(俺不会,俺就是个臭开发的,不能抢了运维部署大佬的活,所以,还是有缘再补~~)

4.3 镜像推送到Docker私服仓库

说实话,当你知道Jenkins的处理流程之后,还有什么是不能做的呢?你甚至可以Jenkins in Jenkins ,左脚踩右脚上天呢。无非就是在Jenkinsfile脚本里增加一个上传的步骤罢了。

5. 一点思考

看完以上操作之后,手动部署到Docker和Jenkins自动化部署是不是有十分甚至九分相似?最终Jenkins帮我们这帮懒狗解决了部署多,部署难的问题。而Jenkins pipeline的每一个steps就是我们手动操作的步骤。当然,如果你读完本文之后 有了一点自己的想法,那还等什么?赶紧行动起来吧!(去之前能不能先给个👍?卑微作者,在线求赞)

6. 结语

至此本文对 Jenkins 使用流水线部署项目到容器就介绍完了,部署到容器可以减少对服务器环境的
依赖(我不会说某司一台服务器放了一大堆项目而且使用的环境还不一样的),而且也将我们从技术
爆发而使用的大量微服务导致“部署地狱”中解放出来!

最后,本文查阅资料地址:

Docker

Jenkins中文网

Building with Docker Using Jenkins Pipelines, Step-by-Step (liatrio.com)

Jenkins中文文档 w3cschool

Linux 教程 | 菜鸟教程