一、DevOps概念
1、DevOps是什么
DevOps:Development和Operations的组合
- DevOps 看作
开发(软件工程)、技术运营和质量保障(QA)三者的交集。 - 突出重视软件开发人员和运维人员的沟通合作,通过自动化流程来使得软件构建、测试、 发布更加快捷、频繁和可靠。
- DevOps 希望做到的是软件产品交付过程中 IT 工具链的打通,使得各个团队减少时间损 耗,更加高效地协同工作。专家们总结出了下面这个 DevOps 能力图,良好的闭环可以大大 增加整体的产出。
2、CICD是什么
持续集成持续部署
1、基本理念
1、持续集成(Continuous Integration)
持续集成是指软件个人研发的部分向软件整体部分交付,频繁进行集成以便更快地发现 其中的错误。“持续集成”源自于极限编程(XP),是 XP 最初的 12 种实践之一。
CI 需要具备这些:
- 全面的自动化测试。这是实践持续集成&持续部署的基础,同时,选择合适的 自动化测试工具也极其重要;
- 灵活的基础设施。容器,虚拟机的存在让开发人员和 QA 人员不必再大费周 折;
- 版本控制工具。如 Git,CVS,SVN 等;
- 自动化的构建和软件发布流程的工具,如 Jenkins,flow.ci;
- 反馈机制。如构建/测试的失败,可以快速地反馈到相关负责人,以尽快解决达到一个更稳定的版本。
2、持续交付(Continuous Delivery)
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。持续交付优先于整个产品生命周期的软件部署,建立 在高水平自动化持续集成之上。
持续交付和持续集成的优点非常相似:
- 快速发布。能够应对业务需求,并更快地实现软件价值。
- 编码->测试->上线->交付的频繁迭代周期缩短,同时获得迅速反馈;
- 高质量的软件发布标准。整个交付过程标准化、可重复、可靠,
- 整个交付过程进度可视化,方便团队人员了解项目成熟度;
- 更先进的团队协作方式。从需求分析、产品的用户体验到交互 设计、开发、测试、运维等角色密切协作,相比于传统的瀑布式软件团队,更少浪费。
3、持续部署(Continuous Deployment)
持续部署是指当交付的代码通过评审之后,自动部署到生产环境中。持续部署是持续交付的最高阶段。这意味着,所有通过了一系列的自动化测试的改动都将自动部署到生产环境。它也可以被称为“Continuous Release”。
“开发人员提交代码,持续集成服务器获取代码,执行单元测试,根据测试结果决定是否部署到预演环境,如果成功部署到预演环境,进行整体验收测试,如果测试通过,自动部署到产品环境,全程自动化高效运转。
持续部署主要好处是,可以相对独立地部署新的功能,并能快速地收集真实用户的反馈。
“You build it, you run it”,这是 Amazon 一年可以完成 5000 万次部署, 平均每个工程师每天部署超过 50 次的核心秘籍。
5000/365 = 15 万次
开发人员代码敲完。可以release的时候,提交代码, 剩下的全部一站式自动搞定
2、最佳实践
1、内循环与外循环
内循环(开发要做的事情):
- 编码、测试、运行、debug、提交
代码推送到代码仓库(svn,git)【代码回滚】
进行CI过程(持续集成),万物皆可容器化。打包成一个Docker镜像
镜像推送到镜像仓库
测试
持续部署流程(CD),拿到之前的镜像,进行CD。怎么放到各种环境。uat、test、prod
外循环()
- 运行时监控
- 生产环境的管理
- 监控
- 线上反馈到开发
来到内循环
2、实践流程
新功能,bug修复。
创建分支来做这个事情(开发功能)
提交分支的代码改变
进入持续集成流程
- 当前分支代码功能性自动化构建和测试
- 自动工具推送这次提交
- 自动化集成测试
- 可以看到效果
- 人工确认此次功能是否发布到生产环境
代码合并。
进入持续部署流程
- 构建、测试、发布......
3、CICD LandSpace
二、Jenkins
/var/jenkins_home jenkins的家目录
包含了jenkins的所有配置。
以后要注意
备份/var/jenkins_home (以文件的方式固化的)
Jenkins镜像用 https://hub.docker.com/r/jenkinsci/jenkins/ 驱动我们整个CICD过程的很多工具
1、Jenkins安装
docker run \ --name=jenkins \ -u root \ -d \ -p 8080:8080 \ -p 50000:50000 \ -e JENKINS_OPTS="--prefix=/jenkins" \ -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 # -e JENKINS_OPTS="--prefix=/jenkins" \ # 可以不加 加了访问就要带上/jenkins docker run \ --name=jenkins \ -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 # 自己的镜像 registry.cn-hangzhou.aliyuncs.com/xue_app/jenkins:1.0 # 自己构建镜像 RUN的时候就把时区设置好 # 如果是别人的镜像,docker hub,UTC; 容器运行时 , -v /etc/localtime:/etc/localtime:ro jenkinsci/jenkins 是没有 blueocean插件的,得自己装 jenkinsci/blueocean:带了的 #/var/run/docker.sock 表示Docker守护程序通过其监听的基于Unix的套接字。 该映射允许 jenkinsci/blueocean 容器与Docker守护进程通信, 如果 jenkinsci/blueocean 容器需要实例化 其他Docker容器,则该守护进程是必需的。 如果运行声明式管道,其语法包含agent部分用 docker;例 如, agent { docker { ... } } 此选项是必需的。 #如果你的jenkins 安装插件装不上。使用这个镜像【registry.cn-hangzhou.aliyuncs.com/xue_app/jenkins:1.0】默认访问账号/密码是 【admin/admin】 #备份jenkins tar -cvf jenkins_data.tar /var/lib/docker/volumes/jenkins-data/_data/ #恢复jenkins tar -xvf jenkins_data.tar /var/lib/docker/volumes/jenkins-data/_data/ # 可以使用 查看jenkins容器运行的日志查看登录密码 docker logs -f jenkins2、Jenkins实战
1、准备一个git项目进行测试
以gitee为例。
步骤:
1、idea创建Spring Boot项目
2、VCS - 创建git 仓库
3、gitee创建一个空仓库,示例为public
4、idea提交内容到gitee
5、开发项目基本功能,并在项目中创建一个Jenkinsfile文件
6、创建一个名为devops-java-demo的流水线项目,使用项目自己的流水线
Jenkins的工作流程
1、先定义一个流水线项目,指定项目的git位置
啥都不用配置,指定Jenkinsfile文件就行,注意:要安装Github插件
流水线启动
- 1、先去git位置自动拉取代码
- 2、解析拉取代码里面的Jenkinsfile文件
- 3、按照Jenkinsfile指定的流水线开始加工项目
Jenkins重要的点
0、jenkins的家目录 /var/jenkins_home 已经被我们docker外部挂载了 ;
/var/lib/docker/volumes/jenkins-data/_data
1、WORKSPACE(工作空间)=/var/jenkins_home/workspace/java-devops-demo
每一个流水线项目,占用一个文件夹位置
BUILD_NUMBER=5;当前第几次构建
WORKSPACE_TMP(临时目录)=/var/jenkins_home/workspace/java-devops-demo@tmp
JOB_URL=http://139.198.9.163:8080/job/java-devops-demo/1
2、远程构建触发
期望效果: 远程的github代码提交了,jenkins流水线自动触发构建。
实现流程:
- 1、保证jenkins所在主机能被远程访问
- 2、jenkins中远程触发需要权限,我们应该使用用户进行授权
- 3、配置gitee/github,webhook进行触发
#远程构建即使配置了github 的webhook,默认会403.我们应该使用用户进行授权 1、创建一个用户 2、一定随便登陆激活一次 3、生成一个apitoken http://xueqimiao:113620edce6200b9c78ecadb26e9cf122e@139.198.186.134:8080/job/dev ops-java-demo/build?token=xueqimiao远程触发: JENKINS_URL /job/simple-java-maven-app/build?token= TOKEN_NAME 请求即可
3、流水线语法
1、基础格式
pipeline { agent any environment { CC = 'clang' } stages { stage('Example') { steps { sh 'printenv' sh 'echo $CC' } } } }2、自定义agent
3、Jenkinsfile-01
pipeline { agent any //定义一些环境信息 environment { WS = "${WORKSPACE}" IMAGE_VERSION = "v1.0" } //定义流水线的加工流程 stages { //流水线的所有阶段 stage('环境检查') { steps { echo "环境检查..." } } //1、编译 "abc" stage('maven编译') { steps { echo "maven编译..." } } //2、测试,每一个 stage的开始,都会重置到默认的WORKSPACE位置 stage('测试') { steps { echo "测试..." } } //3、打包 stage('生成镜像') { steps { echo "打包..." } } //4、运行 stage('运行') { steps { echo "运行..." } } } }4、Jenkinsfile-02
1、配置maven settings.xml文件
# 新建目录 mkdir -p /var/lib/docker/volumes/jenkins-data/_data/appconfig/maven /var/lib/docker/volumes/jenkins-data/_data # 是jenkins的挂载目录 vi settings.xml <?xml version="1.0" encoding="utf-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository <localRepository>${user.home}/.m2</localRepository> 用户目录下的.m2是所有jar包的地方; maven容器内jar包的位置 --> <localRepository>/var/jenkins_home/appconfig/maven/.m2</localRepository> <pluginGroups></pluginGroups> <proxies></proxies> <servers></servers> <mirrors> <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror> </mirrors> <profiles> <profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile> </profiles> </settings>pipeline { agent any //定义一些环境信息 environment { WS = "${WORKSPACE}" IMAGE_VERSION = "v1.0" } //定义流水线的加工流程 stages { //流水线的所有阶段 stage('环境检查') { steps { echo "环境检查..." 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' } } steps { echo "maven编译..." //git下载来的代码目录下 sh 'pwd && ls -alh' sh 'mvn -v' //打包,jar.。默认是从maven中央仓库下载。 jenkins目录+容器目录;-s指定容器内位置 //只要jenkins迁移,不会对我们产生任何影响 sh "echo 默认的工作目录:${WS}" //workdir //每一行指令都是基于当前环境信息。和上下指令无关 sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true ' //这里可以配置把镜像jar包推送给maven repo ,nexus } } //2、测试,每一个 stage的开始,都会重置到默认的WORKSPACE位置 stage('测试') { steps { echo "测试..." } } //3、打包 stage('生成镜像') { steps { echo "打包..." } } //4、运行 stage('运行') { steps { echo "运行..." } } } }5、Jenkinsfile-03
pipeline { agent any //定义一些环境信息 environment { WS = "${WORKSPACE}" IMAGE_VERSION = "v1.0" } //定义流水线的加工流程 stages { //流水线的所有阶段 stage('环境检查') { steps { echo "环境检查..." 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' } } steps { echo "maven编译..." //git下载来的代码目录下 sh 'pwd && ls -alh' sh 'mvn -v' //打包,jar.。默认是从maven中央仓库下载。 jenkins目录+容器目录;-s指定容器内位置 //只要jenkins迁移,不会对我们产生任何影响 sh "echo 默认的工作目录:${WS}" //workdir //每一行指令都是基于当前环境信息。和上下指令无关 sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true ' //这里可以配置把镜像jar包推送给maven repo ,nexus } } //2、测试,每一个 stage的开始,都会重置到默认的WORKSPACE位置 stage('测试') { steps { echo "测试..." } } //3、打包 stage('生成镜像') { steps { echo "生成镜像..." //检查Jenkins的docker命令是否能运行 sh 'docker version' sh 'pwd && ls -alh' // 执行dockerfile文件 sh 'docker rmi -f java-devops-demo' sh 'docker build -t java-devops-demo .' } } //4、运行 stage('运行') { steps { echo "运行..." sh 'docker rm -f java-devops-demo' sh 'docker run --name=java-devops-demo -p 8083:8080 -d java-devops-demo' } } } }临时容器导致的问题
- 1、第一次检出代码,默认在 /var/jenkins_home/workspace/【java-devops-demo】
- 2、使用docker临时agent的时候,每一个临时容器运行又分配临时目录/var/jenkins_home/workspace/java-devops-demo@2;默认就是workspace/java-devops-demo的内容
- 3、在临时容器里面 运行的mvn package命令,会在 /var/jenkins_home/workspace/java-devops-demo@2 进行工作
- 4、package到了 /var/jenkins_home/workspace/java-devops-demo@2 位置
- 5、进入下一步进行打包镜像,又会回到 /var/jenkins_home/workspace/【java-devops-demo】这个默认位置
- 6、这个位置没有运行过 mvn clean package ,没有target。 默认的 工作目录 没有 target
4、修改jenkins插件源
http://mirror.xmission.com/jenkins/updates/update-center.json5、推荐安装的插件
Docker Pipeline && Docker
- 安装Docker Pipeline会自动安装docker相关的
- 这个允许我们自定义agent使用docker环境
Git Parameter
- 解析git参数,允许我们选择分支进行构建
Active Choices
- 可以做到参数的级联选择
Generic Webhook Trigger
- 通用的webhook触发器,构建更强大的webhook功能
Role-based Authorization Strategy
- RBAC权限指定,给一个用户精确指定权限
List Git Branches Parameter
- 列出分支参数
Build With Parameters
基于自定义参数构建
6、邮件发送
系统配置 =-== 配置管理员邮箱
配置邮件发送的认证权限信息
- 登录自己邮箱,开启POP3/SMTP邮件服务
- 获取到自己的授权码
- 配置并测试好邮件发送即可
邮件模板内容
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: '1212@163.com' 大家自己修改 to 的位置3、单体应用部署jenkinsfile - dockerfile
1、Jenkinsfile
pipeline { agent any //定义一些环境信息 environment { WS = "${WORKSPACE}" IMAGE_VERSION = "v1.0" } //定义流水线的加工流程 stages { //流水线的所有阶段 stage('环境检查') { steps { echo "环境检查..." 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' } } steps { echo "maven编译..." //git下载来的代码目录下 sh 'pwd && ls -alh' sh 'mvn -v' //打包,jar.。默认是从maven中央仓库下载。 jenkins目录+容器目录;-s指定容器内位置 //只要jenkins迁移,不会对我们产生任何影响 sh "echo 默认的工作目录:${WS}" //workdir //每一行指令都是基于当前环境信息。和上下指令无关 sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true ' //这里可以配置把镜像jar包推送给maven repo ,nexus } } //2、测试,每一个 stage的开始,都会重置到默认的WORKSPACE位置 stage('测试') { steps { echo "测试..." } } //3、打包 stage('生成镜像') { steps { echo "生成镜像..." //检查Jenkins的docker命令是否能运行 sh 'docker version' sh 'pwd && ls -alh' // 执行dockerfile文件 sh 'docker rmi -f java-devops-demo' sh 'docker build -t java-devops-demo .' } } //4、运行 stage('运行') { steps { echo "运行..." sh 'docker rm -f java-devops-demo' sh 'docker run --name=java-devops-demo -p 8083:8080 -d java-devops-demo' } } } }2、Dockerfile
FROM openjdk:8-jdk-alpine LABEL maintainer="919417579@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" ]4、SSH阿里云镜像仓库部署一
1、安装SSH插件
# 把jenkins的服务器生成秘钥 ssh-keygen -t dsa # 把公钥复制到要访问的机器 - 第一次要输入目标机器的密码 ssh-copy-id 10.140.120.18 # 访问 ssh 10.140.120.18如果报没有这个文件/root/.ssh/id_dsa 就直接复制id_dsa里面的内容过来即可
2、Jenkins配置阿里云镜像仓库全局秘钥
3、Dockerfile
FROM openjdk:8-jdk-alpine LABEL maintainer="919417579@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" ]4、Jenkinsfile
pipeline { agent any //定义一些环境信息 environment { WS = "${WORKSPACE}" //引用Jenkins配置的全局秘钥信息 ALIYUN_SECRTE=credentials("aliyun-docker-repo") IMAGE_VERSION = "v1.0" } //定义流水线的加工流程 stages { //1、编译 "abc" stage('maven编译') { agent { docker { image 'maven:3-alpine' args '-v /var/jenkins_home/appconfig/maven/.m2:/root/.m2' } } steps { echo "maven编译..." sh 'cd ${WS} && mvn clean package -s "/var/jenkins_home/appconfig/maven/settings.xml" -Dmaven.test.skip=true ' } } stage('生成镜像') { steps { echo "生成镜像..." sh 'docker version' sh 'pwd && ls -alh' // 执行dockerfile文件 sh 'docker build -t java-devops-demo .' } } stage('推送镜像至阿里云'){ steps{ echo "推送镜像至阿里云..." 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 java-devops-demo registry.cn-hangzhou.aliyuncs.com/xue_images/java-devops-demo:${IMAGE_VERSION}" sh "docker push registry.cn-hangzhou.aliyuncs.com/xue_images/java-devops-demo:${IMAGE_VERSION}" } } } stage('部署到项目服务器') { steps { echo "部署到项目服务器..." sh 'ssh -tt 10.140.120.18' sh "docker rmi -f java-devops-demo:${IMAGE_VERSION}" sh "docker pull registry.cn-hangzhou.aliyuncs.com/xue_images/java-devops-demo:${IMAGE_VERSION}" sh "docker rm -f java-devops-demo:${IMAGE_VERSION}" sh "docker run --name=java-devops-demo -v /java_devops_log:/java_devops_log -p 8083:8080 -d java-devops-demo:${IMAGE_VERSION}" } } } }5、SSH阿里云镜像仓库部署二
1、deploy.sh
#! /bin/sh imageName=$1 tag=$2 hostPort=$3 imagePort=$4 #容器字符串 containerStr=`docker ps -a | grep -w ${imageName}:${tag} | awk '{print $1}'` imageStr=`docker images | grep -w $imageName | awk '{print $3}'` if [ "$imageStr" != "" ] ; then if [ "$containerStr" != "" ] ; then #停掉容器 docker stop `docker ps -a | grep -w ${imageName}:${tag} | awk '{print $1}'` #删除容器 docker rm `docker ps -a | grep -w ${imageName}:${tag} | awk '{print $1}'` #删除镜像 docker rmi --force ${imageName}:${tag} else #删除镜像 docker rmi --force ${imageName}:${tag} fi fi #pull镜像 docker pull $imageName:$tag echo $containerStr #运行镜像 docker run --name=$containerStr -v /${imageName}_log:/${imageName}_log -d -p ${hostPort}:${imagePort} -t ${imageName}:$tag2、Jenkinsfile
pipeline { agent { node { label 'maven' } } stages { stage('拉取代码') { agent none steps { container('maven') { git(url: 'https://gitee.com/xueqimiao/java-devops-demo.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false) sh 'ls' } } } stage('项目编译') { agent none steps { container('maven') { sh 'ls' sh 'mvn clean package -Dmaven.test.skip=true' sh 'ls' } } } stage('构建镜像') { agent none steps { container('maven') { sh 'ls target' sh 'docker build -t java-devops-demo:latest .' } } } stage('推送镜像') { agent none steps { container('maven') { withCredentials([usernamePassword(credentialsId : 'aliyun-docker-registry' ,passwordVariable : 'DOCKER_PWD_VAR' ,usernameVariable : 'DOCKER_USER_VAR' ,)]) { sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin' sh 'docker tag java-devops-demo:latest $REGISTRY/$DOCKERHUB_NAMESPACE/java-devops-demo:SNAPSHOT-$BUILD_NUMBER' sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/java-devops-demo:SNAPSHOT-$BUILD_NUMBER' } } } } stage('部署到139.198.190.176机器') { agent none steps { sh 'echo $REGISTRY' sh 'echo $DOCKERHUB_NAMESPACE' sshPublisher(publishers: [sshPublisherDesc(configName: '139.198.190.176', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/root/deploy.sh $REGISTRY/$ALIYUNHUB_NAMESPACE/java-devops-demo SNAPSHOT-$BUILD_NUMBER 8083 8080", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) } } } environment { DOCKER_CREDENTIAL_ID = 'dockerhub-id' GITHUB_CREDENTIAL_ID = 'github-id' KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig' REGISTRY = 'registry.cn-hangzhou.aliyuncs.com' DOCKERHUB_NAMESPACE = 'xue_images' GITHUB_ACCOUNT = 'kubesphere' APP_NAME = 'devops-java-sample' ALIYUNHUB_NAMESPACE = 'xue_images' } }