前言 	本文介绍使用Jenkins部署项目,使用gitea、registry配合,分别用作代码管理、镜像存储仓库
注:一般公司的发布方式有3种
直接用jar包发布(在开发环境构建jar包,将jar包上传到目标服务器,并在该服务器运行jar包)
使用docker发布(利用Jenkins从gitea拉取对应分支代码,构建jar包,将jar包和dockerfile构建为docker镜像,然后将该镜像上传的目标服务器,在目标服务器用docker运行该镜像)
使用k8s发布(利用Jenkins从gitea拉取对应分支代码,构建jar包,将jar包和dockerfile构建为docker镜像,然后将该镜像上传到私有镜像仓库(registry、harbor等),然后由k8s从私有镜像仓库拉取docker镜像,并进行部署(k8s一般进行集群部署,将镜像部署到多台服务器))
本文采取循序渐进的方式,先讲述如何实现docker部署方式(第二种方式),再慢慢补充k8s的部署方式
一般初创企业、中小企业使用第二种方式已经能够满足需求
 
 
发布流程(docker方式) 
设备拓扑(docker方式) 
注:我用gitea代替了gitlab,因为gitea的对设备的性能要求更小一些;另外我将gitea和Jenkins都部署在本地(Win11)的DockerDesktop中,因为网络的问题(我在虚拟机中使用macvlan,但是Jenkins很难访问外网),我利用frp转接(Jenkins访问云服务器,云服务利用frp将访问请求转发到本机的gitea),但是原理是一样的,我们开发后将代码推送到gitea服务,Jenkins从gitea拉取代码,编译打包后将jar包推送到需要部署的目标服务器,将jar包和Dockerfile构建为docker镜像,再启动服务 
 
基础服务安装部署 gitea服务安装部署 
在适当的地方建立gitea文件夹
在gitea文件夹中建立docker-compose.yml文件
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 version:  '3' services:   gitea:      image:  gitea/gitea:1.22.2             container_name:  gitea      restart:  always      environment:               -  USER_UID=1000                                -  USER_GID=1000      ports:        -  "3030:3000"          -  "2222:22"          volumes:        -  ./data:/data                 -  /etc/timezone:/etc/timezone:ro        -  /etc/localtime:/etc/localtime:ro  
运行命令安装并运行gitea
  运行命令查看gitea是否成功启动
 访问http://localhost:3030(用frp转接后可以从外网访问,http://{云服务器公网ip}:{frp配置的外网接口}), 设置用户名密码后就可以像使用github、gitee一样使用这个git服务器
创建一个仓库,将本地代码推送到服务器
 使用git命令查看本地git远程连接
  到新建仓库获取仓库URL(这里建议使用frp转接后的公网url,remote默认名称为origin),使用git命令添加一条remote链接
 1 git remote add remote名称 仓库URL 
 现在可以使用git push命令将本地代码推送到搭建好的gitea服务器
 1 git push remote名称 仓库分支名称 
 
Jenkins服务安装部署 
在适当的地方创建Jenkins文件夹 
在Jenkins文件夹中创建docker-compose.yml文件 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 version: '3.6'  services:   jenkins:     image: jenkins/jenkins:lts            container_name: jenkins     restart: on-failure           privileged: true               user: root     environment:       - JAVA_OPTS=-Xmx1024m       ports:       - "8888:8080"              - "50000:50000"          volumes:       - ./jenkins_home:/var/jenkins_home       - ./tool:/tool      
运行命令安装并启动Jenkins 
 
验证Jenkins已经启动 
 
查看初始密码 
 
1 cat  /jenkins_home/secrets/initialAdminPassword
修改’/jenkins_home/hudson.model.UpdateCenter.xml’文件中的url参数为国内的镜像源(如清华镜像源) 
 
1 2 3 4 5 6 7 <?xml version='1.1' encoding='UTF-8'?> <sites >   <site >      <id > default</id >      <url > https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url >    </site >  </sites > 
设置账号密码后进入并额外安装两款插件‘Git Parameter’、‘Publish Over SSH’
将linux版的jdk和maven下载并解压到tool文件夹
 
 
进入Jenkins页面(http://localhost:8888),进入‘系统管理’-‘全局工具配置(tool)’,点击‘JDK安装’和‘MAVEN安装’,名称可以自己取,路径则填写‘/tool/jdk’和’/tool/maven‘
 
注意:路径名称可以不固定的,但是填写的路径要一直到’bin‘目录的上一级;解压文件时windows系统要用管理员模式解压; 
 
在tool下新建repo目录,进入刚才的’/tool/maven/conf’文件夹,修改settings.xml文件中的’localRepository’的值为’/tool/repo‘,修改’mirror‘的值为阿里云镜像 
 
1 2 3 4 5 6 7 8 <localRepository > /tool/repo</localRepository > <mirror > 	<id > aliyunmaven</id >  	<mirrorOf > *</mirrorOf >  	<name > 阿里云公共仓库</name >  	<url > https://maven.aliyun.com/repository/public</url >  </mirror > 
registry服务安装部署 
在适当位置新建’registry‘文件夹,在其中新建’docker-compose.yml‘文件,运行命令启动容器,查看容器是否启动成功 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 services:   registry:      privileged:  true                  image:  registry                        restart:  no      container_name:  registry          ports:                              -  5000 :5000      volumes:                            -  ./data:/var/lib/registry        -  ./certs:/certs      networks:        -  registry-net    registry-web:      image:  konradkleine/docker-registry-frontend:v2           restart:  no      ports:        -  8035 :80      environment:               -  ENV_DOCKER_REGISTRY_HOST=139.155.229.99        -  ENV_DOCKER_REGISTRY_PORT=5000      networks:        -  registry-net  networks:   registry-net:      driver:  bridge  
	
1 2 docker compose up -d docker ps -a 
修改’/etc/docker/daemon.json’文件,添加连接项后重启docker 
 
1 2 3 { 	"insecure-registries" :  [ "139.155.229.99:5000" ]  } 
1 2 systemctl daemon-reload systemctl restart docker  
	如果是使用docker-desktop,则在’设置‘-’docker enigine‘中添加连接项,然后点击‘Apply & restart’
注:这里设置的‘insecure-registries’是docker访问registry服务器的链接;在生产环境中一般会使用https和SSL证书来保证安全 
 
使用方式 
 
(1)为镜像打标签
1 2 3 docker tag 镜像名称 registry-ip:port/组织名称/镜像名称 docker tag mysql:8.0 192.168.144.140:5000/qiuli/mysql:8.0 
(2)上传镜像到registry仓库
1 2 3 docker push registry-ip:port/组织名称/镜像名称 docker push 192.168.144.140:5000/qiuli/mysql:8.0 
(3)访问registry-web可以查看到上传的镜像
(4)拉取镜像
	进入镜像页面,使用命令拉取镜像即可
	
1 docker pull 139.155.229.99:5000/qiuli/hello-world:1.0.0 
部署单体项目 使用Jenkins部署Java项目 新建目标服务器 	从Jenkins主页进入’系统管理‘-’系统配置‘-’Publish Over SSH‘-‘SSH Servers’,添加‘SSH Server’;自定义name,hostname为目标服务器ip,username为目标服务器用户名(默认为’root‘),Remote Directory是发布路径(即将推送来的jar包放在哪里,这里用‘/usr/local’);点击’高级‘,选择’use password‘,然后填写密码;点击’Test Configuration‘,如果显示‘success’则点击’应用‘-’保存‘
新建部署任务 点击’新建任务‘,输入任务名称,先选择’构建一个自由风格的软件项目‘,点击’确定‘
在’源码管理‘中选择’Git‘,填入gitea的仓库URL,选择需要部署的分支
	
在’Build Steps‘中点击’增加构建步骤‘,选择’执行Shell‘,添加命令
1 sh /tool/maven/bin/mvn clean package -Dmaven.test.skip=true 
注意:因为我们没有在容器内添加全局环境变量,所以这里没有办法使用’mvn‘,而必须使用包含具体执行目录的’’/tool/maven/bin/mvn’,‘/tool/maven’是我们安装是yml文件中配置的挂载目录 
 
点击’应用‘-’保存‘回到任务界面,点击’立即构建‘,等待其构建,在’控制台输出‘中可以看到日志
	
构建完毕后进入docker-compose.yml文件中挂载的’jenkins_home‘文件夹,在’workspace‘-’项目名称‘-’target‘中可以看到编译打包完毕的jar包
	
添加构建脚本 	这里我们需要更进一步,将打包好的jar包推送到目标服务器并编写shell脚本运行它
	进入该项目配置页面,来到’构建后操作‘-’增加构建后操作步骤‘-’Send build artifacts over SSH‘;
	选择刚才配置的云服务器,在’Transfer Set‘-’Source files‘中填写’target/*.jar‘(即打包完毕的jar包的本地路径);在’Exec command‘中填写在目标服务器中将要执行的部署脚本:
1 2 3 4 #  首先关闭原先在运行中的java程序(如果有的话) pkill java #  运行java程序并且在运行结束1s后退出 nohup java -jar /usr/local/target/jenkins-deploy-demo-1.0-SNAPSHOT.jar & sleep 1 
	
	再选择’高级‘,点击’Exec in pty‘;点击’应用‘-’保存‘
	
构建并部署 	来到项目界面,再次点击‘立即构建’,等待构建完成查看日志结尾显示‘success’,来到目标服务器,可以查看‘nohup.out’文件,里面是项目的启动日志;这时可以确认项目启动成功
	从浏览器访问’http://目标服务器ip:项目端口port/‘,就可以看到’hello world‘页面
	
使用Jenkins部署Java项目(构建docker镜像并运行容器) 修改代码 	在Java项目中新建’/docker/Dockerfile’,并将修改后的代码推送到gitea服务器
1 2 3 4 5 6 7 8 9 10 11 12 #  使用openjdk8的镜像 FROM openjdk:8-jre #  设置工作目录 WORKDIR /build #  将jar包复制到容器中 # (注意,这里因为我们在第3步设置了消除多余前缀目录,所以jar包直接放在目标服务器中设置的‘Remote Directory’中,前面不会再有‘target’) COPY ./jenkins-deploy-demo-1.0-SNAPSHOT.jar ./jenkins-deploy-demo.jar #  运行jar包 ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS jenkins-deploy-demo.jar $PARAMS"] 
	使用git推送到gitea服务器,这里不再赘述
新建目标服务器 	按照‘使用Jenkins部署Java项目’中的步骤创建即可,这里’Remote Directory’设置为‘/usr/local/jenkins-deploy-demo’,也可以使用已经创建好的目标服务器进行修改
新建部署任务 	按照‘使用Jenkins部署Java项目’中的步骤创建即可,也可以使用原来已经创建好的任务进行修改
重写构建脚本并推送文件到目标服务器 	这里我使用原来的部署任务进行修改,在‘构建后操作’-’Send build artifacts over SSH‘,’Transfers’-‘Transfer Set’中添加‘Remove prefix’的值为‘target’,并在‘Exec command’中删除原来的构建脚本
注:‘Remove prefix’的意思是移除文件前缀,目的是将多余的文件夹去除,让上传的文件保存到同一个目录下; 
 
	再添加一项‘Transfer Set’,‘Source files’中添加‘docker/*’,‘Remove prefix’中添加‘docker’(去除前缀目录),’Exec command’中添加构建脚本:
1 2 3 4 5 6 docker build -t qiuli/jenkins-deploy-demo:1.0 /usr/local/project/jenkins-deploy-demo docker rm  -f jenkins-deploy-demo docker run -d -p 10001:10001 --name=jenkins-deploy-demo qiuli/jenkins-deploy-demo:1.0 
	
注:这里因为我重新设置了‘SSH Server’-‘Remote Directory’为‘/usr/local/project/jenkins-deploy-demo’,所以上传的两个文件保存在了‘/usr/local/project/jenkins-deploy-demo’中 
 
构建并部署 	点击‘应用’-‘保存’后回到项目界面,点击‘立即构建’(这里如果报错,可以到目标服务器,将构建脚本一步步运行,查看报错);
	构建成功后来到目标服务器,输入“docker images”、“docker ps -a”可以看到构建后的镜像和运行的容器
	
	
根据运行的docker容器的端口号,从浏览器访问“http://124.71.82.231:10001/demo/helloworld”,成功返回信息
	
使用Jenkins流水线部署Java项目(Jenkins-pipeline) Jenkins流水线任务示例 新建Jenkins流水线任务
填写简单的pipeline脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pipeline {     agent any 	 	# 执行阶段     stages {     	# 阶段1,拉取代码         stage('拉取代码') {         	# 执行步骤             steps {                 echo '拉取成功'             }         } 		# 阶段2,执行构建 		stage('执行构建') { 		   # 执行步骤             steps {                 echo '构建完成'             }         }     } } 
取消勾选‘使用 Groovy 沙盒’,点击‘Approve script’(审批脚本)
看到‘The script is already approved’(脚本已经审批),再点击‘应用’-‘保存’
来到该流水线任务页面,点击‘立即构建’,可以看到执行成功
注:可以在Jenkins中安装’Blue Ocean’插件,为流水线提供了更多功能 
 
流水线语法 
1 2 3 4 5 pipeline:整条流水线 agent:指定执行器 stages:所有阶段 stage:某一阶段,可有多个 steps:阶段内的每一步,可执行命令 
pipeline语法基础框架:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 pipeline {     agent any     stages {         stage('拉取代码') {             steps {                 echo '拉取代码完成'             }         }         stage('执行构建') {             steps {                 echo '执行构建完成'             }         }     }     post {         always {             echo "完成"         }         failure {             echo "失败"         }     } } 
 
使用流水线部署Java项目 (1)新建流水线任务
	见前文
(2)代码生成器的使用方式
	
(3)’拉取代码‘片段
(4)’执行构建‘片段
1 mvn clean package -Dmaven.test.skip=true  
(5)’清理目标服务器前次部署时创建的容器和镜像‘片段
1 2 3 4 5 rm  -rf *docker stop jenkins-deploy-demo docker rm  -f jenkins-deploy-demo docker rmi -f qiuli/jenkins-deploy-demo:1.0 
(6)’推送到目标服务器、生成镜像并运行容器‘片段
1 2 3 docker build -t qiuli/jenkins-deploy-demo:1.0 /usr/local/project/jenkins-deploy-demo docker run -d -p 10001:10001 --name=jenkins-deploy-demo qiuli/jenkins-deploy-demo:1.0 
(7)全部脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 pipeline {     agent any 	 	// 导入maven,下文就可以使用’mvn‘构建jar包(“maven”的名称与全局工具配置(tool)-maven安装中的一致) 	tools  { 		maven "maven" 	} 	     stages {         stage('拉取代码') {             steps { 				git 'http://139.155.229.99:3030/lkd7736241/Jenkins-deploy-demo.git'                 echo '拉取成功'             }         } 		 		stage('执行构建') {             steps { 				// 测试mvn命令能否正确运行  				// sh "mvn --version" 				 				sh "mvn clean package -Dmaven.test.skip=true"                 echo '构建完成'             }         } 		 		stage('清理目标服务器前次部署时创建的容器和镜像') { 			steps { 				sshPublisher(publishers: [sshPublisherDesc(configName: 'target-huaweiyun-jenkinsdeploydemo', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf * docker stop jenkins-deploy-demo docker rm -f jenkins-deploy-demo docker rmi -f qiuli/jenkins-deploy-demo:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) 				echo '清理完成' 			} 		} 		 		stage('推送到目标服务器、生成镜像并运行容器') {             steps { 				sshPublisher(publishers: [sshPublisherDesc(configName: 'target-huaweiyun-jenkinsdeploydemo', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'jenkins-deploy-demo/target', sourceFiles: 'jenkins-deploy-demo/target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t qiuli/jenkins-deploy-demo:1.0 /usr/local/project/jenkins-deploy-demo docker run -d -p 10001:10001 --name=jenkins-deploy-demo qiuli/jenkins-deploy-demo:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'jenkins-deploy-demo/docker', sourceFiles: 'jenkins-deploy-demo/docker/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])                 echo '部署完成'             }         }     } } 
(8)将脚本粘贴并审批后,点击’应用‘-’保存‘,来到该流水线项目的页面,点击’立即构建‘
使用多分支流水线部署Java项目 (1)在Java项目中创建一个新的分支test,修改后推送到gitea代码仓库
1 2 git checkout -b test  git push origin test  
(2)在两个分支中新建Jenkinsfile文件
该文件中即是构建脚本;本示例项目中,master分支可以直接使用上文中的构建脚本,test分支需要调整的地方是:a.git拉取代码的语句 b.目标服务器的ip、端口、目录等(例如测试服务器和生产服务是分开的,那就需要更新目标服务器脚本片段,这不是必须,根据实际情况调整);脚本还是由脚本片段生成器生成
1 2 # git片段 git branch: 'test', url: 'http://139.155.229.99:3030/lkd7736241/Jenkins-deploy-demo.git' 
	master分支构建脚本全文:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 pipeline {     agent any 	 		// 导入maven,下文就可以使用’mvn‘构建jar包(“maven”的名称与全局工具配置(tool)-maven安装中的一致) 	tools  { 		maven "maven" 	} 	     stages {         stage('拉取master分支代码') {             steps { 				git 'http://139.155.229.99:3030/lkd7736241/Jenkins-deploy-demo.git'                 echo '拉取成功'             }         } 		 		stage('执行构建') {             steps { 				// 测试mvn命令能否正确运行  				// sh "mvn --version" 				 				sh "mvn clean package -Dmaven.test.skip=true"                 echo '构建完成'             }         } 		 		stage('清理目标服务器前次部署时创建的容器和镜像') { 			steps { 				sshPublisher(publishers: [sshPublisherDesc(configName: 'target-huaweiyun-jenkinsdeploydemo', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf * docker stop jenkins-deploy-demo docker rm -f jenkins-deploy-demo docker rmi -f qiuli/jenkins-deploy-demo:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) 				echo '清理完成' 			} 		} 		 		stage('推送到目标服务器、生成镜像并运行容器') {             steps { 				sshPublisher(publishers: [sshPublisherDesc(configName: 'target-huaweiyun-jenkinsdeploydemo', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'jenkins-deploy-demo/target', sourceFiles: 'jenkins-deploy-demo/target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t qiuli/jenkins-deploy-demo:1.0 /usr/local/project/jenkins-deploy-demo docker run -d -p 10001:10001 --name=jenkins-deploy-demo qiuli/jenkins-deploy-demo:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'jenkins-deploy-demo/docker', sourceFiles: 'jenkins-deploy-demo/docker/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])                 echo '部署完成'             }         }     } } 
	test分支构建脚本全文:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 pipeline {     agent any 	 		 	tools  { 		maven "maven"  	} 	     stages {         stage('拉取test分支代码' ) {             steps { 				git branch:  'test' , url:  'http://139.155.229.99:3030/lkd7736241/Jenkins-deploy-demo.git'                  echo '拉取成功'              }         } 		 		stage('执行构建' ) {             steps { 				 				 				 				sh "mvn clean package -Dmaven.test.skip=true"                  echo '构建完成'              }         } 		 		stage('清理目标服务器前次部署时创建的容器和镜像' ) { 			steps { 				sshPublisher(publishers:  [sshPublisherDesc(configName:  'target-huaweiyun-jenkinsdeploydemo' , transfers:  [sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '''rm -rf *  docker stop jenkins-deploy-demo docker rm -f jenkins-deploy-demo docker rmi -f qiuli/jenkins-deploy-demo:1.0''' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  '' , sourceFiles:  '' )], usePromotionTimestamp:  false , useWorkspaceInPromotion:  false , verbose:  false )])				echo '清理完成'  			} 		} 		 		stage('推送到目标服务器、生成镜像并运行容器' ) {             steps { 				sshPublisher(publishers:  [sshPublisherDesc(configName:  'target-huaweiyun-jenkinsdeploydemo' , transfers:  [sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  'jenkins-deploy-demo/target' , sourceFiles:  'jenkins-deploy-demo/target/*.jar' ), sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '''docker build -t qiuli/jenkins-deploy-demo:1.0 /usr/local/project/jenkins-deploy-demo  docker run -d -p 10001:10001 --name=jenkins-deploy-demo qiuli/jenkins-deploy-demo:1.0''' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  'jenkins-deploy-demo/docker' , sourceFiles:  'jenkins-deploy-demo/docker/*' )], usePromotionTimestamp:  false , useWorkspaceInPromotion:  false , verbose:  false )])                echo '部署完成'              }         }     } } 
(3)新建多分支流水线任务(需要安装multi-pipeline插件),添加git仓库后保存
(4)来到该项目页面,点击’立刻扫描 多分支流水线‘即可执行;点击’状态‘,再点击右手边构建符号即可以对某分支进行单独执行
部署集群项目(K8S方式部署) 参考文章kubernetes集群部署 、kubernetes部署Nginx集群 、kubernetes部署Redis集群 
// TODO
项目部署实战 部署hades项目 Jenkins自由风格部署 将代码推送到gitea服务器 新建目标服务器 即服务将被部署的服务器,见‘使用Jenkins部署Java项目’-’新建目标服务器‘
新建自由风格任务 
填写相关配置 配置代码源(gitea服务器地址)、构建步骤(Maven构建)、构建后操作(将Dockerfile文件和jar包推送到目标服务器,然后使用docker构建镜像、运行容器)
配置代码源(gitea服务器) 
构建步骤(Maven构建) 
1 sh /tool/maven/bin/mvn clean package -Dmaven.test.skip=true  
构建后操作(将jar包推送到目标服务器) 
构建后操作(将Dockerfile文件推送到目标服务器,然后使用docker构建镜像、运行容器) 
1 2 3 docker build -t qiuli/hades-web:1.0 /usr/local/project/hades-qiuli docker rm  -f hades-web docker run -d -p 7890:7890 --name=hades-web qiuli/hades-web:1.0 
注:如果目标服务器是云服务器,记得打开端口(见’虚拟机的初始准备‘-’网络设置‘)
Jenkins多分支流水线部署 新建目标服务器 
新建多分支流水线任务 
配置分支源 点击‘配置’-‘分支源’-‘git’,填写代码仓库的地址
生成Jenkinsfile文件 进入项目的流水线语法页面,选择‘sshPublisher’,填写各项配置
注:在需要进行部署的代码分支新建文件Jenkinsfile,该文件中包含部署脚本,使用Jenkins的“流水线语法 ”
生成脚本片段,本次部署脚本共4个片段
(1)片段一:拉取deploy分支代码
1 git branch: 'deploy' , url: 'http://139.155.229.99:3030/lkd7736241/hades-qiuli.git'  
(2)片段二:利用maven构建jar包
1 sh "mvn clean package -Dmaven.test.skip=true"  
(3)片段三:清理目标服务器前次部署时创建的容器和镜像
1 2 3 4 rm  -rf *docker stop hades-web docker rm  -f hades-web docker rmi -f qiuli/hades-web:1.0 
1 2 3 4 5 steps { 				sshPublisher(publishers: [sshPublisherDesc(configName: 'huaweiyun-hades-qiuli', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf *                 docker stop hades-web                 docker rm -f hades-web                 docker rmi -f qiuli/hades-web:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) 
(4)片段四:推送文件到目标服务器、生成镜像并运行容器
1 2 docker build -t qiuli/hades-web:1.0 /usr/local/project/hades-qiuli docker run -d -p 7890:7890 --name=hades-web qiuli/hades-web:1.0 
1 2 sshPublisher(publishers: [sshPublisherDesc(configName: 'huaweiyun-hades-qiuli', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'hades-qiuli/target', sourceFiles: 'hades-qiuli/target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t qiuli/hades-web:1.0 /usr/local/project/hades-qiuli docker run -d -p 7890:7890 --name=hades-web qiuli/hades-web:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'hades-qiuli/docker', sourceFiles: 'hades-qiuli/docker/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) 
(5)将4个片段粘贴到流水线部署脚本中,本次部署脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 pipeline {     agent any 	 	// 导入maven,下文就可以使用’mvn‘构建jar包(“maven”的名称与全局工具配置(tool)-maven安装中的一致) 	tools  { 		maven "maven" 	} 	     stages {         stage('拉取deploy分支代码') {             steps { 				git branch: 'deploy', url: 'http://139.155.229.99:3030/lkd7736241/hades-qiuli.git'                 echo '拉取成功'             }         } 		 		stage('构建jar包') {             steps { 				// 测试mvn命令能否正确运行  				// sh "mvn --version" 				 				sh "mvn clean package -Dmaven.test.skip=true"                 echo '构建完成'             }         } 		 		stage('清理目标服务器前次部署时创建的容器和镜像') { 			steps { 				sshPublisher(publishers: [sshPublisherDesc(configName: 'huaweiyun-hades-qiuli', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''rm -rf *                 docker stop hades-web                 docker rm -f hades-web                 docker rmi -f qiuli/hades-web:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) 				echo '清理完成' 			} 		} 		 		stage('推送文件到目标服务器、生成镜像并运行容器') {             steps {                 sshPublisher(publishers: [sshPublisherDesc(configName: 'huaweiyun-hades-qiuli', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'hades-qiuli/target', sourceFiles: 'hades-qiuli/target/*.jar'), sshTransfer(cleanRemote: false, excludes: '', execCommand: '''docker build -t qiuli/hades-web:1.0 /usr/local/project/hades-qiuli docker run -d -p 7890:7890 --name=hades-web qiuli/hades-web:1.0''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'hades-qiuli/docker', sourceFiles: 'hades-qiuli/docker/*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])				                 echo '部署完成'             }         }     } } 
将Jenkinsfile文件推送动到对应分支,启动部署 将编辑好的部署脚本推送到deploy分支,在Jenkins对应项目页面点击’立即扫描多分支流水线‘,则会扫描出含有Jenkinsfile的分支,点击启动按钮就可以进行部署
部署hades-admin项目 前置安装的服务:node、npm、git、pm2
使用git克隆hades-admin代码到目标服务器适当的文件夹
1 2 git clone  -b deploy http://139.155.229.99:3030/lkd7736241/hades-admin.git 
进入hades-admin文件夹,使用npm安装依赖
使用pm2启动hades-admin服务、查看服务状态
1 2 pm2 start hades-server.js pm2 status 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 const  express = require ('express' );const  http = require ('http' );const  path = require ('path' );const  reload = require ('reload' );const  bodyParser = require ('body-parser' );const  logger = require ('morgan' );const  app = express ();app.set ('port' , process.env .PORT  || 3100 ); app.use (logger ('deploy' )); app.use (bodyParser.json ());  app.use ('/public' , express.static ('public' )); app.use ('/pages' , express.static ('pages' )); app.use ('/sdk' , express.static ('sdk' )); app.get ('/*' , function  (req, res ) {   res.sendFile (path.join (__dirname, 'index.html' )); }); const  server = http.createServer (app);reload (app)  .then (function  (reloadReturned ) {               server.listen (app.get ('port' ), function  (       console .log (                  'Web server listening on port http://ip:'  + app.get ('port' )       );     });   })   .catch (function  (err ) {     console .error (       'Reload could not start, could not start server/sample app' ,       err     );   }); 
部署austin项目 Jenkins自由风格部署 修改代码并上传到gitea服务器 
新建目标服务器 	- 注:目标服务器确定项目部署的服务器、文件夹等,记得在高级中配置服务器ssh登录密码
1 2 3 4 5 6 7 8 huaweiyun-austin-qiuli 124.71.82.231 root /usr/local/project/austin-qiuli 
新建自由风格服务 填写相关配置 (1)配置代码源(gitea仓库地址)
1 2 3 4 http://139.155.229.99:3030/lkd7736241/austin_qiuli.git */deploy 
(2)配置构架操作(构建jar包)
	“增加构建步骤”-“执行Shell”
1 sh /tool/maven/bin/mvn clean package -Dmaven.test.skip=true  
注:jdk和Maven已经配置够了,见“基础服务安装部署”-“Jenkins服务安装部署” 
 
(3)配置构建后操作
将Dockerfile文件和jar包推送到目标服务器,停止之前部署的服务,清理之前的容器、镜像,然后使用docker构建镜像、运行容器
1 2 3 4 austin-web/target/*.jar austin-web/target 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 rm  -rf *.jarrm  -rf Dockerfiledocker stop austin-qiuli docker rm  -f austin-qiuli docker rmi -f qiuli/austin-qiuli:1.0 docker build -t qiuli/austin-qiuli:1.0 /usr/local/project/austin-qiuli mkdir  /usr/local/project/austin-qiuli/logsmkdir  /usr/local/project/austin-qiuli/mailinglistdocker run -d -p 8899:8899 -p 6666:6666 \   -v /usr/local/project/austin-qiuli/logs:/build/logs \   -v /usr/local/project/austin-qiuli/mailinglist:/home/austin/mailinglist \   --name=austin-qiuli \   -e SET_CONTAINER_TIMEZONE=true  \   -e CONTAINER_TIMEZONE=Asia/Shanghai \   -e TZ=Asia/Shanghai \   qiuli/austin-qiuli:1.0 
注意:将项目打包为docker镜像并在docker中运行,需要将所有涉及到的接口映射到主机(例如作为xxl-job执行器需要暴露单独的端口6666); 
要想项目运行的时间正常,需要设置时区的环境变量: 
 
1 2 3 -e SET_CONTAINER_TIMEZONE=true -e CONTAINER_TIMEZONE=Asia/Shanghai -e TZ=Asia/Shanghai 
Jenkins多分支流水线部署 新建目标服务器 
新建多分支流水线任务 
配置分支源 点击‘配置’-‘分支源’-‘git’,填写代码仓库的地址
生成Jenkinsfile文件 进入项目的流水线语法页面,选择‘sshPublisher’,填写各项配置
注:在需要进行部署的代码分支新建文件Jenkinsfile,该文件中包含部署脚本,使用Jenkins的“流水线语法 ”
生成脚本片段,本次部署脚本共4个片段
(1)片段一:拉取deploy分支代码
1 git branch:  'deploy' , url:  'http://139.155.229.99:3030/lkd7736241/austin_qiuli.git'  
(2)片段二:利用maven构建jar包
1 sh /tool/maven/bin/mvn clean package -Dmaven.test.skip=true 
1 sh 'sh /tool/maven/bin/mvn clean package -Dmaven.test.skip=true'  
(3)片段三:清理目标服务器前次部署时创建的容器和镜像
1 2 3 4 5 6 rm -rf *.jar rm -rf Dockerfile docker stop austin-qiuli docker rm -f austin-qiuli docker rmi -f qiuli/austin-qiuli:1.0 
1 2 3 4 5 6 sshPublisher(publishers:  [sshPublisherDesc(configName:  'centos7-05-austin-qiuli' , transfers:  [sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '''rm -rf *.jar  rm -rf Dockerfile docker stop austin-qiuli docker rm -f austin-qiuli docker rmi -f qiuli/austin-qiuli:1.0''' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  'austin-web/target' , sourceFiles:  'austin-web/target/*.jar' )], usePromotionTimestamp:  false , useWorkspaceInPromotion:  false , verbose:  false )])
(4)片段四:推送文件到目标服务器、生成镜像并运行容器
1 2 3 4 5 6 7 8 9 10 11 12 13 docker build -t qiuli/austin-qiuli:1.0 /usr/local/project/austin-qiuli mkdir /usr/local/project/austin-qiuli/logs mkdir /usr/local/project/austin-qiuli/mailinglist docker run -d -p 8899:8899 -p 6666:6666 \   -v /usr/local/project/austin-qiuli/logs:/build/logs \   -v /usr/local/project/austin-qiuli/mailinglist:/home/austin/mailinglist \   --name=austin-qiuli \   -e SET_CONTAINER_TIMEZONE=true \   -e CONTAINER_TIMEZONE=Asia/Shanghai \   -e TZ=Asia/Shanghai \   qiuli/austin-qiuli:1.0 
1 2 3 4 5 6 7 8 9 10 11 12 13 sshPublisher(publishers:  [sshPublisherDesc(configName:  'centos7-05-austin-qiuli' , transfers:  [sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '''docker build -t qiuli/austin-qiuli:1.0 /usr/local/project/austin-qiuli  mkdir /usr/local/project/austin-qiuli/logs mkdir /usr/local/project/austin-qiuli/mailinglist docker run -d -p 8899:8899 -p 6666:6666 \\   -v /usr/local/project/austin-qiuli/logs:/build/logs \\   -v /usr/local/project/austin-qiuli/mailinglist:/home/austin/mailinglist \\   --name=austin-qiuli \\   -e SET_CONTAINER_TIMEZONE=true \\   -e CONTAINER_TIMEZONE=Asia/Shanghai \\   -e TZ=Asia/Shanghai \\   qiuli/austin-qiuli:1.0''' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  'austin-web/target' , sourceFiles:  'austin-web/target/*.jar' )], usePromotionTimestamp:  false , useWorkspaceInPromotion:  false , verbose:  false )])
(5)将4个片段粘贴到流水线部署脚本中,本次部署脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 pipeline {     agent any 	 	 	tools  { 		maven "maven"  	} 	     stages {         stage('拉取deploy分支代码' ) {             steps { 				git branch:  'deploy' , url:  'http://139.155.229.99:3030/lkd7736241/austin_qiuli.git'  				echo '拉取成功'              }         } 		 		stage('执行构建' ) {             steps { 				sh 'sh /tool/maven/bin/mvn clean package -Dmaven.test.skip=true'  				echo '构建完成'              }         } 		 		stage('清理目标服务器前次部署时创建的容器和镜像' ) { 			steps { 				sshPublisher(publishers:  [sshPublisherDesc(configName:  'centos7-05-austin-qiuli' , transfers:  [sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '''rm -rf *.jar  rm -rf Dockerfile docker stop austin-qiuli docker rm -f austin-qiuli docker rmi -f qiuli/austin-qiuli:1.0''' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  'austin-web/target' , sourceFiles:  'austin-web/target/*.jar' )], usePromotionTimestamp:  false , useWorkspaceInPromotion:  false , verbose:  false )])				echo '清理完成'  			} 		} 		 		stage('推送到目标服务器、生成镜像并运行容器' ) {             steps {                 sshPublisher(publishers:  [sshPublisherDesc(configName:  'centos7-05-austin-qiuli' , transfers:  [sshTransfer(cleanRemote:  false , excludes:  '' , execCommand:  '''docker build -t qiuli/austin-qiuli:1.0 /usr/local/project/austin-qiuli  mkdir /usr/local/project/austin-qiuli/logs mkdir /usr/local/project/austin-qiuli/mailinglist docker run -d -p 8899:8899 -p 6666:6666 \\   -v /usr/local/project/austin-qiuli/logs:/build/logs \\   -v /usr/local/project/austin-qiuli/mailinglist:/home/austin/mailinglist \\   --name=austin-qiuli \\   -e SET_CONTAINER_TIMEZONE=true \\   -e CONTAINER_TIMEZONE=Asia/Shanghai \\   -e TZ=Asia/Shanghai \\   qiuli/austin-qiuli:1.0''' , execTimeout:  120000 , flatten:  false , makeEmptyDirs:  false , noDefaultExcludes:  false , patternSeparator:  '[, ]+' , remoteDirectory:  '' , remoteDirectorySDF:  false , removePrefix:  'austin-web/target' , sourceFiles:  'austin-web/target/*.jar' )], usePromotionTimestamp:  false , useWorkspaceInPromotion:  false , verbose:  false )])		                echo '部署完成'              }         }     } } 
将Jenkinsfile文件推送动到对应分支,启动部署 将编辑好的部署脚本推送到deploy分支,在Jenkins对应项目页面点击’立即扫描多分支流水线‘,则会扫描出含有Jenkinsfile的分支,点击启动按钮就可以进行部署
部署austin-admin项目 
前置安装的服务:node、npm、git、pm2 
使用git克隆austin-admin代码到目标服务器适当的文件夹 
 
1 2 git clone  -b deploy http://139.155.229.99:3030/lkd7736241/austin-admin.git 
进入austin-admin文件夹,使用npm安装依赖 
 
使用pm2启动austin-admin服务、查看服务状态 
 
1 2 pm2 start austin-server.js pm2 status 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 const  express = require ('express' );const  http = require ('http' );const  path = require ('path' );const  reload = require ('reload' );const  bodyParser = require ('body-parser' );const  logger = require ('morgan' );const  app = express ();app.set ('port' , process.env .PORT  || 3000 ); app.use (logger ('deploy' )); app.use (bodyParser.json ());  app.use ('/public' , express.static ('public' )); app.use ('/pages' , express.static ('pages' )); app.use ('/sdk' , express.static ('sdk' )); app.get ('/*' , function  (req, res ) {   res.sendFile (path.join (__dirname, 'index.html' )); }); const  server = http.createServer (app);reload (app)  .then (function  (reloadReturned ) {               server.listen (app.get ('port' ), function  (       console .log (         'Web server listening on port http://ip:'  + app.get ('port' )       );     });   })   .catch (function  (err ) {     console .error (       'Reload could not start, could not start server/sample app' ,       err     );   });