栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

jenkins+springcloud+docker 自动化打包部署流程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

jenkins+springcloud+docker 自动化打包部署流程

jenkin安装下载


大致流程说明:
1)开发人员每天把代码提交到Gitlab代码仓库
2)Jenkins从Gitlab中拉取项目源码,编译并打成jar包,然后构建成Docker镜像,将镜像上传到
Harbor私有仓库。
3)Jenkins发送SSH远程命令,让生产部署服务器到Harbor私有仓库拉取镜像到本地,然后创建容器。
4)最后,用户可以访问到容器

1、 从gitlab拉取代码(自己可以用gitee或者github,看自己公司用哪个),本次主要以流水线形式来演示如何自动化打包部署微服务的jar

2、整个流程以脚本式脚本来执行整个自动化流程(自己可以用脚本式语言) 这个语言可以不用写,里面可以生成代码片段的,我们copy就可以了



checkout([$class: ‘GitSCM’, branches: [[name: ‘*/master’]], extensions: [], userRemoteConfigs: [[credentialsId: ‘fa0ff0a7-3b63-46b5-aaed-a7b357c23abe’, url: ‘http://192.168.0.121:82/root/online2022_admin.git’]]])

把上面生成的语法copy到我们编辑的脚本式文件里面

3、验证脚本是否可以拉取gitlab代码



正常拉取代码了

4. Pipeline Script from SCM 刚才我们都是直接在Jenkins的UI界面编写Pipeline代码,这样不方便脚本维护,建议把Pipeline脚本放在项目中(一起进行版本控制)

1)在项目根目录建立Jenkinsfile文件,把内容复制到该文件中


5. 演示拉取不同分支的代码来编译




6. 演示可以选择一个或者多个微服务编译打包

安装Extended Choice Parameter插件,支持多选框

//编译并安装公共工程
sh “mvn -f common clean install”

添加可以多选的项目打包编译


checkboxes选中值得格式我们采用逗号分隔每个项目,每个项目里面项目名和端口号以@分隔
例如: 项目名称1@8001,项目名称2@8002


infrastructure/api_gateway@8222,service/service_acl@8009,service/service_cms@8004,service/service_edu@8001,service/service_msm@8005,service/service_order@8007,service/service_oss@8002,service/service_statistics@8008,service/service_ucenter@8160,service/service_vod@8003

网关,权限,轮播图管理,后台系统主模块,验证码模块,订单模块,阿里云存储文件模块,统计模块,前台系统模块,阿里云音视频模块

stage('编译构建') {

        //编译并安装公共工程
        echo '编译并安装公共工程'
        sh "mvn -f common clean install"

        for(int i=0;i
            //取出每个项目的名称和端口
            def currentProject = selectedProjects[i];
            echo "${currentProject}"
            //项目名称
            def currentProjectName = currentProject.split('@')[0]
            //项目启动端口
            def currentProjectPort = currentProject.split('@')[1]
            echo "${currentProjectName}"
            echo "${currentProjectPort}"
            sh "mvn -f ${currentProjectName} clean package"
        }
}

上面得脚本中引用变量,必须在双引号里面,否则会有问题

注意该项目打包后jar大小是否是正常的,如果太小的话,证明jar里面是没有BOOT-INFO这个包的(自己可以用压缩工具打开看一下),这个jar是不能启动的。这种情况一般是spring-boot-maven-plugins不生效,
1)第一种情况:你的父项目没有继承spring-boot-parent,需要在每个微服务项目里面添加spring-boot-maven-plugin插件,并且指定每个微服务项目的入口文件(公共模块不需要引入spring-boot-maven-plugin插件)


        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                    com.atguigu.gateway.ApiGatewayApplication
                
                
                
                    
                        
                            repackage
                        
                    
                
            
        
    

2)第二种情况:你的父项目继承spring-boot-parent,那么只需要在父项目pom文件添加
spring-boot-maven-plugin插件,公共模块就排除spring-boot-maven-plugin插件就可以了

7. 编译打包后的jar,制作成docker 镜像

1)第一种办法(我们不采用)
在项目中生成Dockerfile 文件

进入该项目目录
docker build
–build-arg JAR_FILE=xx.jar
-f ${Dockerfile} -t ${projectImage} .

–build-arg是构建参数 JAR_FILE是我们Dockefile文件里面需要的参数
-f 指定Dockerfile位置(-f ${Dockerfile} 可以不写,默认会找该目录下的Dockerfile文件)
-t 后面的 projectImage表示镜像名称
最后.号是指镜像构建时打包上传到Docker引擎中的文件的目录,一定要加上去

2)第二种办法(采用),在项目中生成Dockerfile 文件,我们采用maven 有关dockerfile-maven-plugin插件,执行mvn dockerfile:build命令来生成镜像
Dockerfile文件内容:

# 拉取jdk8作为基础镜像
FROM openjdk:8-jdk-alpine
# 输入参数,改参数为打包后的jar包,例如 api_gateway/target/api_gateway-1.0-SNAPSHOT.jar
ARG JAR_FILE
# 添加jar到镜像并命名为app.jar, copy命令是把 api_gateway-1.0-SNAPSHOT.jar直接添加到镜像里面不解压,ADD是添加入镜像并且解压
COPY ${JAR_FILE} app.jar
# 镜像启动后暴露的端口
EXPOSE 8222
# jar运行命令,参数使用逗号隔开
ENTRYPOINT ["java","-jar","/app.jar"]

项目的pom文件添加dockerfile-maven-plugin插件


	
		
		    com.spotify
		    dockerfile-maven-plugin
		    1.4.13
		    
		        ${project.artifactId}
		        
		            target/${project.build.finalName}.jar
		        
		    
		
	

在原有的Jenkinsfile文件添加

 sh "mvn -f ${currentProjectName} dockerfile:build"


jenkins构建结果


我们手动运行一下
docker run -di --name=api_gateway -p 8222:8222 api_gateway:latest
查看一下启动日志 (我这个项目是需要注册中心nacos,自己在nacos安装一下2.x版本nacos启动就可以了)
docker logs -f api_gateway


以上已经完成 选中的微服务项目编译打包,并且制作成docker镜像了,如果不需要私服镜像仓库的话,就部署和jenkins同一台机器上面的话,自己在Jenkinsfile文件加一下docker 运行镜像的shell命令就可以了,每次编译前都要停止对应项目的容器,删除容器和镜像。

如有需要搭建镜像私服Harbor来存储docker制作执行,并且新的服务器可以从Harbor上拉取镜像并且运行成容器的,请往下面看

7. jenkins把jar包构建成docker镜像,将镜像上传到我们得私有仓库里面(Harbor) 8. 安装docker-compose(1.25.1版本)

1)先安装docker-compose
[root@localhost bin]# sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose

2)给docker-compose添加执行权限
[root@localhost bin]# sudo chmod +x /usr/local/bin/docker-compose

3)查看docker-compose是否安装成功
docker-compose -version

4)下载Harbor的压缩包(版本为:v1.9.2)
https://github.com/goharbor/harbor/releases

5)上传压缩包到linux,并解压
tar -xzf harbor-offline-installer-v1.9.2.tgz
mkdir /opt/harbor
mv harbor${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'http://192.168.0.121:82/root/online2022_admin.git']]]) } stage('编译构建') { //编译并安装公共工程 sh "mvn -f common clean install" for(int i=0;i //取出每个项目的名称和端口 def currentProject = selectedProjects[i]; //项目名称 def currentProjectName = currentProject.split('@')[0] //项目启动端口 def currentProjectPort = currentProject.split('@')[1] // 编译打包选中微服务项目 sh "mvn -f ${currentProjectName} clean package" // 生成镜像 sh "mvn -f ${currentProjectName} dockerfile:build" //定义镜像名称(因为原本微服务项目前面还有一个父项目的,所以 必须获取到项目的真正名称 ,例如 infrastructure/api_gateway 变成 api_gateway) def realProjectName = currentProjectName.split("/") def realName = realProjectName[realProjectName.length-1] def imageName = "${realName}:${tag}" //登录 sh "docker login -u ${username} -p ${password} ${harbor_url}" //给镜像打标签 sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}" //上传镜像 sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}" //删除本地镜像 (根据镜像名称删除镜像和打标签的镜像,因为原本的镜像和打包后镜像是同一个镜像id,无法通过镜像id删除镜像) sh "docker rmi -f ${imageName}" sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}" } // infrastructure/api_gateway@8222,service/service_acl@8009,service/service_cms@8004,service/service_edu@8001,service/service_msm@8005,service/service_order@8007,service/service_oss@8002,service/service_statistics@8008,service/service_ucenter@8160,service/service_vod@8003 // 网关,权限,轮播图管理,后台系统主模块,验证码模块,订单模块,阿里云存储文件模块,统计模块,前台系统模块,阿里云音视频模块 } }

效果图

如果怕harbor账号密码泄露,在jenkins凭证管理添加全局配置

添加后会自动生成id,这个id就可以直接关联harbor账号和密码了

用jenkins的流水线语法生成器生成脚本片段

withCredentials([usernamePassword(credentialsId: '262b0b77-61b6-493c-9bb4-bf0659365903', passwordVariable: 'password', usernameVariable: 'username')]) {
    // some block
}

改造后的Jenkinsfile内容

//gitlab的凭证
def git_auth = "fa0ff0a7-3b63-46b5-aaed-a7b357c23abe"

//构建版本的名称
def tag = "latest"

//Harbor私服地址
def harbor_url = "192.168.0.121:85"

//Harbor的项目名称
def harbor_project_name = "online2022_admin"

// harbor用户凭证(全局凭证管理那里配置)
def harbor_auth = "262b0b77-61b6-493c-9bb4-bf0659365903"


node {
    //把选择的项目信息转为数组
    def selectedProjects = "${project_name}".split(',')
    echo "${selectedProjects}"

    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'http://192.168.0.121:82/root/online2022_admin.git']]])
    }

    stage('编译构建') {
        //编译并安装公共工程
        sh "mvn -f common clean install"

        for(int i=0;i
            //取出每个项目的名称和端口
            def currentProject = selectedProjects[i];
            //项目名称
            def currentProjectName = currentProject.split('@')[0]
            //项目启动端口
            def currentProjectPort = currentProject.split('@')[1]

            // 编译打包选中微服务项目
            sh "mvn -f ${currentProjectName} clean package"

            // 生成镜像
            sh "mvn -f ${currentProjectName} dockerfile:build"

            //定义镜像名称(因为原本微服务项目前面还有一个父项目的,所以 必须获取到项目的真正名称 ,例如 infrastructure/api_gateway 变成 api_gateway)
            def realProjectName = currentProjectName.split("/")
            def realName = realProjectName[realProjectName.length-1]
            def imageName = "${realName}:${tag}"

            //给镜像打标签
            sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"


            withCredentials([usernamePassword(credentialsId: '262b0b77-61b6-493c-9bb4-bf0659365903', passwordVariable: 'password', usernameVariable: 'username')]) {
                //登录
                sh "docker login -u ${username} -p ${password} ${harbor_url}"
                //上传镜像
                sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
            }

            //删除本地镜像 (根据镜像名称删除镜像和打标签的镜像,因为原本的镜像和打包后镜像是同一个镜像id,无法通过镜像id删除镜像)
            sh "docker rmi -f ${imageName}"
            sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"

        }
        // infrastructure/api_gateway@8222,service/service_acl@8009,service/service_cms@8004,service/service_edu@8001,service/service_msm@8005,service/service_order@8007,service/service_oss@8002,service/service_statistics@8008,service/service_ucenter@8160,service/service_vod@8003
        // 网关,权限,轮播图管理,后台系统主模块,验证码模块,订单模块,阿里云存储文件模块,统计模块,前台系统模块,阿里云音视频模块
    }
}
10. 部署服务器(192.168.0.130)从harbor(192.168.121)上拉取镜像并且运行镜像

1)jenkins(192.168.0.120) 所在的机器 上生成密钥:
[root@mycentos .ssh]# ssh-keygen
不断回车就好了

2)拷贝公钥到远程服务器(192.168.0.130)

ssh-copy-id 192.168.0.130


3)尝试在jenkin(192.168.0.120)机器上ssh登录部署服务器(192.168.0.130)

如果连接失败jenkins尝试连接失败,请开启sshd服务

sudo service sshd start  //开启sshd服务
 ssh root@192.168.0.130

4)jenkins 192.168.0.120(系统配置)->添加远程服务器

设置私钥位置
/root/.ssh/id_rsa


5)如果jenkins用ssh连接部署服务器失败的话,估计是jenkins不支持所在机器生成的私钥(机器版本太高了)

先移除known_hosts文件
rm -rf /root/.ssh/known_hosts

重新生成密钥
ssh-keygen -m PEM -t rsa -b 4096

重新把公钥给部署服务器
ssh root@192.168.0.130

  1. 生成调用部署服务器的脚本
  2. 因为我们的调用的是我们自己的部署脚本,这个脚本是要传结果参数的,我改造一下生成的脚本
sshPublisher(publishers: [sshPublisherDesc(configName: 'pro_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_project_name} ${realName} ${tag} ${currentProjectPort}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

完整jenkins流水想脚本

//gitlab的凭证
def git_auth = "fa0ff0a7-3b63-46b5-aaed-a7b357c23abe"

//构建版本的名称
def tag = "latest"

//Harbor私服地址
def harbor_url = "192.168.0.121:85"

//Harbor的项目名称
def harbor_project_name = "online2022_admin"

// harbor用户凭证(全局凭证管理那里配置)
def harbor_auth = "262b0b77-61b6-493c-9bb4-bf0659365903"


node {
    //把选择的项目信息转为数组
    def selectedProjects = "${project_name}".split(',')
    echo "${selectedProjects}"

    stage('拉取代码') {
        checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: 'http://192.168.0.121:82/root/online2022_admin.git']]])
    }

    stage('编译构建') {
        //编译并安装公共工程
        sh "mvn -f common clean install"

        for(int i=0;i
            //取出每个项目的名称和端口
            def currentProject = selectedProjects[i];
            //项目名称
            def currentProjectName = currentProject.split('@')[0]
            //项目启动端口
            def currentProjectPort = currentProject.split('@')[1]

            // 编译打包选中微服务项目
            sh "mvn -f ${currentProjectName} clean package"

            // 生成镜像
            sh "mvn -f ${currentProjectName} dockerfile:build"

            //定义镜像名称(因为原本微服务项目前面还有一个父项目的,所以 必须获取到项目的真正名称 ,例如 infrastructure/api_gateway 变成 api_gateway)
            def realProjectName = currentProjectName.split("/")
            def realName = realProjectName[realProjectName.length-1]
            def imageName = "${realName}:${tag}"

            //给镜像打标签
            sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"


            withCredentials([usernamePassword(credentialsId: '262b0b77-61b6-493c-9bb4-bf0659365903', passwordVariable: 'password', usernameVariable: 'username')]) {
                //登录
                sh "docker login -u ${username} -p ${password} ${harbor_url}"
                //上传镜像
                sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
            }

            //删除本地镜像 (根据镜像名称删除镜像和打标签的镜像,因为原本的镜像和打包后镜像是同一个镜像id,无法通过镜像id删除镜像)
            sh "docker rmi -f ${imageName}"
            sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"

            //=====以下为远程调用进行项目部署========
            sshPublisher(publishers: [sshPublisherDesc(configName: 'pro_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh ${harbor_url} ${harbor_project_name} ${realName} ${tag} ${currentProjectPort}", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

        }



        // =================================这个是jenkins部署多参数用到的值,可以直接复制黏贴过去来改
        // infrastructure/api_gateway@8222,service/service_acl@8009,service/service_cms@8004,service/service_edu@8001,service/service_msm@8005,service/service_order@8007,service/service_oss@8002,service/service_statistics@8008,service/service_ucenter@8160,service/service_vod@8003
        // 网关,权限,轮播图管理,后台系统主模块,验证码模块,订单模块,阿里云存储文件模块,统计模块,前台系统模块,阿里云音视频模块
    }
}

8)部署服务器(192.168.0.130) 添加harbot信任列表

{
 "registry-mirrors": ["https://zydiol88.mirror.aliyuncs.com"],
 "insecure-registries": ["192.168.0.121:85"]
}

  1. 部署服务器(192.168.0.130)重启docker
    systemctl restart docker
    如果在192.168.0.130的docker 登录 192.168.0.121(harbor)失败的话,重启一下192.168.0.121的harbor
cd  /opt/harbor   
docker-compose stop
docker-compose up -d

10)部署服务器(192.168.0.130)的deploy.sh内容

#! /bin/sh
#接收外部参数
harbor_url=$1
harbor_project_name=$2
project_name=$3
tag=$4
port=$5
imageName=$harbor_url/$harbor_project_name/$project_name:$tag
echo "$imageName"
#查询容器是否存在,存在则删除
# docker ps -a 查询所有的容器(无论启动还是停止)
# grep -w 根据一个单词来全匹配查询
# awk '{print $1}' 对于获取来的每行数据,按空格分隔,取第1列的值,$2表示拿第二列的值
containerId=`docker ps -a | grep -w ${project_name}:${tag} | awk '{print $1}'`
if [ "$containerId" != "" ] ; then
    #停掉容器
    docker stop $containerId
    #删除容器
    docker rm $containerId
    echo "成功删除容器"
fi
#查询镜像是否存在,存在则删除
imageId=`docker images | grep -w $project_name | awk '{print $3}'`
if [ "$imageId" != "" ] ; then
    #删除镜像
    docker rmi -f $imageId
    echo "成功删除镜像"
fi
# 登录Harbor私服(自己手动登录harbor的话记得加上harbor的端口号,例如docker login -u lijun -p Lijun123456 192.168.0.121:85)
docker login -u lijun -p Lijun123456 $harbor_url
# 下载镜像
docker pull $imageName
# 启动容器
docker run -di -p $port:$port $imageName
echo "容器启动成功"

9)效果图

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/914765.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号