项目
博客
文档
归档
资源链接
关于我
项目
博客
文档
归档
资源链接
关于我
Jenkins流水线脚本使用文档
2024-09-27
·
·
原创
·
其他
·
本文共 2,479个字,预计阅读需要 9分钟。
###### docker安装Jenkins(可执行docker命令) CICD: 持续集成、持续部署 查询docker版本:`yum list docker-ce --showduplicates |sort -r` Jenkin官网下载: https://www.jenkins.io/download/ 选择Docker LTS进入Docker Hub:https://hub.docker.com/r/jenkins/jenkins > 注意:选择最新版本`docker pull jenkins/jenkins:latest`,否则下载插件会失败。 在Docker中下载并允许Jenkins: https://www.jenkins.io/zh/doc/book/installing/: > 推荐:不要使用 `jenkinsci/blueocean`,该版本在2年前停止更新了,下载插件的时候会报错,使用最新的`jenkins/jenkins`,然后在jenkins中下载`Blue Ocean`插件 > > 使用 Blue Ocean: https://www.jenkins.io/zh/doc/book/blueocean/getting-started/ 安装jenkins命令: `--restart=always`设置开机自启动; `-v /var/run/docker.sock:/var/run/docker.sock ` 在docker中可以运行docker `-v /usr/bin/docker:/usr/bin/docker` 载Docker二进制文件 ```dockerfile docker run \ -u root \ -d \ -p 8080:8080 \ -p 50000:50000 \ -v /app/jenkins:/var/jenkins_home \ -v /etc/localtime:/etc/localtime:ro \ -v /var/run/docker.sock:/var/run/docker.sock \ # 挂载Docker套接字 -v /usr/bin/docker:/usr/bin/docker # 挂载Docker二进制文件 --restart=always \ jenkins/jenkins:latest ``` 启动之后,进入`/app/jenkins/hudson.model.UpdateCenter.xml`修改镜像地址 ```xml
default
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
注意:如果`jenkinsci/blueocean`镜像在下载插件报错时,可以先使用`jenkins/jenkins:latest`镜像安装下载插件,没有问题之后,再删除该镜像,将原来的文件目录`/app/jenkins`一样,启动`jenkinsci/blueocean`镜像。 查询容器内的文件 ```dockerfile # 查询docker下所有容器的卷文件 docker volume ls # 找到对应的卷的详细信息 docker volume inspect 0f71ace05d2dad4781288d96fc89d76ca59c8b6cc592e2df9e65c31d44cd8b36 # 根据Mountpoint的路径进入容器里面 [ { "CreatedAt": "2024-09-19T19:28:09-07:00", "Driver": "local", "Labels": { "com.docker.volume.anonymous": "" }, "Mountpoint": "/var/lib/docker/volumes/0f71ace05d2dad4781288d96fc89d76ca59c8b6cc592e2df9e65c31d44cd8b36/_data", "Name": "0f71ace05d2dad4781288d96fc89d76ca59c8b6cc592e2df9e65c31d44cd8b36", "Options": null, "Scope": "local" } ] ``` Jenkins插件搜索:https://plugins.jenkins.io/ui/search/,选择`Release`版本,下载`direct link`,将下载好的插件手动安装: `Manage Jenkins -> Plugins -> Advenced settings -> Deploy Plugin` 将下载的文件导入 安装插件:`Git Parameter` ###### Jenkinsfile编写 参考Jenkins官方文档:https://www.jenkins.io/zh/doc/book/pipeline,编写流水线脚本 在项目下创建Jenkinsfile流水线文件 ```json //写流水线的脚本(声明式、脚本式) pipeline{ //全部的CICD流程都需要在这里定义 //任何一个代理可用就可以执行 agent any //定义一些环境信息 //定义流水线的加工流程 stages { //流水线的所有阶段 // 1.编译 stage('代码编译') { steps { // 要做的事情 echo '编译代码...' } } // 2.测试 stage('代码测试') { steps { // 要做的事情 echo '代码测试...' } } // 3.打包 stage('代码打包') { steps { // 要做的事情 echo '代码打包...' } } // 4.部署 stage('代码部署') { steps { // 要做的事情 echo '代码部署...' } } } } ``` 构建流水线项目:`New Item -> Pipeline -> Pipeline script from SCM - > Git ->配置URL/账号密码/分支 ->Script Path:Jenkinsfile` ###### 生成器/环境变量 流水线语法pipeline-syntax: 代码片段**Snippet Generator**: 例如:邮件操作:mail:Mail -> 配置邮件数据 ```json stage('代码编译') { steps { // 要做的事情 mail bcc: '', body: '成功了', cc: '', from: '', replyTo: '', subject: '测试Jenkins发送邮件', to: '1234@163.com' echo '编译代码...' } } ``` 声明式指令**Generate Declarative Directive**: - agent:Agent -> any:Run on an agent =>生成:`agent any` - 环境参数:environment:Environment -> Add -> Name/Value => - 参数中:凡是取变量值的时候,都用双引号 ```java //任何一个代理可用就可以执行 agent any //定义一些环境信息 environment { mail_message = "成功收到消息了" } stage('代码测试') { steps { // 要做的事情 echo '代码测试...' echo "$mail_message" // 凡是取变量值的时候,都用双引号 echo "${mail_message}" } } ``` ###### 简单设置 操作Liunx命令: sh:Shell Script: ```sh sh 'pwd && ls -alh' sh 'printenv' sh "echo ${GIT_BRANCH}" echo "${GIT_BRANCH}" ``` Jenkins重要的点 > - jenkins的家目录/var/jenkins_home已经被我们docker外部挂载了`/app/jenkins`; > - WORKSPACE(工作空间)=/var/jenkins_home/workspace/blog-2.0 > - 每一个流水线项目,占用一个文件夹位置 > - BUILD_NUMBER=7;当前第几次构建 > - WORKSPACE_TMP(I临时目录)/var/jenkins_home/workspace/blog-2.0@tmp > - JOB_URL=http://192.168.30.130:8080/job/blog-2.0/ ###### 环境检查 ```json // 0.环境检查 stage('环境检查') { steps { sh 'printenv' echo "正在检查环境基本信息..." sh 'java -version' sh 'git --version' sh 'docker version' } } ``` ###### Gitea远程触发Jenkins自动构建 项目配置:`Trigger builds remotely (e.g., from scripts)` ->定义Token 在Gitea的该项目中配置web钩子: - URL: http://Jenkins的用户名:密码@192.168.30.130:8080/job/blog-2.0/build?token=blogHooks - 触发条件:推送事件 ###### 插件安装 - Docker Pipeline&&Docker: 安装DockerPipeline会自动安装docker相关的。这个允许我们自定义agent使用docker环境 - Git Parameter: 解析git参数,允许我们选择分支进行构建 - Active Choices: 可以做到参数的级联选择;例如部署到哪里,集群大且多,北京3区的第2个机房,需要联动选择 - Generic Webhook Trigger: 通用的webhook触发器,构建更强大的webhook功能;通用的Web远程触发插件,比默认的功能强大 - Role-based Authorization Strategy: RBAC权限指定,给一个用户精确指定权限,例如只能查看流水线权限 - List Git Branches Parameter: 列出分支参数 - Build With Parameters: 基于自定义参数构建 - Stage View: 流水构建图 - Blue Ocean:安装 Blue Ocean ###### 自定义maven代理,使用自定义配置文件,本地仓库 容器的缓存数据:https://www.jenkins.io/zh/doc/book/pipeline/docker/ ```json agent { docker { image 'maven:3-alpine' args '-v $HOME/.m2:/root/.m2' } } ``` jenkins不配置任何环境的情况下,仅使用docker兼容所有场景 ```json agent { docker { image 'maven:3-alpine' //设置本地仓库镜像,在settings中配置容器仓库/root/.m2 args '-v /app/jenkins/appconfig/maven/.m2:/root/.m2' } } steps { // 打包跳过单元测试,默认是从maven中央仓库下载 sh 'mvn -clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true' } ``` 在宿主机目录`/app/jenkins/`下新建目录`appconfig/maven`,jenkins中所有的配置文件放到`appconfig`目录下,在`maven`下添加`settings.xml`配置文件 ```xml
/root/.m2
alimaven
aliyun maven
http://maven.aliyun.com/nexus/content/groups/public/
central
``` 此时需要重启jenkins镜像,将映射的文件在docker中生效: `/var/jenkins_home/appconfig/maven/settings.xml` Jenkinsfile文件配置 ```json //写流水线的脚本(声明式、脚本式) pipeline{ //全部的CICD流程都需要在这里定义 //任何一个代理可用就可以执行 // agent none //以后所有的stage都必须指定自己的 agent any //定义一些环境信息 environment { mail_message = "成功收到消息了" } //定义流水线的加工流程 stages { //流水线的所有阶段 // 0.环境检查 stage('环境检查') { steps { // 打印环境信息 sh 'printenv' echo "正在检查环境基本信息..." sh 'java -version' sh 'git --version' sh 'pwd && ls -alh' } } // 1.编译 stage('代码编译') { // jenkins不配置任何环境的情况下,仅使用docker兼容所有场景 agent { docker { image 'maven:3-alpine' //设置本地仓库镜像,在settings中配置容器仓库/root/.m2 args '-v /app/jenkins/appconfig/maven/.m2:/root/.m2' } } steps { // git下载来的代码目录下 sh 'pwd && ls -alh' sh 'mvn -v' // 打包跳过单元测试,默认是从maven中央仓库下载 sh 'mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true' // jar包推送给maven repo,nexus // 如何使用阿里云的maven仓库 } } // 2.测试 stage('代码测试') { steps { echo '代码测试...' } } // 3.打包 stage('生成镜像') { steps { echo '代码打包...' // 检查Jenkins的docker命令是否能运行 sh 'docker version' sh 'pwd && ls -alh' } } // 4.部署 stage('代码部署') { steps { echo '代码部署...' } } } } ``` 临时容器导致的问题: 1. 第一次检出代码,默认在/var/jenkins_home/workspace/【blog-2.0】。 2. 使用dockerl临时agent的时候,每一个临时容器运行又分配临时目录/var/jenkins_home/workspace/blog-2.0@2;默认就是workspace/blog-2.0的内容 3. 在临时容器里面运行的mvn package命令,会在/var/jenkins_home/workspace/blog-2.0@2进行工作0 4. package到了/var/jenkins_home/workspace/blog-2.0@2位置 5. 进入下一步进行打包镜像,又会回到/var/jenkins_home/workspace/【blog-2.0】这个默认位I置 6. 这个位置没有运行过mvn clean package,没有target。 ###### 编写Dockerfile&配置全局的工作空间&打包部署 Dockerfile ```dockerfile FROM adoptopenjdk/openjdk11:jre11u-nightly LABEL maintainer="xx@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 8056 ENTRYPOINT ["sh","-c","java -Djava.security.egd=file:/dev/./urandom $JAVA_OPTS -jar /app.jar $PARAMS" ] ``` Jenkinsfile ```JSON pipeline{ agent any environment { // 定义全局动态的工作空间 WS = "${WORKSPACE}" } stages { stage('环境检查') { steps { // 打印环境信息 sh 'printenv' echo "正在检查环境基本信息..." sh 'java -version' sh 'git --version' sh 'pwd && ls -alh' } } // 1.编译 stage('maven编译') { agent { docker { image 'maven:3-alpine' args '-v /app/jenkins/appconfig/maven/.m2:/root/.m2' } } steps { sh 'pwd && ls -alh' sh 'mvn -v' sh "echo 默认的工作目录: ${WS}" // 要进入工作空间进行打包,否则会获取不到target目录 sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true ' } } // 2.测试 stage('代码测试') { steps { } } // 3.打包 stage('生成镜像') { steps { sh 'pwd && ls -alh' // 启动脚本命令,以项目名称:yn-blog2.0 sh 'docker build -t yn-blog2.0 .' } } // 4.部署 stage('代码部署') { steps { echo '代码部署...' // docker删除且部署命令 sh 'docker rm -f blog-admin-dev' sh 'docker run -d -p 8881:8056 --name blog-admin-dev yn-blog2.0' } } } } ``` 此时访问:8881就可以获取到服务 **注意点**: 1. 工作空间,在流水线中执行命令的时候工作空间是切换的,会变化。定义全局的工作空间来使用 2. 命令`cd ${WS} && mvn clean`中不能拆开,否则是在不同的工作空间执行的。每一行指令都是基于当前环境信息。和上下指令无关 3. 在启动docker服务的时候,要先删除之前的docker服务 ###### 发送邮件通知 进入流水线项目 -> Pipeline Syntax -> **Generate Declarative Directive** -> post: 后置 感知Jenkins任何阶段出问题时的处理: 在全局方一个后置处理,感知失败或者成功 ```json pipeline{ agent any ... // 后置执行 post { failure { echo "失败,出问题了..... $currentBuild.result " } success { echo "成功了.... $currentBuild.result " } } } ``` 系统配置管理员的邮件 System - Jenkins Location - System Admin e-mail address =>配置管理员的邮箱地址:xx@qq.com Extended E-mail Notification - SMTP server: smtp.qq.com / SMTP Port:465 ```json // 5.推送报告 stage('发送报告') { steps { echo "发送报告" mail bcc: '', body: '成功了', cc: '', from: '', replyTo: '', subject: '测试Jenkins发送邮件', to: '1234@163.com' // 发送短信 // sh 'curl -i -k -X POST 'https://wwww.wex.com' -H Authorization: 你自己的AppCode' ' } } ``` 邮件模板 ``` 模板Default Content分享: (本邮件是程序自动下发的,请勿回复,
请相关人员fix it,重新提交到git 构建
)
项目名称:$PROJECT_NAME
构建编号:$BUILD_NUMBER
GIT版本号:${GIT_REVISION}
构建状态:$BUILD_STATUS
触发原因:${CAUSE}
构建日志地址:
${BUILD_URL}console
构建地址:
$BUILD_URL
变更集:${JELLY_SCRIPT,template="html"}
``` ###### CICD **推送镜像** 配置阿里云镜像仓库:https://cr.console.aliyun.com/ 参考: [42| 容器化部署Docker镜像打包&私有镜像仓和自动化构建脚本编写](https://blog.virtualagent.cn/blog/details/id/226) 配置全局的阿里云账号密码:Manage Jenkins - Credentials - System - Global credentials (unrestricted) ID: aliyun-docker-repo 环境配置:https://www.jenkins.io/zh/doc/book/pipeline/syntax/ ```json environment { AN_ACCESS_KEY = credentials('my-prefined-secret-text') } ``` 在全局定义阿里云容器账号和镜像版本 ```json environment { IMAGE_VERSION = "v1.0" // 引用Jenkins配置的全局阿里云容器账号密码 ALIYUN_SECRTE = credentials('aliyun-docker-repo') } ``` 在生成镜像后配置:推送镜像 ```json stage('推送镜像') { steps { echo '推送镜像...' //使用定义的环境变量_USER:用户名,_PSW:密码 sh 'docker login -u ${ALIYUN_SECRTE_USR} -p ${ALIYUN_SECRTE_PSW} registry.cn-hangzhou.aliyuncs.com' // 这里的ImageId就是上一步打包镜像:yn-blog2.0:latest,可以简写去掉latest sh 'docker tag yn-blog2.0 registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${IMAGE_VERSION}' sh 'docker push registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${IMAGE_VERSION}' } } ``` **发布版本,自己确认** 语法: https://www.jenkins.io/zh/doc/book/pipeline/syntax/ , => input 进入项目,使用语法生成器: **Generate Declarative Directive** - iput Message : 需要部署到生产环境吗? OK Button Caption: 需要 **Multi-line String Parameter**: Name: IMAGE_VERSION, Default Value:v 1.2, Description:生产环境需要部署的版本 ```json input { message '需要部署到生产环境吗?' ok '需要' parameters { text defaultValue: 'v1.2', description: '生产环境需要部署的版本', name: 'APP_VERSION' } } ``` 使用文档中的语法: ```json input { message "需要部署到生产环境吗?" ok "是的,提交吧" //submitter "alice,bob" parameters { string(name: 'APP_VERSION', defaultValue: 'v 1.2', description: '请指定生产版本号') } } ``` 就使用生成器的,此时在推送镜像时会暂停,需要去选择版本号 ```json environment { APP_VERSION = "v1.0" } // 4.推送镜像 stage('推送镜像') { input { message '需要部署到生产环境吗?' ok '需要' parameters { text defaultValue: 'v1.2', description: '生产环境需要部署的版本', name: 'APP_VERSION' choice choices: ['bj-01','sh-02','wh-03'], description: '部署的大区', name: 'DEPLOY_WHERE' } } steps { echo '推送镜像...' sh 'docker login -u ${ALIYUN_SECRTE_USR} -p ${ALIYUN_SECRTE_PSW} registry.cn-hangzhou.aliyuncs.com' sh 'docker tag yn-blog2.0 registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' script { //groovy def where = "${DEPLOY_WHERE}" if (where == "bj-01"){ sh "echo 我帮你部署到${DEPLOY_WHERE}区了" } } sh 'docker push registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' } } ``` 使用生成器引入秘钥: **Snippet Generator** - withCredentials - **Username and password (separated)** Varilable: aliyRepo,Username Variable:ali_user, Password Variable:ali_pwd, 选择配置好的账号密码,点击生成 ```json withCredentials([usernamePassword(credentialsId: 'aliyun-docker-repo', passwordVariable: 'ali_pwd', usernameVariable: 'ali_user')]) { // some block } ``` 更新后 ```json // 4.推送镜像 stage('推送镜像') { input { message '需要部署到生产环境吗?' ok '需要' parameters { text defaultValue: 'v1.2', description: '生产环境需要部署的版本', name: 'APP_VERSION' choice choices: ['bj-01','sh-02','wh-03'], description: '部署的大区', name: 'DEPLOY_WHERE' } } steps { echo '推送镜像...' script { //groovy def where = "${DEPLOY_WHERE}" if (where == "bj-01"){ sh "echo 我帮你部署到${DEPLOY_WHERE}区了" } withCredentials([usernamePassword(credentialsId: 'aliyun-docker-repo', passwordVariable: 'ali_pwd', usernameVariable: 'ali_user')]) { sh 'docker login -u ${ali_user} -p ${ali_pwd} registry.cn-hangzhou.aliyuncs.com' sh 'docker tag yn-blog2.0 registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' } } sh 'docker push registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' } } ``` ###### 其他问题 ```yaml server: shutdown: graceful #springboot中的优雅停机 ``` 视频地址: https://www.bilibili.com/video/BV1Tm4HevEWu 完整的Jenkinsfile脚本: ```json //写流水线的脚本(声明式、脚本式) pipeline{ //全部的CICD流程都需要在这里定义 //任何一个代理可用就可以执行 // agent none //以后所有的stage都必须指定自己的 agent any //定义一些环境信息 environment { mail_message = "成功收到消息了" WS = "${WORKSPACE}" APP_VERSION = "v1.0" // 引用Jenkins配置的全局阿里云容器账号密码 ALIYUN_SECRTE = credentials('aliyun-docker-repo') } //定义流水线的加工流程 stages { //流水线的所有阶段 // 0.环境检查 stage('环境检查') { steps { // 打印环境信息 sh 'printenv' echo "正在检查环境基本信息..." sh 'java -version' sh 'git --version' sh 'pwd && ls -alh' } } // 1.编译 stage('maven编译') { // jenkins不配置任何环境的情况下,仅使用docker兼容所有场景 agent { docker { image 'maven:3-alpine' //设置本地仓库镜像,在settings中配置容器仓库/root/.m2 args '-v /app/jenkins/appconfig/maven/.m2:/root/.m2' } } steps { //mail bcc: '', body: '成功了', cc: '', from: '', replyTo: '', subject: '测试Jenkins发送邮件', to: 'yuanjs625@163.com' // git下载来的代码目录下 sh 'pwd && ls -alh' sh 'mvn -v' // 打包跳过单元测试,默认是从maven中央仓库下载 sh "echo 默认的工作目录: ${WS}" sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true ' // jar包推送给maven repo,nexus // 如何使用阿里云的maven仓库 } } // 2.测试 stage('代码测试') { steps { echo '代码测试...' } } // 3.打包 stage('生成镜像') { steps { echo '代码打包...' // 检查Jenkins的docker命令是否能运行 sh 'docker version' sh 'pwd && ls -alh' // 启动脚本命令 sh 'docker build -t yn-blog2.0 .' } } // 4.推送镜像 stage('推送镜像') { input { message '需要部署到生产环境吗?' ok '需要' parameters { text defaultValue: 'v1.2', description: '生产环境需要部署的版本', name: 'APP_VERSION' choice choices: ['bj-01','sh-02','wh-03'], description: '部署的大区', name: 'DEPLOY_WHERE' } } steps { echo '推送镜像...' // sh 'docker login -u ${ALIYUN_SECRTE_USR} -p ${ALIYUN_SECRTE_PSW} registry.cn-hangzhou.aliyuncs.com' // sh 'docker tag yn-blog2.0 registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' script { //groovy def where = "${DEPLOY_WHERE}" if (where == "bj-01"){ sh "echo 我帮你部署到${DEPLOY_WHERE}区了" } withCredentials([usernamePassword(credentialsId: 'aliyun-docker-repo', passwordVariable: 'ali_pwd', usernameVariable: 'ali_user')]) { sh 'docker login -u ${ali_user} -p ${ali_pwd} registry.cn-hangzhou.aliyuncs.com' sh 'docker tag yn-blog2.0 registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' } } sh 'docker push registry.cn-hangzhou.aliyuncs.com/docker-yuanjs/blog-admin-dev:${APP_VERSION}' } } // 4.部署 stage('代码部署') { steps { echo '代码部署...' // docker删除且部署命令 sh 'docker rm -f blog-admin-dev' sh 'docker run -d -p 8881:8056 --name blog-admin-dev yn-blog2.0' } } // 5.推送报告 stage('发送报告') { steps { echo "发送报告" // mail bcc: '', body: '成功了', cc: '', from: '', replyTo: '', subject: '测试Jenkins发送邮件', to: '782063616@qq.com' // 发送短信 // sh 'curl -i -k -X POST 'https://wwww.wex.com' -H Authorization: 你自己的AppCode' ' } } } // 后置执行 post { failure { echo "失败,出问题了..... $currentBuild.result " } success { echo "成功了.... $currentBuild.result " } } } ```