Jenkins+Docker+Spring+Java项目持续集成(单机版)
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项目持续集成(单机版)相关推荐
- Jenkins学习总结(2)——Jenkins+Maven进行Java项目持续集成
最近配置了Jenkins服务器,记录下基本过程.(当然还遇到了若干小问题,兵来将挡水来土掩就是了) Jenkins安装 安装Tomcat 从Jenkins官网下载jenkins.war文件.官网地址: ...
- jenkins+Docker+springcloud微服务持续集成
流程说明 本地部署 微服务是可以独立部署的,如果不借助spring-boot-maven插件,package出来的jar包是不能运行的. 借助spring-boot-maven插件package出来的 ...
- jenkins+docker部署java项目
jenkins + maven + jdk + docker + docker register + dockerfile jenkins插件 # 安装插件 SSH# 配置系统设置-> SSH ...
- k8s和harbor的集成_爱威尔-基于kubernetes集群的项目持续集成(gitlab+harbor+Jenkins)安装...
这个算是基于kubernetes集群的项目持续集成的前导篇,先把这用环境搭建好我们后面就可以专注做基于k8s的docker化项目持续集成了. gitlab安装 https://about.gitlab ...
- CI/CD——构建企业级Docker+Jenkins+Git+Harbor流水线自动化持续集成持续发布平台
构建企业级Docker+Jenkins+Git+Harbor流水线自动化持续集成持续发布平台 CI/CD是什么? 持续集成(CI)/持续交付(CD)的优势 自动化部署流程图 Git Github Gi ...
- Centos+Gitlab+Jenkins 针对.NET项目持续集成环境搭建和自动化部署
目录 一.前言 二.系统环境 三.Gitlab安装 3.1 安装依赖软件 3.2 开启postfix 3.3 安装Gitlab 3.4 设置服务器IP和端口 3.5 重置并启动GitLab 3.6 浏 ...
- 『中级篇』docker之CI/CD持续集成-项目生成镜像(76)
原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『中级篇』docker之CI/CD持续集成-项目生成镜像(76) 开始想用docker registry做私有镜像库,后来放弃 ...
- 完整项目持续集成方案
完整项目持续集成方案 [docker|jenkins|git] 工具 本次持续集成使用到工具有:jenkins.maven.jdk.docker.docker私服[register].git. 发布流 ...
- 使用Maven+Nexus+Jenkins+Svn+Tomcat+Sonar搭建持续集成环境
前言 但凡一个略有规模的项目都需要一个持续集成环境的支撑,为什么需要持续集成环境,我们来看一个例子.假如一个项目,由A.B两位程序员来协作开发,A负责前端模块,B负责后端模块,前端依赖后端.A和B都习 ...
最新文章
- JavaScript触摸与手势事件
- 正则表达式 perl
- WAS6集群部署及初步测试
- 今天高考,讲几句大实话
- 【SAP解决方案干货合集】满满的干货,是您了解华为云SAP解决方案的必备利器
- 手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)【转】
- 全国计算机等级考试报名入口黑龙江,黑龙江2021年3月计算机等级考试报名入口...
- mysql优化的基本原则和方向
- (四)Ubuntu 14.04 文件服务器--samba的安装和配置
- 编译libxcb时报错:No package 'xcb-proto' found
- IDEA放大和缩小代码字体的快捷键设置
- (转)关于第一行代码中NotificationCompat失效的解决方法
- java-信息安全(十六)-双向认证
- 然爸读书笔记(2014-4)----史玉柱自述:我的营销心得
- drcom宽带认证登录超时_DrCOM客户端常见问题解决方法
- oracle递归查询(层级查询)
- 好趣艺术设计部落网页制作案例
- 上海应用技术大学计算机研究生院,计算机考研调剂|2018年上海应用技术大学计算机学院计算机大类考研调剂信息...
- JavaDoc文档生成
- 用JS制作一个简易GPA计算器
热门文章
- FATE联邦学习初探(二)
- 齐岳定制EG/Li-BH4复合储氢材料/La2Mg17-Ni复合储氢材料/Mg-Nb/Mg-Nb2O5复合储氢粉体复合材料
- 华为设备远程登陆配置
- 如何批量重命名文件?
- 我们可以用什么来编辑html文件,编辑HTML文件要用什么软件?
- 微信小程序开发之音乐播放器
- ubuntu20.4安装anaconda和pycharm
- 华为Mate40系列国行参数价格曝光
- 小米6手机投屏到wins 8.1电脑上的软件——scrcpy的安装与使用教程
- 微信支付时出现[交易已提交,请查询确认是否已扣款,避免重复操作]