1、大致流程

流程说明:

1)开发人员每天把代码提交到 Gitlab 代码仓库

2)Jenkins 从 Gitlab 中拉取项目源码,编译并打成jar包,然后构建成 Docker 镜像,将镜像上传到 Harbor 私有仓库。

3)Jenkins 发送 SSH 远程命令,让生产部署服务器(应用服务器)到 Harbor 私有仓库拉取镜像到本地,然后创建容器。

4)最后,用户可以访问到容器(api或网站)

2、服务器规划


注:上面表格中机器标识是为了我在下面文章种描述方便加上去的,没实际作用。_

3、环境准备

3.1 项目源码

因为我这边描述的是单机版,所以项目源码找了一个由 sping 架构的微服务,前后端不分离的。不是传统意义上的 SpringCloud sping(全家桶)。整个项目前后端只有一个 jar包。

3.2 Docker、Harbor等软件安装

根据上面表格可以看出来,具体需要安装那些软件,按需安装即可,因为之前已经写过这些软件的安装过程,不再重复撰述了。

  • Jenkins 安装 点击这里查看

  • Docker 安装 点击这里查看

  • Harbor 安装 点击这里查看

  • Git安装 点击这里查看

  • Jdk安装 点击这里查看

4、持续集成之创建 Jenkins Pipeline 流水线项目

注意,本文的重点是将本地运行的 java 微服务 jar包,构建成 docker 镜像,然后部署到生产服务器上。这个这套流程是通过 Jenkins Pipeline 的形式去完成,也是下面要讲的。Jenkins 处理这个流程有很多方式,Pipeline(流水线)只是其中一种方式,也是官方推荐的。

4.1 Jenkins项目构建类型-Pipeline流水线项目创建

Pipeline,简单来说,就是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点

的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。

使用 Pipeline 的优点(来自翻译自官方文档):

Pipeline以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流

程。

4.1.1 安装 Pipeline 插件

Jenkins中依次打开,Manage Jenkins->Manage Plugins->可选插件,搜素。

安装插件后可以创建项目了。

4.1.2 配置构建

  • 参数化构建,根据分支拉取代码

4.1.3 创建 Jenkinsfile 文件-拉取代码

项目根目录创建 Jenkinsfile 文件,编写流水线脚本。

pipeline {agent anyoptions {timeout(time: 1, unit: 'HOURS')}stages {stage('拉取代码') {steps {checkout(\[$class: 'GitSCM', branches: \[\[name: '*/${branch}'\]\], extensions: \[\], userRemoteConfigs: \[\[credentialsId: '32d07987-6f74-4b74-bb91-a9f5509', url: 'http://192.168.5.111:80/gitee/xx/xx/cabast'\]\]\])echo '拉取代码成功' }}    }}

说明,这里需要在Jenkins中配置好git仓库的相关凭证,就是Jenkins和git仓库通信。具体配置方法看前面的准备环境中,Jenkins安装链接。

现在构建验证下。

4.1.4 构建镜像

既然代码拉取下来了,就可以构建镜像了,使用 Dockerfile 编译、生成镜像。

这里简单的介绍下 jar包构建成 Docker 镜像的基础知识。

怎么把Java应用打包成Docker镜像?对熟悉Docker的同学这应该是一个很简单的问题,把项目打包成JAR包然后在Dockerfile里用ADD命令把JAR文件放到镜像里,启动命令设置执行这个JAR文件即可。

FROM openjdk:8-jre
ADD target/*.jar /application.jar
ENTRYPOINT \["java", "-jar","/application.jar"\]

比如上面这个 dockerfile,就是把 本地 JAR 从 target 目录里添加到 Docker 镜像中,以及将 jar -jar /application.jar 设置成容器的启动命令这两步操作。

不过除了这种最原始的方法外我们还可以使用 Maven 的一些插件,或者 Docker 的多阶段打包功能来完成把 Java应用打包成 Docker 镜像的动作。

Spotify 公司的 dockerfile-maven-plugin 和 Google 公司出品的 jib-maven-plugin 是两款比较有名的插件,下面简单介绍一下 dockerfile-maven-plugin 的配置和使用。也是本次使用的方法

1)项目的 pom.xml 文件中加入 dockerfifile-maven-plugin 插件

说明,红框里的很多参数可以自己自定义的,如果不熟悉sping,不用改直接用即可。

其中,JAR_FILE 这个参数是传给 dockerfile 的,所以必须跟 dockerfile 中的一致才行。

这里把红框中的代码贴出来,方便复制。

            <!--   dockerfile-maven-plugin  --><plugin><groupId>com.spotify</groupId><artifactId>dockerfile-maven-plugin</artifactId><version>1.4.7</version><executions><execution><id>default</id><goals><goal>build</goal></goals></execution></executions><configuration><repository>${project.artifactId}</repository><tag>${project.version}</tag><buildArgs><JAR\_FILE>${project.build.finalName}.jar</JAR\_FILE></buildArgs></configuration></plugin>

2)在微服务项目根目录下建立 Dockerfile 文件,注意修改端口

FROM openjdk:8-jdk-alpine
EXPOSE 8082
ARG JAR_FILE
ADD target/${JAR_FILE} /app.jar
ENTRYPOINT \["java", "-jar","/app.jar"\]
# ${JAR_FILE} 这个参数是从pox.xml 文件中传过来的,名称必须一致才行。

3)修改 Jenkinsfile 构建脚本

pipeline {agent anyoptions {timeout(time: 1, unit: 'HOURS')}stages {stage('拉取代码') {steps {checkout(\[$class: 'GitSCM', branches: \[\[name: '*/${branch}'\]\], extensions: \[\], userRemoteConfigs: \[\[credentialsId: '32d07987-6f74-4b74-bb91-a9f5509', url: 'http://192.168.5.111:80/gitee/xx/xx/cabast'\]\]\])echo '拉取代码成功' }}  stage('编译打包成镜像') {steps {//sh "mvn -f ${project_name} clean package"  //暂不用这种,如果多个微服务,多个pom工程可以参数化构建的时候指定对应项目。sh "mvn -e clean package dockerfile:build"echo "编译成功"}}}}

说明,Jenkinsfile 这个文件的脚本内容,随着配置的增加不断的在更新,不要搞错。

还需要说明的是,以上配置的 Jenkinsfile、Dockerfile、pox.xml(项目源码自带),都是在项目根目录编辑或新增的,其中,Jenkinsfile、Dockerfile 是新添加的,pox.xml 项目自带的,只需编辑添加内容即可。最终这三个文件随同项目源码一同 push 到代码托管服务器,上面表格中的机器D中,Jenkins 构建的时候会拉取这些文件。

4.1.5 将镜像上传到 Harbor 镜像仓库

大致意思,Jenkins 需要跟 Harbor 通信并且登录后才能上传镜像,所以必须先配置好通信这一步,操作跟Jenkins通信git仓库一样。在Jenkins先生成harbor凭据(就是Jenkins和harbor绑定)。

1)Jenkins 中生成 harbor 账号凭据

2)生成凭证脚本代码

3)继续更新 Jenkinsfile 文件

pipeline {agent anyoptions {timeout(time: 1, unit: 'HOURS')}environment{jar\_file\_name="dwq"tag="1.0.0"def imageName ="${jar\_file\_name}:${tag}"DT="\`date +%m%d%H%M\`"newimageName="cn.keyi/dwq"def newtag ="v${DT}"harbor_url="192.168.108.5:85"harbor\_project\_name="project_dwq"port=8082}stages {stage('拉取代码') {steps {checkout(\[$class: 'GitSCM', branches: \[\[name: '*/${branch}'\]\], extensions: \[\], userRemoteConfigs: \[\[credentialsId: '32d07987-6f74-4b74-bb91-a9f5509', url: 'http://192.168.5.111:80/gitee/xx/xx/cabast'\]\]\])echo '拉取代码成功' }}  stage('编译打包成镜像') {steps {//sh "mvn -f ${project_name} clean package"  //暂不用这种,如果多个微服务,多个pom工程可以参数化构建的时候指定对应项目。sh "mvn -e clean package dockerfile:build"echo "编译成功"}}stage('镜像打标签并上传') {steps {//对镜像打上标签sh "docker tag ${imageName} ${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}"//上传镜像的前提需要登录对应镜像仓库,登录仓库需要先绑定账号和凭据withCredentials(\[usernamePassword(credentialsId: '42521--69904', passwordVariable: 'Din1', usernameVariable: 'dwqn')\]) {//登录镜像仓库sh "docker login ${harbor_url} -u ${dqin} -p ${Dadn1}"echo "harbor 登录成功"//推送镜像sh "docker push ${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}"echo "上传完成"}}stage('上传完成后删除本地镜像') {steps {sh "docker rmi -f ${newimageName}"sh "docker rmi -f ${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}"echo "删除成功"}}}}

说明,上传(推送)镜像前先需要对镜像打标签(第42行),上传镜像先需要Jenkins登录的harbor(第47行),登录前先需要绑定凭据(第45行)。绑定凭据这行代码可以在流水线语法生成器中生成,上面截图中所示。

注意,Jenkins 登录到 harbor 这里(机器A登录到机器C),还需要配置一步,机器C的 harbor 访问地址包括端口添加到机器A的 docker 信任列表里。在机器A操作如下。

vim /etc/docker/daemon.json
# 添加如下内容,如果这个文件有多行内容,每行尾部需要逗号隔开,最后一行不需要,json语法。
"insecure-registries": \["192.168.66.102:85"\]

还需要注意,上面流水线脚本中打标签和推送的docker命令,我不使用变量方式粘贴下。

# 给镜像打标签
docker tag dwq:1.0.0 192.168.108.5:85/dwq_pojname/newdwq:v1
# dwq:1.0.0 这个是编译完后打包出来的默认镜像名,这里不能改成别的,如果改的话可能需要在pox.xml中提前定义属性的方式改我没搞定,java不熟悉。
# dwq_pojname 这个是harbor配置完后,创建的空间名称,所以需要提前配置和harbor(参考前面环境准备那一节)。
# newdwq:v1 这个是打完标签后显示的镜像名称,可以自定义。# 推送镜像(上传)
docker push 192.168.108.5:85/dwq_pojname/cn.key/newdwq:v1

4)构建验证推送效果

4.1.6 生产服务器拉取镜像并发布

大致流程,Jenkins SSH 插件远程调用拉取 harbor 仓库中的镜像,并将其部署在生产服务器(机器B)。

1)安装 Publish Over SSH 插件

2)Jenkins 上配置远程生产部署服务器

系管理-系统配置->下拉找到远程服务器配置

说明,截图中标1的地方填写Jenkins服务器(机器A)上生成的私钥,标2、3的地方填写生产部署服务器(机器B)的ip和登录用户名。其它地方自定义。

注意,因为Jenkins服务器需要在远程服务器上执行脚本,所以Jenkins需要免密登录到生产部署服务器,即(机器A免密登录到机器B)。需要提前配置好免密登录,具体配置方法参照之前写过的文章,两台Linux服务器之间免密登录,点击查看 。

其实,就是将机器A的公钥拷贝到机器B,如下快速操作。机器A上执行,前提A上已经生成了密钥对。

ssh-copy-id 192.168.108.4

3)生成远程调用模板代码

在流水线语法生成器中生成调用SSH插件模板代码

说明,第一个红框是插件ssh名字,第二个红框是远程生产部署服务器的名字,上面设置好的这里下拉选择,其它的均不填。

# 生成的代码片段如下
sshPublisher(publishers: \[sshPublisherDesc(configName: 'master_server', transfers: \[sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '\[, \]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')\], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)\])

说明,这行调用代码,就是Jenkins远程登录到生产部署服务器上(机器B),并执行远程服务器上的部署脚本。所以,这行代码上需要添加执行的 shll 脚本和相关参数。添加shll脚本后更新如下

sshPublisher(publishers: \[sshPublisherDesc(configName: 'uatserver\_108.4\_docker', transfers: \[sshTransfer(cleanRemote: false, excludes: '', execCommand: "/data/api/dokapp/deploy.sh ${harbor\_url} ${harbor\_project_name} ${newimageName} ${newtag} ${port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '\[, \]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')\], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)\])
# 注意更新了这里  execCommand: "/data/api/dokapp/deploy.sh ${harbor\_url} ${harbor\_project_name} ${newimageName} ${newtag} ${port}"
# deploy.sh 这个是机器B上的部署脚本,前面是路径,后面跟5个参数,Jenkinsfile中都定义过,这个5个参数用在部署脚本里接受。

机器B上的部署脚本如下。

#! /bin/sh
# 接收外部参数,在jenkinsfile和设置定义的参数对应
harbor_url=$1
harbor\_project\_name=$2
newimageName=$3
newtag=$4
port=$5imageName=${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}echo "${imageName}"#查询容器是否存在,存在则删除
containerId=\`docker ps -a | grep -w ${project_name}:${tag}  | awk '{print $1}'\`
if \[ "${containerId}" !=  "" \] ; then#停掉容器docker stop ${containerId}#删除容器docker rm ${containerId}echo "成功删除容器"
fi#查询镜像是否存在,存在则删除
imageId=\`docker images | grep -w ${project_name}  | awk '{print $3}'\`if \[ "${imageId}" !=  "" \] ; then#删除镜像docker rmi -f ${imageId}echo "成功删除镜像"
fi# 登录Harbor
docker login ${harbor_url} -u dwqadmin -p Dwqadmin1# 下载镜像
docker pull ${imageName}# 启动容器
docker run -dit --name=dwq -p ${port}:${port} ${imageName}#脱掉变量的启动容器命令,为了方便调试
docker run -di --name=dwq -p 8082:8082 192.168.108.5:85/project_dwq/cn.keyi/dwq:v03040955echo "容器启动成功"

说明,上面的部署脚本我是放在远程生产部署服务器上的(机器B),也可以放在项目源码根目录,跟jenkfile文件一样,或者 Jenkins 服务器上(机器A),Jenkins SSH远程链接后,先复制部署脚本到机器B,再执行也可以。只需要在Jenkinsfile中应用部署那部分的shell脚本改下即可,可以参考下面的其它方案2

3)再次更新 jenkfile 文件

pipeline {agent anyoptions {timeout(time: 1, unit: 'HOURS')}environment{jar\_file\_name="dwq"tag="1.0.0"def imageName ="${jar\_file\_name}:${tag}"DT="\`date +%m%d%H%M\`"newimageName="cn.keyi/dwq"def newtag ="v${DT}"harbor_url="192.168.108.5:85"harbor\_project\_name="project_dwq"port=8082}stages {stage('拉取代码') {steps {checkout(\[$class: 'GitSCM', branches: \[\[name: '*/${branch}'\]\], extensions: \[\], userRemoteConfigs: \[\[credentialsId: '32d07987cec09', url: 'http://192.168.108.6:8080/gitee/cabt'\]\]\])echo '拉取代码成功' }}    /*stage('编译,安装公共子工程') {//    steps {//         sh "mvn -f common clean install"//    }}*/stage('编译打包成镜像') {steps {//sh "mvn -f ${project_name} clean package"  //暂不用这种,如果多个微服务,多个pom工程可以参数化构建的时候指定对应项目。sh "mvn -e clean package dockerfile:build"echo "编译成功"}}stage('镜像打标签并上传') {steps {//对镜像打上标签sh "docker tag ${imageName} ${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}"//上传镜像的前提需要登录对应镜像仓库,登录仓库需要先绑定账号和凭据withCredentials(\[usernamePassword(credentialsId: '425e4-69978f422d04', passwordVariable: 'Dadmin1', usernameVariable: 'admin')\]) {//登录镜像仓库sh "docker login ${harbor_url} -u ${admin} -p ${Ddmin1}"echo "harbor 登录成功"//推送镜像sh "docker push ${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}"echo "上传完成"}}}stage('上传完成后删除本地镜像') {steps {sh "docker rmi -f ${newimageName}"sh "docker rmi -f ${harbor\_url}/${harbor\_project_name}/${newimageName}:${newtag}"echo "删除成功"}}stage('应用部署') {steps {sshPublisher(publishers: \[sshPublisherDesc(configName: 'uatserver\_108.4\_docker', transfers: \[sshTransfer(cleanRemote: false, excludes: '', execCommand: "/data/api/dokapp/deploy.sh ${harbor\_url} ${harbor\_project_name} ${newimageName} ${newtag} ${port}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '\[, \]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')\], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)\])echo "启动成功"}}}
}

4.1.7 部署脚本其它方案

其它方案1,应用部署这块,案例中用 Jenkins 的 Publish Over SSH 远程链接机器B,也可以不用这个插件,直接机器A用shell脚本登录到机器B,然后在机器B执行部署脚本,可以如下方式。

stage('应用部署') {steps {sh '''sshpass -p '机器B root密码' ssh -p 22 -o StrictHostKeyChecking=no root@192.168.108.4 << reallshsh /data/api/dokapp/deploy.shexit'''echo "启动成功"

说明,如果用这种方式,还需要修改部署脚本的那5个外部参数改成固定参数即可。

其它方案2,应用部署这块,将部署脚本放到其它服务器,机器A用shell脚本登录到机器B,然后把部署脚本传送过去再执行脚本,可以如下方式。

stage('应用部署') {steps {sh '''//传送部署脚本到机器B scp /data/jenkins/jenkins_home/workspace/03-dwq-api-Pipeline-vm/deploy.sh root@192.168.108.4:/data/api/dokapp//远程执行脚本 ssh -p 22 root@192.168.108.4 "chmod +x /data/api/dokapp/deploy.sh & sh /data/api/dokapp/deploy.sh"'''echo "启动成功"

说明,此方案中部署脚本放在本地项目根目录,代码提交后部署脚本推送到代码托管服务器(机器D),Jenkins构建后,部署脚本被拉取到Jenkins(机器A)的工作空间目录下。

5、总结

Jenkins 流水线构建 jar 微服务,打包成镜像并发布到生产服务器,大致流程很简单。

1、拉取代码

2、编译,打包成 images 镜像

3、给镜像打标签

4、push镜像到harbor

5、拉取镜像到生产部署服务器

6、部署

当然,还有很多问题,比如项目回滚,多个微服务参数化发布等,还有集群下的发布。后期再弄弄k8s的发布。

● QQ群:330374464
● 公众号:软件测试资源站(ID:testpu)
● CSDN:https://blog.csdn.net/mcfnhm
● 语雀:https://www.yuque.com/testpu/pro

Jenkins+Docker+Spring+Java项目持续集成(单机版)相关推荐

  1. Jenkins学习总结(2)——Jenkins+Maven进行Java项目持续集成

    最近配置了Jenkins服务器,记录下基本过程.(当然还遇到了若干小问题,兵来将挡水来土掩就是了) Jenkins安装 安装Tomcat 从Jenkins官网下载jenkins.war文件.官网地址: ...

  2. jenkins+Docker+springcloud微服务持续集成

    流程说明 本地部署 微服务是可以独立部署的,如果不借助spring-boot-maven插件,package出来的jar包是不能运行的. 借助spring-boot-maven插件package出来的 ...

  3. jenkins+docker部署java项目

    jenkins + maven + jdk + docker + docker register + dockerfile jenkins插件 # 安装插件 SSH# 配置系统设置-> SSH ...

  4. k8s和harbor的集成_爱威尔-基于kubernetes集群的项目持续集成(gitlab+harbor+Jenkins)安装...

    这个算是基于kubernetes集群的项目持续集成的前导篇,先把这用环境搭建好我们后面就可以专注做基于k8s的docker化项目持续集成了. gitlab安装 https://about.gitlab ...

  5. CI/CD——构建企业级Docker+Jenkins+Git+Harbor流水线自动化持续集成持续发布平台

    构建企业级Docker+Jenkins+Git+Harbor流水线自动化持续集成持续发布平台 CI/CD是什么? 持续集成(CI)/持续交付(CD)的优势 自动化部署流程图 Git Github Gi ...

  6. Centos+Gitlab+Jenkins 针对.NET项目持续集成环境搭建和自动化部署

    目录 一.前言 二.系统环境 三.Gitlab安装 3.1 安装依赖软件 3.2 开启postfix 3.3 安装Gitlab 3.4 设置服务器IP和端口 3.5 重置并启动GitLab 3.6 浏 ...

  7. 『中级篇』docker之CI/CD持续集成-项目生成镜像(76)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『中级篇』docker之CI/CD持续集成-项目生成镜像(76) 开始想用docker registry做私有镜像库,后来放弃 ...

  8. 完整项目持续集成方案

    完整项目持续集成方案 [docker|jenkins|git] 工具 本次持续集成使用到工具有:jenkins.maven.jdk.docker.docker私服[register].git. 发布流 ...

  9. 使用Maven+Nexus+Jenkins+Svn+Tomcat+Sonar搭建持续集成环境

    前言 但凡一个略有规模的项目都需要一个持续集成环境的支撑,为什么需要持续集成环境,我们来看一个例子.假如一个项目,由A.B两位程序员来协作开发,A负责前端模块,B负责后端模块,前端依赖后端.A和B都习 ...

最新文章

  1. JavaScript触摸与手势事件
  2. 正则表达式 perl
  3. WAS6集群部署及初步测试
  4. 今天高考,讲几句大实话
  5. 【SAP解决方案干货合集】满满的干货,是您了解华为云SAP解决方案的必备利器
  6. 手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)【转】
  7. 全国计算机等级考试报名入口黑龙江,黑龙江2021年3月计算机等级考试报名入口...
  8. mysql优化的基本原则和方向
  9. (四)Ubuntu 14.04 文件服务器--samba的安装和配置
  10. 编译libxcb时报错:No package 'xcb-proto' found
  11. IDEA放大和缩小代码字体的快捷键设置
  12. (转)关于第一行代码中NotificationCompat失效的解决方法
  13. java-信息安全(十六)-双向认证
  14. 然爸读书笔记(2014-4)----史玉柱自述:我的营销心得
  15. drcom宽带认证登录超时_DrCOM客户端常见问题解决方法
  16. oracle递归查询(层级查询)
  17. 好趣艺术设计部落网页制作案例
  18. 上海应用技术大学计算机研究生院,计算机考研调剂|2018年上海应用技术大学计算机学院计算机大类考研调剂信息...
  19. JavaDoc文档生成
  20. 用JS制作一个简易GPA计算器

热门文章

  1. FATE联邦学习初探(二)
  2. 齐岳定制EG/Li-BH4复合储氢材料/La2Mg17-Ni复合储氢材料/Mg-Nb/Mg-Nb2O5复合储氢粉体复合材料
  3. 华为设备远程登陆配置
  4. 如何批量重命名文件?
  5. 我们可以用什么来编辑html文件,编辑HTML文件要用什么软件?
  6. 微信小程序开发之音乐播放器
  7. ubuntu20.4安装anaconda和pycharm
  8. 华为Mate40系列国行参数价格曝光
  9. 小米6手机投屏到wins 8.1电脑上的软件——scrcpy的安装与使用教程
  10. 微信支付时出现[交易已提交,请查询确认是否已扣款,避免重复操作]