基于Docker+Jenkins+Git的CI/CD实战

与上一篇随笔:基于 Jenkins+Docker+Git 的CI流程初探 有所不同,该内容更偏向于实际业务的基础需求。

有几点需要注意:

  • 该实战中没有涉及到镜像仓库,所以略去了镜像推送阶段,可以参考基于 Jenkins+Docker+Git 的CI流程初探
  • 与上一篇对比,该实战是基于外网服务器进行的,所以加入了Jenkins自动触发拉取代码以及发送构建报告功能。
  • 实战中的Jenkins也是基于docker运行,对于Jenkins数据持久化是通过VOLUME实现的。
  • 不再进行自建git代码仓库,选择使用Gitee管理代码。
  • 实验环境均已提前准备完毕。

1、Jenkins启动

docker run \
-u root \
-d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
-v /etc/localtime:/etc/localtime:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
--restart=always \
jenkinsci/blueocean

启动后设置用户与密码

2、新建item

名称:java-devops-demo

创建流水线

选择保存

Jenkins流水线工作流程:

  先定义一个流水线项目,指定项目的git位置

  流水线启动

  a.先去git位置自动拉取代码

  b.解析拉取代码里面的Jenkinsfile文件

  c.按照Jenkinsfile指定的流水线开始加工项目

Jenkins重要的点

  1) jenkins的家目录 /var/jenkins_home 已经被我们docker外部挂载了/var/lib/docker/volumes/jenkins-data/_data

  2)WORKSPACE(工作空间)=/var/jenkins_home/workspace/java-devops-demo每一个流水线项目,占用一个文件夹位置

  3)BUILD_NUMBER=5;当前第几次构建

  4)WORKSPACE_TMP(临时目录)=/var/jenkins_home/workspace/java-devops-demo@tmp

3、定义Jenkinsfile与Dockerfile具体内容

Jenkinsfile部分是逐步测试,按阶段写成。

pipeline{
//全部的CI/CD流程都需要在这里定义
//任何一个代理可用就可以执行
agent any //定义一些环境信息
environment {
WS = "${WORKSPACE}"
} //定义流水线的加工流程
stages{ stage('环境检查'){
steps {
sh 'printenv'
echo "正在检测基本信息"
sh 'java -version'
sh 'git --version'
sh 'docker version'
sh 'pwd && ls -alh'
}
} //1、编译 "abc"
stage('maven编译'){
agent {
docker {
image 'maven:3-alpine'
args '-v /var/jenkins_home/appconfig/maven/.m2:/root/.m2'
//docker run -v /var/jenkins_home/appconfig/maven/.m2:/root/.m2
}
}
//要做的所有事情
//jenkins不配置任何环境的情况下, 仅适用docker兼容所有场景
steps{
echo "编译..."
sh 'pwd && ls -alh'
sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true'
}
}
//2、打包
stage('生成镜像'){
steps{
sh 'pwd && ls -alh'
sh 'docker version'
sh 'docker build -t java-devops-demo .'
}
} //3、部署
stage('部署'){
steps{
echo "部署..."
sh 'docker rm -f java-devops-demo-dev'
sh 'docker run -d -p 80:8080 --name java-devops-demo-dev java-devops-demo'
}
} //4、推送报告
stage("发送报告"){
steps {
//短信通知,购买api接口即可
// sh 'curl -i -k -X POST 'https://gyytz.market.alicloudapi.com/sms/smsSend?mobile=mobile&param=**code**%3A12345%2C**minute**%3A5&smsSignId=2e65b1bb3d054466b82f0c9d125465e2&templateId=908e94ccf08b4476ba6c876d13f084ad' -H 'Authorization:APPCODE dddddddd''
//REST API 所有都行
// sh 'curl '
echo '准备发送报告'
emailext body: '''<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<h3>本邮件由系统自动发出,请勿回复!</h3>
<tr>
<br/>
各位同事,大家好,以下为${PROJECT_NAME }项目构建信息</br>
<td><font color="#CC0000">构建结果 - ${BUILD_STATUS}</font></td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">构建信息</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li>
<li>构建编号 : 第${BUILD_NUMBER}次构建</li>
<li>触发原因: ${CAUSE}</li>
<li>构建状态: ${BUILD_STATUS}</li>
<li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建 Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul> <h4><font color="#0B610B">最近提交</font></h4>
<ul>
<hr size="2" width="100%" />
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
</ul>
详细提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/> </td>
</tr>
</table>
</body>
</html>''', subject: '${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志', to: 'xxxxx@163.com'
}
}
}
//后置处理过程
post {
failure {
echo "这个阶段 完蛋了.... $currentBuild.result"
}
success {
echo "这个阶段 成了.... $currentBuild.result"
}
}
}

Dockerfile:

#这个也得有
FROM openjdk:8-jre-alpine
LABEL maintainer="xxxxxxx@qq.com"
#复制打好的jar包
COPY target/*.jar /app.jar
RUN apk add -U tzdata; \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; \
echo 'Asia/Shanghai' >/etc/timezone; \
touch /app.jar; ENV JAVA_OPTS=""
ENV PARAMS="" EXPOSE 8080 ENTRYPOINT [ "sh", "-c", "java -Djava.security.egd=file:/dev/./urandom $JAVA_OPTS -jar /app.jar $PARAMS" ]

Jenkinsfile与Dockerfile均位于java-devops-jemo目录下,由Jenkins从git仓库拉取。

4、远程构建触发

期望效果: 远程的github代码提交了,jenkins流水线自动触发构建。

实现条件:

  • 保证jenkins所在主机能被远程访问。
  • jenkins中远程触发需要权限,我们应该使用用户进行授权。
  • 配置gitee,webhook进行触发。

实现过程:

1)进入流水线配置页,填入身份验证令牌

2)远程构建即使配置了gitee/github 的webhook,默认会403。我们应该使用用户进行授权

  a.创建一个用户 (主界面>管理Jenkins>管理user>新建用户)

  b.新建用户后一定要重新登陆激活一次,进入用户列表>点击当前用户名>设置

  c.生成一个apitoken (生成后立即复制,只出现一次)

3)码云端配置WebHooks,进入码云对应代码仓库-配置-WebHooks-添加WebHook

URL配置格式:http://dk:用户dk的apitoken@主机的公网ip:8080/job/java-devops-demo/build?token=身份验证令牌

添加成功后可测试与Jenkins主机的连通性。

至此,当本地修改代码,git push提交到gitee/github后,Jenkins就能够自动构建,构建成功即可查看前端页面的变化。

5、配置maven环境

(使用自定义agent的方式引入maven环境,利用多阶段构建不同场景下的复杂环境)

1)安装docker pipeline插件

2)自定义agent(在stages内部)

3)配置maven加速(配置国内阿里云)

把Maven的配置文件放在jenkins-data里面的某个位置。默认所有的可变配置项都推荐放在jenkins-home的位置,增强移植性。

4)缓存必要jar包,下次构建无需下载

agent {
docker {
image 'maven:3-alpine' //用完就会杀掉
args '-v /var/jenkins_home/appconfig/maven/.m2:/root/.m2'
// 将jar包映射到宿主机上/var/jenkins_home/appconfig/maven/.m2目录中
// 也可以将jar包以数据卷方式挂载到宿主机
}
}
注:jenkins不配置任何环境的情况下, 仅适用docker兼容所有场景。
  • 临时容器导致的问题(每个stage都会回到默认workspace,临时容器产生的打包数据不能被利用)
    • 第一次检出代码,默认在 /var/jenkins_home/workspace/【java-devops-demo】
    • 使用docker临时agent的时候,每一个临时容器运行又分配临时目录 /var/jenkins_home/workspace/java-devops-demo@2;默认就是workspace/java-devops-demo 的内容
    • 在临时容器里面 运行的mvn package命令,会在 /var/jenkins_home/workspace/java-devops-demo@2 进行工作
    • package到了 /var/jenkins_home/workspace/java-devops-demo@2 位置
    • 进入下一步(stage)进行打包镜像,又会回到 /var/jenkins_home/workspace/【java-devops-demo】(默认workspace)这个位置
    • 这个位置没有运行过 mvn clean package ,所以没有target。 默认的 工作目录 没有 target

     解决方法:在临时容器内部切换到Jenkins的默认工作目录,再进行maven打包。

6、邮件推送

使用邮件扩展插件:Email Extension Plugin-2.71 (对于每个stage执行的任务成功与否可以通过后置执行post来进行感知)

系统管理>系统配置>配置管理员邮箱(系统管理员邮件地址)、SMTP服务相关及其他

下图Use SMTP Authentication部分在高版本插件中已不再支持

填写完毕,可以通过发送测试邮件进行测试。

上图的邮件用户的授权码需要配置邮件发送的认证权限信息

  1. 登录自己邮箱,开启POP3/SMTP邮件服务
  2. 获取到自己的授权码(tlqhksolsmeodjad)
  3. 配置并测试好邮件发送即可

邮件模板内容见Jenkinsfile中报告推送阶段。

至此,开发提交代码后,将自动触发构建过程,构建结束后发送此次构建邮件报告如下:

DevOps实战(Docker+Jenkins+Git)的更多相关文章

  1. Docker+Jenkins+Git发布SpringBoot应用

    Doccker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之 ...

  2. Docker——Jenkins + Git + Registry构建自动化持续集成环境(CI/CD)

    前言 在互联网时代,对于每一家公司,软件开发和发布的重要性不言而喻,目前已经形成一套标准的流程,最重要的组成部分就是持续集成(CI)及持续部署.交付(CD). 本文基于Jenkins+Docker+G ...

  3. Docker: Jenkins与Docker的自动化CI/CD流水线实战

    什么是CI/CD 持续集成(Continuous Integration,CI):代码合并.构建.部署.测试都在一起,不断地执行这个过程,并对结果反馈.持续部署(Continuous Deployme ...

  4. ASP.NET Core & Docker & Jenkins 零基础持续集成实战

    原文:ASP.NET Core & Docker & Jenkins 零基础持续集成实战 一.本系列教程说明 源代码管理工具:Gogs 持续集成工具:Jenkins 容器:Docker ...

  5. 手把手0基础项目实战(一)——教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)...

    原文:手把手0基础项目实战(一)--教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)... 本文你将学到什么? 本文将以原理+实战的方式,首先对& ...

  6. SpringCloud+Docker+Jenkins+GitLab+Maven实现自动化构建与部署实战

    1.前言与初衷 本文章会涉及Docker常见命令基础知识点结合不同场景实操一起使用. 本文章会涉及结合工作过程中部署不同环境服务器的项目案例场景为初心进行实际细讲. 本文章主要讲述Docker.Jen ...

  7. jenkins+git+docker实验环境的搭建

    持续集成(c/i)的实验环境 git/harbor服务器    ip 192.168.200.132 docker服务器          ip 192.168.200.149 Jenkins服务器 ...

  8. Jenkins+Git+Docker+K8s部署

    准备工作 Jenkins已安装 Docker和K8s部署运行成功 代码管理工具使用Git 最近公司项目使用Jenkins+Git+Docker+K8s进行持续化构建部署,这里笔者整理了一下构建部署的相 ...

  9. Postman+newman+jenkins+git实战

    一.接口分类,流程,用例设计 接口分类: 外部接口:被测系统与外部其他系统之间的接口. 承保系统(被测系统),核算系统. 内部接口:被测系统内部各个子模块之间的接口. 承保系统(A模块,B模块) 测试 ...

随机推荐

  1. BZOJ3971 [WF2013]Матрёшка

    *XXXIV. BZOJ3971 [WF2013]Матрёшка 摘自 DP 做题记录 II 例题 XXXIV. 仍然是神仙区间 DP. 直接设状态 \(f_{i,j}\) 表示区间 \([i,j] ...

  2. JS设计模式之建造者模式

    建造者模式(builder pattern)属于创建型模式的一种,提供一种创建复杂对象的方式.它将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式是一步一步的创建 ...

  3. Python 包管理工具 pip 与 conda

    简介 pip是接触 python 后最早认识的包管理工具.通过使用 pip 能够自动下载和解决不同 python 模块的依赖问题,使 python 的配置过程变得简单. 与 pip 类似,conda ...

  4. 【ThermoRawFileParser】质谱raw格式转换mgf

    众所周知,Proteowizard MSconvert用于质谱原始数据的格式转换,但主要平台是windows,要想在Linux上运行需要打Docker或Wine,对于普通用户来说还是很困难的,想想质谱 ...

  5. C语言计算fastq文件GC含量

    C语言小练习:计算非压缩fastq格式的GC含量 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <strin ...

  6. HMS Core Discovery直播预告 | AI画质增强 ,开启超清视界

    [直播入口] B站华为开发者联盟:http://live.bilibili.com/22551651 4K.8K视频屡见不鲜,HD.FHD分辨率成小屏标配,当网络卡顿.视频自动切换到较低画质时,用户最 ...

  7. jsp的动态包含和静态包含

    jsp的动态包含和静态包含 例如:提取一个公共的页面(top.jsp)到/WEB-INF/jsp/common/目录下 动态包含: 被包含的页面也会独立编译,生成字节码文件,一般包含页面信息频繁变化的 ...

  8. Scala(七)【异常处理】

    目录 一.try-catch-finally 二.Try(表达式).getOrElse(异常出现返回的默认值) 三. 直接抛出异常 一.try-catch-finally 使用场景:在获取外部链接的时 ...

  9. 容器之分类与各种测试(三)——list部分用法

    list是一个双向链表 例程 #include<stdexcept> #include<memory.h> #include<string> #include< ...

  10. How does “void *” differ in C and C++?

    C allows a void* pointer to be assigned to any pointer type without a cast, whereas C++ does not; th ...