4 Jenkins+Docker+SpringCloud微服務持續集成(上)


4 Jenkins+Docker+SpringCloud微服務持續集成(上)

4.1 Jenkins+Docker+SpringCloud持續集成流程說明

image-20210522102230391

大致流程說明:

1)開發人員每天把代碼提交到Gitlab代碼倉庫

2)Jenkins從Gitlab中拉取項目源碼,編譯並打成jar包,然后構建成Docker鏡像,將鏡像上傳到Harbor私有倉庫。

3)Jenkins發送SSH遠程命令,讓生產部署服務器到Harbor私有倉庫拉取鏡像到本地,然后創建容器。

4)最后,用戶可以訪問到容器

服務列表

名稱 IP地址 安裝軟件
持續基礎服務器 192.168.5.3 jenkins,JDK,Maven,Git,SonarQube,Docker,MySQL
代碼托管服務器 192.168.5.4 gitlab-ce
Docker倉庫服務器 192.168.5.5 Docker,Harbor
生產部署服務器 192.168.5.6 Docker

4.2 SpringCloud微服務源碼概述

# 測試代碼下載地址
wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/tensquareAdmin.zip
wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/tensquare_parent.zip
# 數據庫文件下載
wget https://cunqi0105-1300757323.cos.ap-shanghai.myqcloud.com/configuration-file/mysql-sql.zip

項目架構:前后端分離

后端技術棧:SpringBoot+SpringCloud+SpringDataJpa(Spring全家桶)

微服務項目結構:

image-20210522192902530

  • tensquare_parent:父工程,存放基礎配置

  • tensquare_common:通用工程,存放工具類

  • tensquare_eureka_server:SpringCloud的Eureka注冊中心

  • tensquare_zuul:SpringCloud的網關服務

  • tensquare_admin_service:基礎權限認證中心,負責用戶認證(使用JWT認證)

  • tensquare_gathering:一個簡單的業務模塊,活動微服務相關邏輯

數據庫結構:

image-20210522203821293

  • tensquare_user:用戶認證數據庫,存放用戶賬戶數據。對應tensquare_admin_service微服務

  • tensquare_gathering:活動微服務數據庫。對應tensquare_gathering微服務

微服務配置分析:

  • tensquare_eureka

  • tensquare_zuul

  • tensquare_admin_service

  • tensquare_gathering

4.3 環境准備(1)-Docker安裝

詳細請參考文檔:Linux-Docker安裝

4.5 環境准備(2)-Harbor鏡像倉庫安裝及使用

詳細請參考文檔:企業級鏡像倉庫Harbor

4.6 微服務持續集成(1)-項目代碼上傳到Gitlab

在IDEA操作即可,參考之前的步驟。包括后台微服務和前端web網站代碼

image-20210522211325644

4.7 微服務持續集成(2)-從Gitlab拉取項目源碼

1)Jenkins上創建 tenquare_back任務

image-20210531212714539

2) 創建參數化構建函數

image-20210601193147152

image-20210601193216214

3)生成流水線腳本

image-20210601193056841

image-20210601193043855

4)創建Jenkinsfile文件

image-20210601193717633

//gitlab的憑證
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"

node {
  stage('拉取代碼') {
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
  }
}

5)上傳代碼

image-20210601193706248

6)項目測試

image-20210601193906844

4.8 微服務持續集成(3)-提交到SonarQube代碼審查

1) 創建參數化構建函數

image-20210601195108961

image-20210601195207091

2)在每個微服務項目的根目錄下添加sonar-project.properties

image-20210601195524633

# must be unique in a given SonarQube instance
sonar.projectKey=項目名稱
# this is the name and version displayed in the SonarQube UI. Was mandatory
prior to SonarQube 6.1.
sonar.projectName=項目名稱
sonar.projectVersion=1.0

# Path is relative to the sonar-project.properties file. Replace "\" by "/" on
Windows.
# This property is optional if sonar.modules is set.
sonar.sources=.
sonar.exclusions=**/test/**,**/target/**
sonar.java.binaries=.

sonar.java.source=1.8
sonar.java.target=1.8
# sonar.java.libraries=**/target/classes/**

# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8

3)修改Jenkinsfile構建腳本

//gitlab的憑證
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 構建版本的名稱
def tag = "latest"

node {
  stage('拉取代碼') {
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
  }
stage('代碼審查') {
//定義當前Jenkins的SonarQubeScanner工具
def scannerHome = tool 'sonarqube-scanner'
//引用當前Jenkins SonarQube環境
withSonarQubeEnv('sonarqube') {
sh """
cd ${project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
}

image-20210601202109620

4)項目測試

image-20210601202522600

4.9 微服務持續集成(4)-使用Dockerfile編譯、生成鏡像

利用dockerfile-maven-plugin插件構建Docker鏡像 1)在每個微服務項目的pom.xml加入dockerfile-maven-plugin插件(依賴父工程tensquare_common,不需要添加)

<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>${project.artifactId}</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>

2)在每個微服務項目根目錄下建立Dockerfile文件(依賴父工程tensquare_common,不需要添加)

#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 10086
ENTRYPOINT ["java","-jar","/app.jar"]

注意:每個項目公開的端口不一樣

3)修改Jenkinsfile構建腳本

//gitlab的憑證
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 構建版本的名稱
def tag = "latest"

node {
  stage('拉取代碼') {
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
  }
stage('代碼審查') {
//定義當前Jenkins的SonarQubeScanner工具
def scannerHome = tool 'sonarqube-scanner'
//引用當前Jenkins SonarQube環境
withSonarQubeEnv('sonarqube') {
sh """
cd ${project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
stage('編譯,構建鏡像') {
//定義鏡像名稱
def imageName = "${project_name}:${tag}"

//編譯,安裝公共工程
sh "mvn -f tensquare_common clean install"

//編譯,構建本地鏡像
sh "mvn -f ${project_name} clean package dockerfile:build"
}
}

4)項目測試

image-20210601215323430

image-20210601221717697

5)編譯失敗

image-20210601221252458

出現這種問題,是因為微服務具有相關的依賴,需要將tensquare_parent項目手動上傳到maven本地倉庫中

image-20210601221402534

4.10 微服務持續集成(5)-上傳到Harbor鏡像倉庫

1)使用憑證管理Harbor私服賬戶和密碼

image-20210601222731302

2)生成憑證腳本代碼

image-20210601222526370

image-20210601222629421

3)修改Jenkinsfile構建腳本

//gitlab的憑證
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 構建版本的名稱
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.5.5:8080"
//Harbor的項目名稱
def harbor_project_name = "tensquare"
//Harbor的憑證
def harbor_auth = "cd0b948d-e82b-4c0c-8a7c-8c6b8fb5454b"
node {
  stage('拉取代碼') {
      checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
  }
stage('代碼審查') {
//定義當前Jenkins的SonarQubeScanner工具
def scannerHome = tool 'sonarqube-scanner'
//引用當前Jenkins SonarQube環境
withSonarQubeEnv('sonarqube') {
sh """
cd ${project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
stage('編譯,構建鏡像') {
//定義鏡像名稱
def imageName = "${project_name}:${tag}"

//編譯,安裝公共工程
sh "mvn -f tensquare_common clean install"

//編譯,構建本地鏡像
sh "mvn -f ${project_name} clean package dockerfile:build"

//給鏡像打標簽
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登錄Harbor,並上傳鏡像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}",passwordVariable: 'password', usernameVariable: 'username')]) {

//登錄
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上傳鏡像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}

//刪除本地鏡像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
}
}

3)項目測試

image-20210603204005518

image-20210603204350050

4.11 微服務持續集成(6)-拉取鏡像和發布應用

1)安裝 Publish Over SSH 插件

Publish Over SSH

image-20210603204714226

2)拷貝jenkins公鑰到生產服務器

ssh-copy-id 192.168.5.6

3)添加遠程服務器

image-20210603205320844

image-20210603205252730

4)添加一個port參數

image-20210603205404673

5)生成遠程調用模板代碼

image-20210603210342891

image-20210603210355227

6)修改Jenkinsfile構建腳本

//gitlab的憑證
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_bak.git"
// 構建版本的名稱
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.5.5:8080"
//Harbor的項目名稱
def harbor_project_name = "tensquare"
//Harbor的憑證
def harbor_auth = "cd0b948d-e82b-4c0c-8a7c-8c6b8fb5454b"
node {
stage('拉取代碼') {
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
}
stage('代碼審查') {
//定義當前Jenkins的SonarQubeScanner工具
def scannerHome = tool 'sonarqube-scanner'
//引用當前Jenkins SonarQube環境
withSonarQubeEnv('sonarqube') {
sh """
cd ${project_name}
${scannerHome}/bin/sonar-scanner
"""
}
}
stage('編譯,構建鏡像') {
//定義鏡像名稱
def imageName = "${project_name}:${tag}"

//編譯,安裝公共工程
sh "mvn -f tensquare_common clean install"

//編譯,構建本地鏡像
sh "mvn -f ${project_name} clean package dockerfile:build"

//給鏡像打標簽
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登錄Harbor,並上傳鏡像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}",passwordVariable: 'password', usernameVariable: 'username')]) {

//登錄
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上傳鏡像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}

//刪除本地鏡像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"

//=====以下為遠程調用進行項目部署========
sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}

7)編寫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"

#查詢容器是否存在,存在則刪除
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私服
docker login -u admin -p Harbor12345 $harbor_url

# 下載鏡像
docker pull $imageName

# 啟動容器
docker run -di -p $port:$port $imageName

echo "容器啟動成功"
chmod +x /opt/jenkins_shell/deploy.sh

8)項目測試

image-20210603211723627

image-20210603211739600

image-20210603213226738

4.12 微服務持續集成(7)-部署前端靜態web網站

1)安裝NodeJS插件

NodeJS

 

image-20210603213812311

2)配置NodeJS環境

image-20210603214919956

image-20210603214832342

3)添加branch,project_name,port參數

image-20210605113923687

image-20210605113933578

image-20210605113940889

4)編寫dockerfile腳本

FROM nginx
COPY ./dist /usr/share/nginx/html
EXPOSE 80

5)編寫Jenkinsfile構建腳本

//gitlab的憑證
def git_auth = "14ae86e8-c3b4-4d7d-afe1-8c23d9fed317"
//gitlab的地址
def git_url = "git@192.168.5.4:root/tensquare_front.git"
// 構建版本的名稱
def tag = "latest"
//Harbor私服地址
def harbor_url = "192.168.5.5:8080"
//Harbor的項目名稱
def harbor_project_name = "tensquare"
//Harbor的憑證
def harbor_auth = "cd0b948d-e82b-4c0c-8a7c-8c6b8fb5454b"
node {
stage('拉取代碼') {
checkout([$class: 'GitSCM', branches: [[name: "*/${branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_url}"]]])
}
stage('編譯,構建鏡像') {
//定義鏡像名稱
def imageName = "${project_name}:${tag}"
//使用NodeJS 進行打包
nodejs('nodejs'){
sh'''
npm install
npm run build
'''
}
//生成鏡像
sh "docker build -t ${project_name}:${tag} ."
//給鏡像打標簽
sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
//登錄Harbor,並上傳鏡像
withCredentials([usernamePassword(credentialsId: "${harbor_auth}",passwordVariable: 'password', usernameVariable: 'username')]) {

//登錄
sh "docker login -u ${username} -p ${password} ${harbor_url}"
//上傳鏡像
sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
}

//刪除本地鏡像
sh "docker rmi -f ${imageName}"
sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"

//=====以下為遠程調用進行項目部署========
sshPublisher(publishers: [sshPublisherDesc(configName: 'master_server', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: "/opt/jenkins_shell/deploy.sh $harbor_url $harbor_project_name $project_name $tag $port", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}

6)編寫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"

#查詢容器是否存在,存在則刪除
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私服
docker login -u admin -p Harbor12345 $harbor_url

# 下載鏡像
docker pull $imageName

# 啟動容器
docker run -di -p $port:$port $imageName

echo "容器啟動成功"

7)修改代碼連接后端微服務服務

image-20210605114113877

image-20210605114059051

8)項目測試

image-20210605114146875

image-20210605120126025

image-20210605114240136

image-20210605114309932

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM