轻量级CI/CD发布部署环境搭建及使用_07_jenkins配置pipeline
尽自己的绵薄之力,为开源技术分享添砖加瓦
2,设置git仓库地址、用户名、密码

3,生成流水线脚本

4,编写pipeline_配置发布服务器、harbor、jar包目录等

5,编写pipeline_配置dockerfile、docker编译命令等

6,编写pipeline_配置连接部署服务器、docker启动、删除容器命令等
============================部署后端pieplie范例脚本============================
相关变量都以xxx代替,请自行替换
1 pipeline{
2 agent any
3 environment {
4 HARBOR_HOST = "192.168.xxx.xxx:xxx"
5 HARBOR_USER = "xxx"
6 HARBOR_PASSWORD = "xxx"
7 HARBOR_PROJECT = "xxx"
8 PROJECT_NAME = "xxx"
9 DEPLOY_ENV = "test"
10 DEPLOY_PORT = "xxx"
11 PACKAGE_PATH = "./xxx/xxx/xxx.jar"
12 BUILD_VERSION = createVersion()
13 CLEAR_NONE_SSH = "n=`docker images | grep '<none>' | wc -l`; if [ \$n -gt 0 ]; then docker rmi `docker images | grep '<none>' | awk '{print \$3}'`; fi"
14 DEPLOY_REMOTE_01 = "192.168.100.xxx"
15 DEPLOY_REMOTE_02 = "192.168.100.xxx"
16 }
17 tools{
18 // 添加环境,名称为Jenkins全局配置中自己定义的别名
19 jdk 'jdk1.8.0_11'
20 maven 'apache-maven-3.6.2'
21 }
22 stages{
23 stage("拉取代码"){
24 //check CODE
25 steps {
26 checkout([$class: 'GitSCM', branches: [[name: '$Tag']], extensions: [], userRemoteConfigs: [[credentialsId: 'xxx', url: 'http://xxx:xxx/xxx/xxx.git']]])
27 }
28 }
29 stage("maven构建"){
30 steps {
31 sh "mvn clean package -P ${DEPLOY_ENV} -P jdk8 -Dmaven.test.skip=true"
32 }
33 }
34 stage("构建docker镜像,并push到harbor当中"){
35 //docker push
36 steps {
37 sh '''cat << EOF > Dockerfile
38 FROM openjdk:8-jre
39 MAINTAINER hawksoft hawksoft@qq.com
40 RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
41 COPY ${PACKAGE_PATH} /app.jar
42 ENTRYPOINT ["java", "-Xmx512m", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
43 CMD ["--spring.profiles.active=${DEPLOY_ENV}"]
44 '''
45 sh 'cat Dockerfile'
46 sh 'ls -l'
47 sh "docker build -t ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION ."
48 sh "docker login -u ${HARBOR_USER} -p '${HARBOR_PASSWORD}'" + " ${HARBOR_HOST}"
49 sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
50 sh "docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
51 }
52 }
53 stage("拉取docker镜像,并部署发布"){
54 steps {
55 deployAndRun("${DEPLOY_REMOTE_01}")
56 deployAndRun("${DEPLOY_REMOTE_02}")
57 }
58 }
59 }
60 }
61
62 // 定义一个版本号作为当次构建的版本,输出结果 20221209248576_103
63 def createVersion() {
64 return new Date().format('yyyyMMddHHmmss') + "_${env.BUILD_ID}"
65 }
66
67 // 声明一个方法,其中 withCredentials 是 Jenkins 凭据管理中添加过的凭据
68 def conRemote(ip){
69 def remote = [:]
70 remote.name = "test--->>>${PROJECT_NAME}------>>>>>>>${ip}"
71 remote.host = ip
72 remote.port = xxx
73 remote.allowAnyHosts = true
74 withCredentials([usernamePassword(credentialsId: 'xxx', passwordVariable: 'password', usernameVariable: 'userName')]) {
75 remote.user = "${userName}"
76 remote.password = "${password}"
77 }
78 return remote
79 }
80
81 // 部署运行
82 def deployAndRun(ip){
83 // 登录harbor
84 sshCommand remote: conRemote(ip), command: "docker login -u ${HARBOR_USER} -p '${HARBOR_PASSWORD}'" + " ${HARBOR_HOST}"
85 // 更新或下载镜像
86 sshCommand remote: conRemote(ip), command: "docker pull ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
87 // 打印所有镜像
88 sshCommand remote: conRemote(ip), command: "docker images"
89 try{
90 // 停止指定名称容器
91 sshCommand remote: conRemote(ip), command: "docker stop ${PROJECT_NAME}"
92 // 删除指定名称容器
93 sshCommand remote: conRemote(ip), command: "docker rm ${PROJECT_NAME}"
94 // 启动容器
95 sshCommand remote: conRemote(ip), command: "docker run -idt --name ${PROJECT_NAME} --restart=always -p ${DEPLOY_PORT}:xxx -v /home/docker/${PROJECT_NAME}/logs:/logs ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
96 // 删除未使用到的镜像
97 sshCommand remote: conRemote(ip), command: "docker image prune -a -f"
98 // 清理none镜像
99 sshCommand remote: conRemote(ip), command: "${CLEAR_NONE_SSH}"
100 }
101 catch (e){
102 // 启动容器
103 sshCommand remote: conRemote(ip), command: "docker run -idt --name ${PROJECT_NAME} --restart=always -p ${DEPLOY_PORT}:xxx -v /home/docker/${PROJECT_NAME}/logs:/logs ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
104 // 删除未使用到的镜像
105 sshCommand remote: conRemote(ip), command: "docker image prune -a -f"
106 // 清理none镜像
107 sshCommand remote: conRemote(ip), command: "${CLEAR_NONE_SSH}"
108 }
109 }
============================部署前端pieplie范例脚本============================
相关变量都以xxx代替,请自行替换
1 pipeline{
2 agent any
3 environment {
4 HARBOR_HOST = "192.168.100.xxx:xxx"
5 HARBOR_USER = "xxx"
6 HARBOR_PASSWORD = "xxx"
7 HARBOR_PROJECT = "xxx"
8 PROJECT_NAME = "xxx"
9 DEPLOY_ENV = "test"
10 PACKAGE_PATH = "./dist"
11 BUILD_VERSION = createVersion()
12 CLEAR_NONE_SSH = "n=`docker images | grep '<none>' | wc -l`; if [ \$n -gt 0 ]; then docker rmi `docker images | grep '<none>' | awk '{print \$3}'`; fi"
13 DEPLOY_REMOTE_01 = "192.168.xxx.xxx"
14 DEPLOY_PORT = "xxx"
15 }
16 tools{
17 // 添加环境,名称为Jenkins全局配置中自己定义的别名
18 nodejs 'node-v14.17.6'
19 }
20 stages{
21 stage("拉取代码"){
22 //check CODE
23 steps {
24 checkout([$class: 'GitSCM', branches: [[name: '$Tag']], extensions: [], userRemoteConfigs: [[credentialsId: 'xxx', url: 'http://xxx/xxx/xxx.git']]])
25 }
26 }
27 stage("build构建"){
28 steps {
29 sh '''
30 cnpm install
31 cnpm run build:${DEPLOY_ENV}
32 '''
33 }
34 }
35 stage("构建docker镜像,并push到harbor当中"){
36 //docker push
37 steps {
38 sh 'pwd'
39 sh '''cat << EOF > Dockerfile
40 # 设置基础镜像
41 FROM nginx:latest
42 # 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
43 COPY ${PACKAGE_PATH} /usr/share/nginx/html/
44 EXPOSE 80
45 CMD ["nginx", "-g", "daemon off;"]
46 '''
47 sh 'cat Dockerfile'
48 sh 'ls -l'
49 sh "docker build -t ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION ."
50 sh "docker login -u ${HARBOR_USER} -p '${HARBOR_PASSWORD}'" + " ${HARBOR_HOST}"
51 sh "docker push ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
52 sh "docker rmi ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
53 }
54 }
55 stage("拉取docker镜像,并部署发布"){
56 steps {
57 deployAndRun("${DEPLOY_REMOTE_01}")
58 }
59 }
60 }
61 }
62
63 // 定义一个版本号作为当次构建的版本,输出结果 20211029532456_17
64 def createVersion() {
65 return new Date().format('yyyyMMddHHmmss') + "_${env.BUILD_ID}"
66 }
67
68 // 声明一个方法,其中 withCredentials 是 Jenkins 凭据管理中添加过的凭据
69 def conRemote(ip){
70 def remote = [:]
71 remote.name = "dev-${PROJECT_NAME}------>>>>>>>${ip}"
72 remote.host = ip
73 remote.port = xxx
74 remote.allowAnyHosts = true
75 withCredentials([usernamePassword(credentialsId: 'xxx', passwordVariable: 'password', usernameVariable: 'userName')]) {
76 remote.user = "${userName}"
77 remote.password = "${password}"
78 }
79 return remote
80 }
81
82 // 部署运行
83 def deployAndRun(ip){
84 // 登录harbor
85 sshCommand remote: conRemote(ip), command: "docker login -u ${HARBOR_USER} -p '${HARBOR_PASSWORD}'" + " ${HARBOR_HOST}"
86 // 更新或下载镜像
87 sshCommand remote: conRemote(ip), command: "docker pull ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
88 // 打印所有镜像
89 sshCommand remote: conRemote(ip), command: "docker images"
90 try{
91 // 停止指定名称容器
92 sshCommand remote: conRemote(ip), command: "docker stop ${PROJECT_NAME}"
93 // 删除指定名称容器
94 sshCommand remote: conRemote(ip), command: "docker rm ${PROJECT_NAME}"
95 // 启动容器
96 sshCommand remote: conRemote(ip), command: "docker run -idt --name ${PROJECT_NAME} --restart=always -p ${DEPLOY_PORT}:80 ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
97 // 删除未使用到的镜像
98 sshCommand remote: conRemote(ip), command: "docker image prune -a -f"
99 // 清理none镜像
100 sshCommand remote: conRemote(ip), command: "${CLEAR_NONE_SSH}"
101 }
102 catch (e){
103 // 启动容器
104 sshCommand remote: conRemote(ip), command: "docker run -idt --name ${PROJECT_NAME} --restart=always -p ${DEPLOY_PORT}:80 ${HARBOR_HOST}/${HARBOR_PROJECT}/${PROJECT_NAME}:$BUILD_VERSION"
105 // 删除未使用到的镜像
106 sshCommand remote: conRemote(ip), command: "docker image prune -a -f"
107 // 清理none镜像
108 sshCommand remote: conRemote(ip), command: "${CLEAR_NONE_SSH}"
109 }
110 }
7,执行构建
第一次进入时只有master,需要先选master构建,而后下次构建时就会出现可供选择的branch或tag了

8,通过发布日志、harbor、portainer验证及查看发布情况




至此,轻量级CI/CD发布部署环境搭建及使用_07_jenkins配置pipeline
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po