jenkins项目发布
一、简介
1、该章节基于jenkins、Harbor、pipeline来做发布,如对这些不熟悉,请按以下进入学习
2、jenkins学习地址:https://www.cnblogs.com/lvlinguang/p/15163691.html
3、Harbor学习地址:https://www.cnblogs.com/lvlinguang/p/15500171.html
4、pipeline学习地址:https://www.cnblogs.com/lvlinguang/p/15512349.html
二、docker打包
一、后端打包
1、git代码拉取
# 使用checkout拉取代码
checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: 'a8db6793-cc2b-4d82-bd3d-c5beb1c5149e', url: 'https://gitee.com/lvlinguang/rapid-demo-back.git']]])
# 使用git branch拉取代码
git branch: 'master', credentialsId: 'a8db6793-cc2b-4d82-bd3d-c5beb1c5149e', url: 'https://gitee.com/lvlinguang/rapid-demo-back.git'
2、mvn打包
mvn -U clean install -Dmaven.test.skip=true
3、docker打包
- 使用maven插件打包并推送到Harbor
mvn dockerfile:build dockerfile:push
- 使用docker打包并推送到Harbor
# docker打包
docker build -t 192.168.3.12:1180/library/rapid-demo-back:v2.1.2 .
// harbor登录
withCredentials([usernamePassword(credentialsId: '8d4ff3de-9b05-427d-a211-23be72f65bbb', passwordVariable: 'password', usernameVariable: 'username')]) {
sh "docker login -u ${username} -p ${password} ${dockerRegistry}"
}
# docker推送到Harbor
docker push 192.168.3.12:1180/library/rapid-demo-back:v2.1.2
4、删除本地镜像
docker rmi 192.168.3.12:1180/library/rapid-demo-back:v2.1.2
5、Dockerfile内容
# jdk版本
FROM java:8
# 临时文件目录
VOLUME /tmp
ADD target/*.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
二、前端打包
1、checkout代码下载
2、nodeJs打包
- 打包后目录下会生成dist文件
nodejs('node-v12.20.0') {
sh 'npm install --registry=https://registry.npm.taobao.org'
sh 'npm run build'
}
3、复制文件
mv ../build_fronted_dist/dist ./dist
mv ../build_fronted_dist/Dockerfile ./Dockerfile
mv ../build_fronted_dist/nginx.conf ./nginx.conf
4、docker打包
docker build -t 192.168.3.12:1180/library/rapid-demo-web:v2.1.2 .
5、推送到Harbor
withCredentials([usernamePassword(credentialsId: '8d4ff3de-9b05-427d-a211-23be72f65bbb', passwordVariable: 'password', usernameVariable: 'username')]) {
// harbor登录
sh "docker login -u ${username} -p ${password} ${dockerRegistry}"
// 推送Harbor
docker push 192.168.3.12:1180/library/rapid-demo-web:v2.1.2
}
6、删除本地镜像
docker rmi 192.168.3.12:1180/library/rapid-demo-web:v2.1.2
7、Dockerfile内容
FROM nginx:alpine
COPY ./dist/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf
8、nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
三、启动容器
1、查询容器是否存在,存在则删除
# 容器id
containerId=$(docker ps -a | grep -w "rapid-demo-back" | awk '{print $1}')
if [ "$containerId" != "" ] ;
then
#停掉容器
docker stop "$containerId"
#删除容器
docker rm "$containerId"
fi
2、查询镜像是否存在,存在则删除
# 镜像id
imageId=$(docker images | grep -w "rapid-demo-back" | awk '{print $3}')
if [ "$imageId" != "" ] ;
then
#删除镜像
docker rmi -f "$imageId"
fi
3、下载镜像
docker pull 192.168.3.12:1180/library/rapid-demo-back:v2.1.2
4、启动容器
docker run -d --name rapid-demo-back -p 6001:8080 192.168.3.12:1180/library/rapid-demo-back:v2.1.2
四、完整代码
1、pipeline script
pipeline {
agent any
environment{
dockerRegistry="192.168.3.12:1180"
//后端变量
backPort= 7001
backServerPort=8080
backName="rapid-demo-back"
backGitUrl="https://gitee.com/lvlinguang/rapid-demo-back.git"
backBranch="*/master"
backDockerImage="${dockerRegistry}/library/${backName}:v2.1.2"
//前端变量
frontPort= 7002
frontServerPort=8080
frontName="rapid-demo-web"
frontGitUrl="https://gitee.com/lvlinguang/rapid-demo-web.git"
frontBranch="*/master"
frontDockerImage="${dockerRegistry}/library/${frontName}:v2.1.2"
}
parameters {
booleanParam(name: 'ENABLE_BACKEND_BUILD', defaultValue: false, description: '开启后端构建')
booleanParam(name: 'ENABLE_FRONTED_BUILD', defaultValue: false, description: '开启前端构建')
booleanParam(name: 'ENABLE_BACKEND_DEPLOY', defaultValue: false, description: '开启后端部署')
booleanParam(name: 'ENABLE_FRONTED_DEPLOY', defaultValue: false, description: '开启前端部署')
}
stages {
stage('初始化') {
steps {
echo '初始化。。。'
}
}
stage('后端打包'){
when{
expression{params.ENABLE_BACKEND_BUILD}
}
steps{
script{
ws("backend_build"){
dir("build_backend_docker"){
// git代码拉取。。。
gitClone(backGitUrl, backBranch);
// mvn打包。。。
sh "/usr/local/apache-maven-3.8.2/bin/mvn -U clean install -Dmaven.test.skip=true"
// docker打包。。。
sh "docker build -t ${backDockerImage} ."
// harbor登录
withCredentials([usernamePassword(credentialsId: '8d4ff3de-9b05-427d-a211-23be72f65bbb', passwordVariable: 'password', usernameVariable: 'username')]) {
sh "docker login -u ${username} -p ${password} ${dockerRegistry}"
}
// docker推送至Harbor
sh "docker push ${backDockerImage}"
// 删除镜像
sh "docker rmi ${backDockerImage}"
}
echo '打包完成。。。'
// 删除backend_build工作目录
cleanWs()
}
}
}
}
//前端打包
stage('前端打包'){
when {
expression { params.ENABLE_FRONTED_BUILD }
}
steps {
script {
echo '前端打包。。。'
ws("fronted_build"){
dir("build_fronted_dist"){
// git代码拉取。。。
gitClone(frontGitUrl, frontBranch);
// nodejs的npm进行打包。。。
nodejs('node-v12.20.0') {
sh 'npm install --registry=https://registry.npm.taobao.org'
sh 'npm run build'
}
}
dir("build_fronted_docker"){
// 复制dist、dockerfile、nginx文件。。。
sh "mv ../build_fronted_dist/dist ./dist"
sh "mv ../build_fronted_dist/Dockerfile ./Dockerfile"
sh "mv ../build_fronted_dist/nginx.conf ./nginx.conf"
// docker打包。。。
sh "docker build -t ${frontDockerImage} ."
// harbor登录
withCredentials([usernamePassword(credentialsId: '8d4ff3de-9b05-427d-a211-23be72f65bbb', passwordVariable: 'password', usernameVariable: 'username')]) {
sh "docker login -u ${username} -p ${password} ${dockerRegistry}"
}
// docker推送至Harbor
sh "docker push ${frontDockerImage}"
// 删除镜像
sh "docker rmi ${frontDockerImage}"
}
echo '打包完成。。。'
// 删除backend_build工作目录
cleanWs()
}
}
}
}
stage('测试') {
steps {
echo '测试。。。'
}
}
stage('后端发布') {
when{
expression{params.ENABLE_BACKEND_DEPLOY}
}
steps {
script {
echo '后端发布。。。'
// 远程服务器
def sshServer = getRemoteServer('192.168.3.15')
//remote发布
sshCommand remote: sshServer, command: "/usr/local/java/deploy.sh $backName $backDockerImage $backPort $backServerPort"
}
}
}
stage('前端发布') {
when{
expression{params.ENABLE_FRONTED_DEPLOY}
}
steps {
script{
echo '前端发布。。。'
// 远程服务器
def sshServer = getRemoteServer('192.168.3.15')
//remote发布
sshCommand remote: sshServer, command: "/usr/local/java/deploy.sh $frontName $frontDockerImage $frontPort $frontServerPort"
}
}
}
}
}
//获取远程服务器
def getRemoteServer(String ip='192.168.3.15',String credentialsId='67cc51e8-9614-43c2-9ea1-2070ee9407c6'){
def remote = [:]
remote.name = ip
remote.host = ip
remote.port = 22
remote.allowAnyHosts = true
withCredentials([usernamePassword(credentialsId: credentialsId, passwordVariable: 'password', usernameVariable: 'username')]) {
remote.user = "${username}"
remote.password = "${password}"
}
return remote
}
//git代码下载
def gitClone(String gitUrl, String gitBranch, String credentialsId = 'b494c748-17fd-4356-8218-5131b5ea5b92') {
checkout([
$class : 'GitSCM',
branches : [[name: gitBranch]],
extensions : [],
userRemoteConfigs: [[
credentialsId: credentialsId,
url : gitUrl
]]
])
}
2、deploy.sh
#接收外部参数,由jenkinsfile执行部署脚本时传递
projectName=$1
imageName=$2
port=$3
serverPort=$4
echo "镜像名: $imageName"
echo "项目名: $projectName"
# 容器id
containerId=$(docker ps -a | grep -w "${projectName}" | awk '{print $1}')
if [ "$containerId" != "" ] ;
then
#停掉容器
docker stop "$containerId"
#删除容器
docker rm "$containerId"
echo "成功删除容器"
fi
# 镜像id
imageId=$(docker images | grep -w "${projectName}" | awk '{print $3}')
if [ "$imageId" != "" ] ;
then
#删除镜像
docker rmi -f "$imageId"
echo "成功删除镜像"
fi
# 镜像下载
docker pull "$imageName"
# 启动容器
docker run -d --name "$projectName" -p"${port}":"${serverPort}" $imageName
echo "容器启动成功"
五、发布测试
1、jenkins新建pipeline项目,使用上面的pipeline script

2、发布测试


3、服务器查看项目是否启动

4、访问测试:192.168.3.15:7002

六、优化方案
1、新建docker-build工程,如下

2、新建pipeline项目


2、目录介绍
- config:项目配置信息,config.json配置了项目地址、docker信息、发布信息等
- scripts:打包脚本和发布脚本
- 公共变量:common_var.groovy
- 工具类:common_util.groovy
- 后端打包:build_backend.groovy
- 前端打包:build_fronted.groovy
- 后端发布:publish_backend.groovy
- 前端发布:publish_fronted.groovy
- Jenkinsfile:pipeline脚本,jenkins项目选择该文件
- build_back:脚本备份,deploy.sh通用发布,Jenkinsfile未优化版
七、源码地址:
- 前端源码:https://gitee.com/lvlinguang/rapid-demo-web
- 后端源码:https://gitee.com/lvlinguang/rapid-demo-back
- docker-build:https://gitee.com/lvlinguang/docker-build
八、参考
- https://www.jianshu.com/p/1401e2fe4711
- remote ssh使用:https://www.cnblogs.com/dreamer-fish/p/13524138.html
- nodeJs安装:https://blog.csdn.net/liumiaocn/article/details/102618269
- npm淘宝镜像设置:https://www.jianshu.com/p/1d8debb671a7
- vue项目部署:https://www.cnblogs.com/blue-rain/p/12463133.html
- vue项目部署:https://blog.csdn.net/mumushuiding/article/details/94452574
jenkins项目发布的更多相关文章
- jenkins 项目发布脚本
构建shell #!/bin/bash ########################################################################## 编译部分 ...
- [原]Jenkins(七)---jenkins项目编译测试发布由maven构建的web项目
/** * lihaibo * 文章内容都是根据自己工作情况实践得出. * 版权声明:本博客欢迎转发,但请保留原作者信息! http://www.cnblogs.com/horizonli/p/533 ...
- [原]Jenkins(九)---jenkins分别发布多个项目到多个远程主机
/** * lihaibo * 文章内容都是根据自己工作情况实践得出. * 版权声明:本博客欢迎转发,但请保留原作者信息! http://www.cnblogs.com/horizonli/p/533 ...
- Jenkins实用发布与回滚PHP项目生产实践
目录 1.概述 2.项目实践 2.1.环境说明 2.2.Jenkins配置 2.2.1.修改Jenkins的运行用户 2.2.2.配置Jenkins用户和Gitlab的ssh-key 2.2.3.Je ...
- Gitlab + Jenkins 构建,发布一个基于Go的Gin测试项目
部署Go项目简介 对于golang的发布,之前一直没有一套规范的发布流程,来看看之前发布流程: 方案一 • 开发者本地环境需要将环境变量文件改为正式环境配置 • 编译成可执行文件 • 发送给运维 • ...
- jenkins+docker+k8s项目发布
目录 一.简介 二.新建docker-build工程 三.项目部署 四.访问测试 一.简介 1.该章节基于jenkins.Harbor.pipeline.k8s来做发布,如对这些不熟悉,请按以下进入学 ...
- jenkins自动发布java代码
注:本文来源于<KaliArch> jenkins笔记 一.相关概念 1.1 Jenkins概念: Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台. ...
- Jenkins自动发布代码实战篇
Jenkins自动发布代码实战篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Jenkins服务器配置秘钥对并上传到Gitlab中 1>.在Jenkins后端生成秘钥 ...
- 记录.NET Core在CentOS上基于Jenkins自动化发布
1.安装Jenkins,我这里采用的是非docker方式安装(两种都行,任选一种) 参考:https://www.cnblogs.com/xiaxiaolu/p/10357806.html https ...
随机推荐
- 新一代容器平台ACK Anywhere,来了
5G.AR.AIoT 等场景在推动新一代云架构的演进,而容器重塑了云的使用方式. 近日,阿里云容器服务全面升级为ACK Anywhere,让企业在任何需要云的地方,都能获得一致的容器基础设施能力. 早 ...
- iOS Swift逻辑运算符
运算符 运算符分类 从操作数角度看:运算符包括一元.二元.三元.这里的一二三指操作数的数量,操作数指的是被操作的数值. 从运算符位置看:运算符分为前缀.中缀.后缀.例如:!b, b + c, c! 赋 ...
- Java-爬虫-小项目
爬取数据:(获取请求返回的页面信息,筛选出我们想要的数据就可以了!) 项目地址:https://gitee.com/zwtgit/java-reptile 导入依赖,写一个工具类 <depend ...
- java 从零开始手写 RPC (05) reflect 反射实现通用调用之服务端
通用调用 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 java 从零开始手写 RPC (03) 如何 ...
- ECMA 2022 (es13) 新特性
本文主要整理了截至到 2021年10月12日 为止的且处于 Stage 3->Stage 4 阶段的ECMA提案. 主要包括: Class Fields RegExp Match Indices ...
- keystore password was incorrect
一.问题由来 最近在部署后台系统项目的时候,希望给项目增加一些安全措施,在项目中添加了SSL证书,可是在自己添加完该证书后,测试启动项目立马报错. 报错信息如下: org.springframewor ...
- linux下修改IP地址的方法
linux下修改IP地址的方法 1.网卡的命名规则 在centos7中,en表示着:ethernet以太网,即现在所用的局域网,enX(X常见有以下3种类型) 2.IP地址的临时修改(重启后失效) 查 ...
- LeetCode352 将数据流变为多个不相交区间
LeetCode352 将数据流变为多个不相交区间 1 题目 给你一个由非负整数 a1, a2, ..., an 组成的数据流输入,请你将到目前为止看到的数字总结为不相交的区间列表. 实现 Summa ...
- python中的 * 和 ** 作用含义
python中的 * 和 ** ,能够让函数支持任意数量的参数,它们在函数定义和调用中,有着不同的目的 一. 打包参数 * 的作用:在函数定义中,收集所有位置参数到一个新的元组,并将整个元组赋值给变量 ...
- 无法获取指向控制台的文件描述符 (couldn't get a file descriptor referring to the console)
背景 最近收拾东西,从一堆杂物里翻出来尘封四年多的树莓派 3B 主机来,打扫打扫灰尘,接上电源,居然还能通过之前设置好的 VNC 连上.欣慰之余,开始 clone 我的 git 项目,为它们拓展一个新 ...