jenkins專案釋出

呂林光發表於2021-11-11

一、簡介

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未優化版

七、原始碼地址:

八、參考

相關文章