02_使用Docker在服務器上部署jenkins實現項目的自動化部署
一、使用docker拉取阿里云容器私有鏡像倉庫內的jenkins鏡像
- 登錄阿里云Docker Registry
$ sudo docker login --username=wxxxo@1xxx registry.cn-shanghai.aliyuncs.com
用于登錄的用戶名為阿里云賬號全名,密碼為開通服務時設置的密碼。
您可以在訪問憑證頁面修改憑證密碼。
- 從Registry中拉取鏡像
$ sudo docker pull registry.cn-shanghai.aliyuncs.com/xxx/jenkins:[鏡像版本號]
二、創建jenkins容器并運行
$ sudo docker run -d -u root -p 8080:8080 -p 50000:50000 -v /home/docker/jenkins_home:/var/jenkins_home --name jenkins registry.cn-shanghai.aliyuncs.com/xxx/jenkins:2.491-jdk17
每個參數的含義:
-
docker run: 運行 Docker 容器的命令。
-
-d: 在后臺運行容器,即“detached”模式。
-
-u root: 以 root 用戶身份運行容器。這通常用于確保容器內的進程具有足夠的權限執行需要的操作。
-
-p 8080:8080: 將容器內部的 8080 端口映射到宿主機的 8080 端口(宿主機端口:容器內部端口)。Jenkins 服務通常在 8080 端口上運行。
-
-p 50000:50000: 將容器內部的 50000 端口映射到宿主機的 50000 端口(宿主機端口:容器內部端口)。這是 Jenkins 使用的用于構建和執行任務的端口。
-
-v /home/docker/jenkins_home:/var/jenkins_home: 將宿主機上的目錄(/home/docker/jenkins_home)掛載到容器內的 /var/jenkins_home 目錄(宿主機目錄:容器內部目錄)。這樣可以確保 Jenkins 數據和配置持久化,即使容器被刪除,數據仍然保存在宿主機上。
注意:/home/docker/jenkins_home 為自己在Linux系統里創建的用來持久化jenkins數據的目錄,而/var/jenkins_home是docker容器內的默認路徑,即jenkins_home的路徑在docker容器內的/var下。
-
–name jenkins: 為容器指定一個名稱,即 “jenkins”。
-
registry.cn-shanghai.aliyuncs.com/xxx/jenkins:2.491-jdk17: 指定要運行的 Docker 鏡像的名稱和版本(鏡像名稱:版本號)。
三、登錄jenkins
通過訪問[服務器IP]:[jenkins端口]訪問jenkins服務,剛使用jenkins服務時,需要使用jenkins提供的默認密碼進行驗證。
jenkins提供的默認密碼路徑(在docker容器內)為:
/var/jenkins_home/secrets/initialAdminPassword
(如果將宿主機的某個目錄路徑掛載到 /var/jenkins_home 路徑):如將宿主機上的目錄(/home/docker/jenkins_home)掛載到容器內的 /var/jenkins_home 目錄,那么默認密碼路徑為
/home/docker/jenkins_home/secrets/initialAdminPassword
安裝插件,當然也可以跳過,不過一般推薦按照jenkins的推薦的插件。安裝完畢后,可以創建jenkins用戶。
四、編寫dockerfile、K8S/deployment.yaml、jenkinsfile文件
dockerfile文件:docker打包鏡像時,可以讀取該文件中的內容,依據文件中的命令進行打包。
dockerfile示例:
# FROM 指定使用哪個鏡像作為基準
FROM docker.m.daocloud.io/openjdk:8u191-jdk-alpine# 創建目錄, 并設置該目錄為工作目錄
RUN mkdir -p /aaa
WORKDIR /aaa# 復制文件到鏡像中
COPY target/aaa-1.0.jar aaa.jar# 設置時區
ENV TZ=Asia/Shanghai# 設置 JAVA_OPTS 環境變量,可通過 docker run -e "JAVA_OPTS=" 進行覆蓋
ENV JAVA_OPTS="-Xms300m -Xmx300m -Djava.security.egd=file:/dev/./urandom"# 應用參數,可通過 docker run -e "ARGS=" 來設置,如 -e "ARGS=--spring.profiles.active=prod"
ENV ARGS=""# 暴露 8080 端口
EXPOSE 8080# 啟動后端服務
CMD java ${JAVA_OPTS} -jar aaa.jar $ARGS
K8S/deployment.yaml文件:K8S創建應用時,可以通過該文件中的內容進行創建。
K8S/deployment.yaml文件:
apiVersion: v1 // apiVersion: v1:指定 Kubernetes API 版本,v1 適用于 Service 資源
kind: Service // 定義該資源的類型是一個 Service
metadata:name: // 定義 Service 的名稱
spec: // 定義 Service 的詳細配置type: NodePort //指定 Service 類型為 NodePort,即允許外部通過 NodeIP:nodePort 訪問服務。selector:app: aaa // 表示該 Service 只會選擇 app: aaa 這個標簽的 Pod 作為后端服務。ports: // 定義 Service 的端口映射- protocol: TCP // 指定使用 TCP 作為通信協議port: 8080 // 這是 Service 內部的端口,其他 Pod 訪問該 Service 時使用這個端口。 port 會轉發流量到 targetPort,通常它們可以相同,但不強制相同nodePort: 31500 // Kubernetes 在每個節點上分配的端口號,用于外部訪問targetPort: 8080 // 這是 Pod 內部運行的容器監聽的端口,對應 Dockerfile 里 EXPOSE 的端口和后文的里的 containerPortname: http // 端口名稱(可不寫)---
apiVersion: apps/v1 // 指定 Kubernetes API 版本,apps/v1 適用于 Deployment 資源
kind: Deployment // 定義該資源的類型是一個 Deployment,用于管理 Pod 的創建和更新
metadata:name: aaa // Deployment 的名稱annotations:kubernetes.io/change-cause: registry-vpc.cn-shanghai.aliyuncs.com/aaa/aaa:{{GIT_COMMIT}} // 用于記錄該 Deployment 變更的原因,常用于回滾和版本管理,其中 {{GIT_COMMIT}} 是 Git 提交的版本號,通常在 CI/CD 過程中會被替換為實際值,例如Jenkinsfile文件中有一條命令便是查找{{GIT_COMMIT}}并將其替換為實際的版本號
spec: // 定義 Deployment 的詳細配置replicas: 1 // 指定副本數,即 Pod 的數量為 1selector:matchLabels:app: aaa // 表示該 Deployment 只會管理 app: aaa 這個標簽的 Podtemplate: // 定義 Pod 模板,所有由該 Deployment 創建的 Pod 都會遵循此模板metadata:labels:app: aaa // 給 Pod 打上 app: aaa 的標簽,便于 Service 發現該 Podspec: // 定義 Pod 的詳細配置 containers:- name: aaa // 容器名稱image: registry-vpc.cn-shanghai.aliyuncs.com/aaa/aaa:{{GIT_COMMIT}} // 指定容器的鏡像地址,{{GIT_COMMIT}} 代表 Git 版本號,CI/CD 過程中會被替換為實際值ports: - containerPort: 8080 // 定義容器內部監聽的端口,應和dockerfile里explode暴露的端口保持一致//下面注射的為健康檢查配置# livenessProbe: // (存活探針):檢查容器是否存活,若失敗 Kubernetes 會重啟該容器# httpGet:# path: /user/health_check // 通過 HTTP GET 請求 /user/health_check 端點檢查健康狀態# port: 8080# initialDelaySeconds: 30# readinessProbe: // (就緒探針):檢查容器是否準備好接收流量,未通過時 Kubernetes 不會將其加入負載均衡# httpGet:# path: /user/health_check // 通過 HTTP GET 請求 /user/health_check 端點檢查健康狀態# port: 8080# initialDelaySeconds: 30 // 表示容器啟動后等待 30 秒再執行檢查env: // 定義環境變量- name: PROFILE // 環境變量名value: dev // 環境變量值,表示該容器運行在 dev(開發)環境volumeMounts:- name: timezone // 引用 volumes 定義的 timezonemountPath: /etc/localtime // 將宿主機的 /usr/share/zoneinfo/Asia/Shanghai 文件掛載到容器的 /etc/localtime,確保容器使用上海時區imagePullSecrets:- name: aliyun-registry // 指定 Kubernetes 拉取私有鏡像所需的憑據,通常用于登錄阿里云鏡像倉庫volumes: - name: timezone 定義一個名為 timezone 的存儲卷hostPath:path: /usr/share/zoneinfo/Asia/Shanghai // 宿主機路徑,提供時區文件
Jenkinsfile文件:Jenkins全流程部署時,根據該文件中的內容,進行全流程部署。
Jenkinsfile文件:
pipeline { // 定義一個工作流environment { //定義環境變量//定義Docker鏡像倉庫地址registry = "registry-vpc.cn-shanghai.aliyuncs.com/xxxx/aaa"registryCredential = "dockerhub"parentWorkspace = "$WORKSPACE" FAILED_STAGE=""CURRENT_ENVIRONMENT=""BLUE_OR_GREEN=""}agent any // 定義在哪個 agent 上運行,這里使用任意可用節點stages { // 定義流水線中各個階段(stages)stage("Deply Parent") { // 項目構建階段agent {docker { //指定使用 Docker 代理運行image 'registry.cn-hangzhou.aliyuncs.com/acs/maven:3-jdk-8'args '-v $HOME/.m2/repository:/root/.m2/repository -u root'}}steps { // 定義該階段的步驟(steps),并使用 script 塊以腳本形式執行命令script {FAILED_STAGE=env.STAGE_NAME //將當前階段名稱(env.STAGE_NAME)賦值給變量 FAILED_STAGE,以便在出錯時記錄是哪一階段失敗了。sh "mvn -Dmaven.repo.local=/var/jenkins_home/jenkins_m2_repo -U install -Dmaven.test.skip=true" // 執行一個 shell 命令,通過 Maven 進行項目構建:-Dmaven.repo.local=/var/jenkins_home/jenkins_m2_repo 指定 Maven 本地倉庫路徑,-U 表示強制更新 SNAPSHOT 依賴,install 命令用于構建并安裝項目,-Dmaven.test.skip=true 則跳過測試執行。// 拷貝到容器外sh "cp target/aaa-1.0.jar " + parentWorkspace +"/aaa-1.0.jar" // 執行一個 shell 命令,將 target 目錄下生成的 aaa-1.0.jar 文件復制到外部的工作空間路徑(由變量 parentWorkspace 指定)。}}}stage("Building image") { //構建鏡像階段steps {script {FAILED_STAGE=env.STAGE_NAME // 將當前階段名稱賦值給 FAILED_STAGE,docker.build(registry) // 調用 docker.build(registry) 方法,根據之前定義的 registry 變量構建 Docker 鏡像。}}}stage("Deploy Image") { // 部署鏡像階段steps {script {FAILED_STAGE=env.STAGE_NAME // 將當前階段名稱賦值給 FAILED_STAGEdocker.withRegistry('https://registry-vpc.cn-shanghai.aliyuncs.com', registryCredential) { // 使用 docker.withRegistry 方法指定鏡像倉庫地址 https://registry-vpc.cn-shanghai.aliyuncs.com 和憑據 registryCredential,docker.image(registry).push("$GIT_COMMIT") //將構建的鏡像以當前 Git 提交號($GIT_COMMIT)作為標簽推送到倉庫。}}}}stage("Update k8s cluster") { // 更新 Kubernetes 集群階段options {timeout(time: 5, unit: 'MINUTES') // 本階段超時時間限定為 5 分鐘}steps {script {FAILED_STAGE = env.STAGE_NAME // 當前階段名稱賦值給 FAILED_STAGEif (env.GIT_BRANCH == "origin/master") { // 判斷當前的 Git 分支是否為 "origin/master"sh "cat k8s/deployment.yml | sed 's/{{GIT_COMMIT}}/$GIT_COMMIT/g' | kubectl apply -n default -f -" // 使用 sed 命令將 k8s/deployment.yml 文件中的占位符 {{GIT_COMMIT}} 替換為實際的 Git 提交號,并通過管道傳遞給 kubectl apply 命令,應用于 default 命名空間sh "kubectl rollout status deployment/aaa -n default" // 使用 kubectl rollout status 命令檢查部署狀態,確保部署成功}else{sh "cat k8s/deployment-test.yml | sed 's/{{GIT_COMMIT}}/$GIT_COMMIT/g' | kubectl apply -n test -f -" // 對 k8s/deployment-test.yml 文件進行替換,并將其應用于 test 命名空間sh "kubectl rollout status deployment/aaa -n default" // 檢查部署狀態}}}}}post { // 流水線的后置操作(post)aborted { // 流水線被中止(aborted)時,執行以下 script 腳本script {if (FAILED_STAGE == "Update k8s cluster") { // 如果最后出錯的階段(FAILED_STAGE)是 "Update k8s cluster",則根據當前 Git 分支進行回滾操作if (env.GIT_BRANCH == "origin/master") { // 如果在 origin/master 分支下sh "kubectl config use kubernetes" // 切換 kubectl 配置)sh "kubectl rollout undo deployment/aaa" // 回滾部署 aaa。}else{sh "kubectl config use kubernetes" 切換配置sh "kubectl rollout undo deployment/aaa-test" 回滾部署}}}}}
}
五、創建任務
創建一個任務(可以使用模板,如Freestyle project、Pipeline)。
- 如果使用的是Freestyle project
- 選擇代碼源,無論使用哪個模板,都需要處理代碼源管理(Source Code Management),項目如果在Coding、GitHub、Gitee等托管平臺上,則選擇Git。
- 填寫倉庫路徑(Repository URL),HTTP的倉庫路徑。填寫完路徑以后,一般會報錯。
- 如果沒有Credentials,則需要添加一個新的Credentials。添加時,Username 填倉庫所在平臺的郵箱,密碼填倉庫所在平臺的用戶密碼。完成以后,如果賬號密碼沒問題,則此處不會報錯。
- 有時還需要選擇分支(Branch Specifier)。
- 處理構建流程(Steps),需要手動一個一個添加(Add build step)。
- 選擇代碼源,無論使用哪個模板,都需要處理代碼源管理(Source Code Management),項目如果在Coding、GitHub、Gitee等托管平臺上,則選擇Git。
- 如果使用的是Pipeline
- 一般選擇Pipeline-Definition為Pipeline script from SCM。
- SCM (代碼源)選擇為 Git
- 填寫倉庫路徑(Repository URL),HTTP的倉庫路徑。填寫完路徑以后,一般會報錯。
- 如果沒有Credentials,則需要添加一個新的Credentials。添加時,Username 填倉庫所在平臺的郵箱,密碼填倉庫所在平臺的用戶密碼。完成以后,如果賬號密碼沒問題,則此處不會報錯。
- 有時還需要選擇分支(Branch Specifier)。
- Script Path填寫自己在項目根目錄放置的用于jenkins讀取的文件(自動化部署的命令),如jenkinsfile文件等。