在 Linux 系統上安裝 Jenkins 服務,以及配置自動化構建項目
前置準備環境:docker、docker-compose、jdk、maven
一、環境搭建
1. Jenkins 安裝
(1)拉取鏡像
# 安裝鏡像包,默認安裝最新版本
docker pull jenkins/jenkins
# 查看是否安裝成功
docker images
(2)啟動并創建 Jenkins 容器
Jenkins工作空間目錄:每新建一個項目都會在該目錄下創建對應文件夾,拉取的代碼等文件均在該路徑下。
若是需要推送文件到目標服務器,默認從該項目文件夾下加載。例如:
- 工作空間目錄為:/var/jenkins_home/workspace
- 項目名稱為:demo
那么推送文件時所在路徑為:/var/jenkins_home/workspace/demo,只需在腳本中維護后續路徑即可
啟動容器
docker run -u root -d \
-p 8080:8080 -p 50000:50000 \
-v /var/jenkins_home/workspace/:/var/jenkins_home/workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
-v /usr/local/java:/usr/local/java \
-v /usr/local/maven/apache-maven-3.9.9:/usr/local/maven \
-e JAVA_OPTS="-Dorg.apache.commons.jelly.tags.fmt.timeZone='Asia/Shanghai" \
--restart=unless-stopped \
--name jenkins-server jenkins/jenkins:2.426.2-lts
啟動命令解釋
docker run -u root -d \
-p 80:8080 -p 81:50000 \ # 鏡像8080端口映射到宿主機80端口
-v /var/jenkins_home/workspace/:/var/jenkins_home/workspace \ # 掛載 jenkins 工作空間目錄
-v /var/run/docker.sock:/var/run/docker.sock \ # 掛載 docker
-v /usr/bin/docker:/usr/bin/docker \ # 掛載 docker
-v /usr/local/java:/usr/local/java \ # 掛載 jdk
-v /usr/local/maven/apache-maven-3.9.9:/usr/local/maven \ # 掛載 maven
-e JAVA_OPTS="-Dorg.apache.commons.jelly.tags.fmt.timeZone='Asia/Shanghai" \ # 同步時間
--restart=unless-stopped \ # 重啟策略
--name jenkins-server jenkins/jenkins:2.426.2-lts # jenkins-serve(自定義容器名稱) jenkins/jenkins:2.426.2-lts(鏡像名稱及版本)
安裝并創建用戶
瀏覽器打開 http://127.0.0.1:8080,輸入超級管理密碼進行登錄
# 進入容器,查看管理員密碼
docker exec -it jenkins-server bash
cat /var/jenkins_home/secrets/initialAdminPassword
- 選擇安裝推薦的插件,安裝完成后創建管理員用戶
2. Harbor 鏡像倉庫安裝
(1)下載在線安裝包
mkdir -p /root/software/harbor
cd /home/software/harbor
wget https://all-share-public.oss-cn-shanghai.aliyuncs.com/install-harbor/harbor-online-installer-v2.10.1.tgz
tar -zxvf harbor-online-installer-v2.10.1.tgz
cd harbor
(2)配置 harbor.yml 文件
cp harbor.yml.tmpl harbor.yml
編輯 harbor.yml,并在對應位置寫入以下內容
hostname: 192.168.1.1 # 設置為指定部署機器IP
......
http:
port: 8081 # 從80修改為指定端口(可選)
https: # 注釋掉 https 相關(無證書必須注釋掉)
......
harbor_admin_password: Harbor12345 # admin用戶指定密碼 (可選)
......
data_volume: /root/software/harbor/data # 數據存儲目錄(可選)
......
log:
......
local:
......
location: /root/software/harbor/logs # 日志目錄(可選)
(3)編譯安裝
./prepare
./install.sh
瀏覽器打開 http://192.168.1.1:8081(admin/Harbor12345),新建鏡像倉庫
(4)修改 docker 配置
配置 docker 鏡像源,添加 Harbor 鏡像倉庫地址,需重啟 docker 生效
vim /etc/docker/daemon.json
{
......
"insecure-registries":["192.168.1.1:8081"]
.....
}
重啟 docker
systemctl daemon-reload
systemctl restart docker
(5)設置開機自啟動
vim /usr/lib/systemd/system/harbor.service
[Unit]
Description=Harbor service with docker-compose
Requires=docker.service
After=docker.service
[Service]
Restart=always
#Type=oneshot
RemainAfterExit=yes
StandardError=null
StandardOutput=null
# Harbor實際安裝路徑
WorkingDirectory=/home/software/harbor/harbor
# Remove old containers
ExecStartPre=/usr/local/bin/docker-compose -f /home/software/harbor/harbor/dockercompose.yml down -v
# Compose up
ExecStart=/usr/local/bin/docker-compose -f /home/software/harbor/harbor/dockercompose.yml up -d
# Compose down, remove containers
ExecStop=/usr/local/bin/docker-compose -f /home/software/harbor/harbor/dockercompose.yml down -v
[Install]
WantedBy=multi-user.target
設置自啟動
systemctl daemon-reload
systemctl enable harbor
3. Sonarqube 代碼檢測工具安裝
(1)下載在線安裝包
mkdir -p /home/software/sonarqube
cd /home/software/sonarqube
wget https://all-share-public.oss-cn-shanghai.aliyuncs.com/install-sonarqube/sonarqube.tar
tar -zxvf sonarqube.tar
cd sonarqube
若是需要修改端口、掛載文件路徑,編輯當前目錄下 docker-compose.yml 文件即可
# 執行安裝程序
./install.sh
(2)創建 Token 令牌
瀏覽器打開 http://192.168.1.1:8021,賬號:admin/admin
創建 Token 令牌:生成的 Token 值要記錄下來,配置 Jenkins 流水線時需要使用
二、Jenkins配置
1. 插件安裝
需要安裝以下插件:
Publish Over SSH:用于Jenkins 發送文件到遠程服務器
Maven Integration:Maven 插件,打包項目
GitLab:Gitlab 插件,拉取代碼
DingTalk:釘釘插件,用于推送項目構建狀態等通知
系統管理 -> 插件管理,安裝完成后重啟 Jenkins
2. 配置 JDK 和 Maven
點擊:系統管理 -> 全局工具配置
3. 配置 SSH 連接
點擊:系統管理 -> 系統配置 -> 找到SSH
4. 配置全局憑據
點擊:系統管理 -> 憑據管理 -> System/全局 -> Add Credentials
根據合適的認證方式創建憑據(示例為用戶名&密碼)
5. 配置釘釘通知
此配置為構建項目時釘釘推送通知,若是不需要可忽略
(1)生成釘釘 webhook 地址和密鑰
打開釘釘 選擇要推送的群 -> 群設置 -> 機器人 -> 添加機器人 -> 自定義 -> 添加 打開如下頁面
(2)Jenkins中配置釘釘信息
三、Jenkins 構建項目
Jenkins中構建項目的類型有很多,實際上每種類型的構建都可以完成一樣的構建過程與結果,只是在操作方式、靈活度等方面有所區別,在實際開發中可以根據自己的需求和習慣來選擇。從靈活度上來說,流水線類型是最高的。常用的有以下三種:
- 自由風格軟件項目(FreeStyle Project)(推薦)
- 流水線項目(Pipeline Project)(推薦)
- Maven項目(Maven Project)
1. 新建任務(選擇流水線)
2. 配置構建參數
用于在構建項目時動態維護的參數(例如 構建的代碼分支、構建環境等)
3. 構建流水線(Pipeline)【重點】
Jenkins Pipeline Doc
tools :工具定義。可定義在腳本中使用的工具等;需在 系統管理 -> 全局配置管理 中維護,此處填寫對應的 maven 和 jdk 名稱即可
environment:變量定義。可將代碼倉庫地址,項目部署路徑等信息在該模塊下定義,方便維護
stages:Pipeline 各階段定義。是必須出現的指令,包含一個或多個 stage,Pipeline 的大部分工作在此執行。可以在此處進行項目代碼拉取、打包、推送倉庫、部署等一系列操作
post:post 是在 Pipeline 或者 stages 執行結束后的操作,不是必須出現的指令。例如發送項目構建成功、失敗等通知
以下為示例 Pipeline 腳本,可根據實際情況進行修改。
pipeline {agent anytools {// 需在 系統管理 -> 全局配置管理 中維護,此處填寫對應的 maven 和 jdk 名稱即可maven "maven3.9.9"jdk "java17"}environment {// 項目名稱 projectName = "ruoyi-cloud-plus"// projectCodeParentPath = "./ruoyi-cloud-plus" // 項目父模塊代碼路徑// projectCodeSubPath = "./ruoyi-cloud-plus/admin-server" // 項目子模塊代碼路徑(如果沒有子模塊,則刪除此變量,下面引用此變量的地方均修改為 $projectCodeParentPath) // 項目部署服務器路徑serverPath = "/home/project/ruoyi-cloud-plus" // git倉庫的url地址gitUrl = 'http://192.168.1.1/gitlab/demo/ruoyi-cloud-plus.git'// git倉庫的認證憑據ID, 可前往 系統管理-> 憑據管理 查看gitCredentialsId = "git-demo"// sonarqube 的 url 地址sonarquebUrl = "http://192.168.1.1:8021"// sonarqube 的 token 令牌 sonarquebToken = "sqa_05fxxxxxxxxxxxx227b1"// harbor 鏡像倉庫的用戶名harborUser = "admin"// harbor鏡像倉庫的用戶密碼harborPasswrod="Harbor12345"// harbor倉庫的url地址harborUrl = "192.168.1.1:8081"// harbor倉庫項目名稱harborRepo = "demo-library"// 釘釘機器人IDdingTalk = "Jenkins-DingTalk"}stages {stage('=========【拉取代碼】=========') {steps{git branch: params.branchName, credentialsId: env.gitCredentialsId, url: env.gitUrl}}stage('=========【編譯打包】=========') {steps {sh """mvn clean package -Dmaven.test.skip=true -P ${params.active}"""}}stage('=========【sonarqueb代碼質量檢測】=========') { steps {sh """ /var/jenkins_home/sonar-scanner/bin/sonar-scanner \\-Dsonar.projectKey=${env.projectName}-${params.branchName} \\ -Dsonar.projectName=${env.projectName}-${params.branchName} \\ -Dsonar.sourceEncoding=UTF-8 \\-Dsonar.sources=${env.projectCodeParentPath} \\-Dsonar.java.binaries=${env.projectCodeSubPath}/target/ \\-Dsonar.host.url=${env.sonarquebUrl} \\-Dsonar.login=${env.sonarquebToken}"""}}stage('=========【構建鏡像到Harbor倉庫】=========') {steps {sh """echo "-------- 1. 構建鏡像 ------------"docker build -t ruoyi-nacos:${params.imageTag} -f ruoyi-nacos/Dockerfile .docker build -t ruoyi-auth:${params.imageTag} -f ruoyi-auth/Dockerfile .docker build -t ruoyi-gateway:${params.imageTag} -f ruoyi-gateway/Dockerfile .docker build -t ruoyi-system:${params.imageTag} -f ruoyi-modules/ruoyi-system/Dockerfile .echo "-------- 2. 鏡像打標簽 ------------"docker login -u ${harborUser} -p ${harborPasswrod} ${harborUrl}docker tag ruoyi-nacos:${params.imageTag} ${harborUrl}/${harborRepo}/ruoyi-nacos:${params.imageTag}docker tag ruoyi-auth:${params.imageTag} ${harborUrl}/${harborRepo}/ruoyi-auth:${params.imageTag}docker tag ruoyi-gateway:${params.imageTag} ${harborUrl}/${harborRepo}/ruoyi-gateway:${params.imageTag}docker tag ruoyi-system:${params.imageTag} ${harborUrl}/${harborRepo}/ruoyi-system:${params.imageTag}echo "-------- 3. 推送鏡像至Harbor ------------"docker push ${harborUrl}/${harborRepo}/ruoyi-nacos:${params.imageTag}docker push ${harborUrl}/${harborRepo}/ruoyi-auth:${params.imageTag}docker push ${harborUrl}/${harborRepo}/ruoyi-gateway:${params.imageTag}docker push ${harborUrl}/${harborRepo}/ruoyi-system:${params.imageTag}echo "-------- 4. 刪除未被任何容器使用的鏡像 ------------"// docker image prune -f"""}}stage('=========【拉取鏡像并運行】=========') { steps { sshPublisher(publishers: [sshPublisherDesc(configName: 'service-160', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: """#!/bin/bashcd ${env.serverPath} ./deploy.sh ${env.harborUrl} ${env.harborUser} ${env.harborPasswrod} ${env.harborRepo} ${params.imageTag}""", execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: """${env.servePath}""", remoteDirectorySDF: false, removePrefix: 'docker', sourceFiles: 'docker/docker-compose.yml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])}}}// 若是不需要配置釘釘推送,則不需要下面的配置 post { success { dingtalk ( robot: '${dingTalk}', type:'MARKDOWN',title: "${projectName}項目構建成功", text: [ "### ${projectName}項目構建成功", "---","- 環境: ${params.active}", "- 分支: ${params.branchName}", "- 持續時間: ${currentBuild.durationString}", "- 執行人:${currentBuild.buildCauses.shortDescription}" ]) }failure { dingtalk ( robot: '${dingTalk}', type:'MARKDOWN', title: "${projectName}項目構建失敗", text: [ "### ${projectName}項目構建失敗", "---","- 環境: ${params.active}", "- 分支: ${params.branchName}", "- 持續時間: ${currentBuild.durationString}", "- 執行人:${currentBuild.buildCauses.shortDescription}" ]) } unstable { dingtalk ( robot: '${dingTalk}', type:'MARKDOWN', title: "${projectName}項目構建異常", text: [ "### ${projectName}項目構建異常", "---", "- 環境: ${params.active}", "- 分支: ${params.branchName}", "- 持續時間: ${currentBuild.durationString}", "- 執行人:${currentBuild.buildCauses.shortDescription}" ]) } }
}
4. 部署項目服務器上預置腳本
該步驟可忽略,需同時修改流水線腳本中【拉取鏡像并運行】stage 對該腳本的引用
在需要部署應用的服務器中,然后在 environment 中 serverPath 路徑下編寫 deploy.sh(記得賦予執行權限)
下面是提供的 deploy.sh 示例模版(需根據自身項目修改)
#!/bin/bash
# 接收啟動時的傳參
harborUrl=$1
harborUser=$2
harborPasswrod=$3
harborRepo=$4
imageTag=$5# 拼接完整鏡像地址變量,在docker-compose文件中可引用
nacos_image=$(echo "nacos_image=\"$harborUrl/$harborRepo/ruoyi-nacos:$imageTag\"")
auth_image=$(echo "auth_image=\"$harborUrl/$harborRepo/ruoyi-auth:$imageTag\"")
gateway_image=$(echo "gateway_image=\"$harborUrl/$harborRepo/ruoyi-gateway:$imageTag\"")
system_image=$(echo "system_image=\"$harborUrl/$harborRepo/ruoyi-system:$imageTag\"")# 新建 docker-compose 環境變量文件, 并寫入鏡像地址
envFile=".env"
rm -f "$envFile"echo "$nacos_image" >> "$envFile"
echo "$auth_image" >> "$envFile"
echo "$gateway_image" >> "$envFile"
echo "$system_image" >> "$envFile"# 登錄 Harbor 倉庫
docker login -u ${harborUser} -p ${harborPasswrod} ${harborUrl}# 停止并刪除服務
docker-compose down# 啟動 nginx
docker-compose up -d nginx-web# 啟動 nacos
docker-compose up -d nacos# 啟動 ruoyi-gateway ruoyi-auth ruoyi-system
docker-compose up -d ruoyi-gateway ruoyi-auth ruoyi-system# 刪除未被任何容器使用的鏡像
docker image prune -f
至此配置完成,進行構建驗證
四、Jenkins Pipeline語法
1. stages
Pipeline 階段定義,是必須出現的指令,每個 Pipeline 包含一個或多個 stage,Pipeline 的大部分工作在此執行。可以在此處進行 項目代碼拉取、打包、推送倉庫、部署等一系列操作。其中 steps 塊中可以包含script 塊。
pipeline {agent anystages {stage('第一階段') {steps {echo '第一階段 拉取代碼'}}stage('第二階段') {steps {echo '第二階段 項目打包'}}}
}
2. post
post是在Pipeline或者 stage執行結束后的操作,不是必須出現的指令,可設置以下觸發條件:
- always:無論 Pipeline 或者 stage 運行完成的狀態如何都會運行
- changed:只有當前 Pipeline 或者 stage 運行的狀態與先前運行狀態不同時才能運行
- fixed:只有當前一次構建失敗或者不穩定,而當前 Pipeline 或者 stage 運行成功時運行
- regression:前一次運行成功,而當前 Pipeline 或者 stage 運行狀態為 failure, unstable 或者 aborted 時運行
- aborted:只有當前 Pipeline 或者 stage 處于 “aborted” 狀態時才能運行,通常是手動終止。
- failure:當前 Pipeline 或者 stage 處于 “failed” 狀態時才運行
- success:當前 Pipeline 或者 stage 具有 “success” 狀態時才運行
- unstable:當前 Pipeline 或者 stage 具有 “unstable” 狀態才運行
- unsuccessful:當前 Pipeline 或者 stage 不是 “success” 狀態時運行
- cleanup:不管 Pipeline 或 stage 的狀態如何,在每一個 post 條件被執行之后運行。
pipeline {agent anystages {stages {stage('第一階段') {steps {echo '第一階段 拉取代碼'}}}post {success {echo '代碼拉取成功!'}failure {echo '代碼拉取失敗!'}always {echo 'goodbye'}}
}
3. 流水線語法生成
在配置流水線頁面,點擊流水線語法可打開語法生成器頁面
(1)在此處可選擇需要生成語法的類型
- 拉取代碼 :git:Git
- 推送文件到遠程服務器:sshPublisher:Send build artifacts over SSH
(2)填寫對應的參數信息,此處以文件推送示例
推送文件路徑配置可結合文章開頭Jenkins工作空間目錄
描述進行配置,其中docker/docker-compose.yml
就位于/var/jenkins_home/workspace/demo
路徑下,此處只需配置docker/docker-compose.yml
即可
填寫完成后,點擊下方的 “生成流水線腳本” 進行生成,最后復制生成的腳本到 steps 中即可