
13-自動化CI/CD流水線代碼提交→編譯→打包→鏡像構建自動流程一、什么是CI/CD先搞懂概念再動手很多新手一上來就配流水線配了半天不知道自己在配啥。咱們先把概念捋清楚。CIContinuous Integration持續(xù)集成開發(fā)人員把代碼推送到倉庫后自動觸發(fā)編譯、單元測試、代碼質量檢查。核心目的是——盡早發(fā)現(xiàn)問題別等到上線前一天才發(fā)現(xiàn)代碼跑不起來。CDContinuous Delivery/Deployment持續(xù)交付/部署在CI的基礎上把編譯好的產物自動打包、構建鏡像、推送到倉庫甚至自動部署到測試/生產環(huán)境。一句話總結CI管編譯測試CD管打包部署。兩者串聯(lián)起來就是一條從代碼提交到上線的自動化流水線。二、為什么我們需要CI/CD在智慧農業(yè)和無人售貨柜的項目中后端有十幾個微服務Java SpringBoot設備端有嵌入式固件瑞芯微/STM32前端有安卓APP。如果沒有CI/CD程序員手動mvn package手動docker build手動docker push——十個服務能搞一下午某個同事忘了推鏡像測試環(huán)境跑的還是上周的代碼排查半天上線時手忙腳亂人為操作出錯率極高上了CI/CD之后git push 一敲剩下的事交給機器。這就是工程化的魅力。三、GitLab CI流水線實戰(zhàn)我們以GitLab CI為例GitHub Actions原理類似搭建一條完整的流水線。3.1 核心概念速覽概念說明Runner執(zhí)行流水線的機器物理機/容器需要注冊到GitLabPipeline一條完整的流水線包含多個StageStage流水線的階段如 build → test → package → deployJobStage中的具體任務同一Stage的Job并行執(zhí)行3.2 .gitlab-ci.yml 完整配置示例在項目根目錄創(chuàng)建.gitlab-ci.yml文件# 定義階段順序前一個階段全部成功才會執(zhí)行下一個stages:-build-test-package-deploy# 全局變量variables:MAVEN_OPTS:-Dmaven.repo.local.m2/repositoryIMAGE_REGISTRY:registry.cn-shenzhen.aliyuncs.comIMAGE_NAMESPACE:alspd/smart-agri# 編譯階段 build-job:stage:buildimage:maven:3.8-openjdk-8script:-echo 開始編譯 $CI_PROJECT_NAME -mvn clean compile-DskipTests-echo 編譯完成產物路徑target/artifacts:paths:-target/*.jarexpire_in:1 hourrules:-if:$CI_COMMIT_BRANCH develop||$CI_COMMIT_BRANCH main# 單元測試階段 test-job:stage:testimage:maven:3.8-openjdk-8script:-echo 執(zhí)行單元測試 -mvn test-echo 測試通過率統(tǒng)計-cat target/site/jacoco/index.html|grep-oP Total.*?([0-9]%)|tail-1rules:-if:$CI_COMMIT_BRANCH develop# Docker鏡像構建與推送 package-job:stage:packageimage:docker:20.10services:-docker:20.10-dindscript:-echo 構建Docker鏡像 # 登錄鏡像倉庫-docker login-u $CI_REGISTRY_USER-p $CI_REGISTRY_PASSWORD $IMAGE_REGISTRY# 構建鏡像標簽包含分支名commit短hash時間戳-IMAGE_TAG$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-$(date %Y%m%d%H%M)-docker build-t $IMAGE_REGISTRY/$IMAGE_NAMESPACE/$CI_PROJECT_NAME:$IMAGE_TAG .-docker push $IMAGE_REGISTRY/$IMAGE_NAMESPACE/$CI_PROJECT_NAME:$IMAGE_TAG-echo 鏡像推送成功$IMAGE_REGISTRY/$IMAGE_NAMESPACE/$CI_PROJECT_NAME:$IMAGE_TAG# 把鏡像tag寫入文件供下游階段使用-echo $IMAGE_TAGimage-tag.txtartifacts:paths:-image-tag.txtexpire_in:1 dayrules:-if:$CI_COMMIT_BRANCH develop||$CI_COMMIT_BRANCH main# 部署到測試環(huán)境 deploy-test-job:stage:deployimage:alpine:latestbefore_script:-apk add--no-cache openssh-clientscript:-echo 部署到測試環(huán)境 -IMAGE_TAG$(cat image-tag.txt)# 通過SSH遠程執(zhí)行部署腳本-ssh-o StrictHostKeyCheckingno deploy192.168.1.100 docker pull $IMAGE_REGISTRY/$IMAGE_NAMESPACE/$CI_PROJECT_NAME:$IMAGE_TAGdocker stop $CI_PROJECT_NAME||truedocker rm $CI_PROJECT_NAME||truedocker run-d--name $CI_PROJECT_NAME--network agri-net-p 8080:8080-e SPRING_PROFILES_ACTIVEtest $IMAGE_REGISTRY/$IMAGE_NAMESPACE/$CI_PROJECT_NAME:$IMAGE_TAG-echo 部署完成rules:-if:$CI_COMMIT_BRANCH develop3.3 關鍵配置解讀1artifacts產物傳遞build-job編譯出來的 jar 包通過artifacts傳遞給下游Job。如果不配每個Job都是獨立容器編譯產物拿不到。2rules條件觸發(fā)rules:-if:$CI_COMMIT_BRANCH develop只有推送到develop分支才觸發(fā)完整流水線。推到feature/xxx分支只編譯不部署避免每個功能分支都污染測試環(huán)境。3鏡像標簽策略IMAGE_TAG$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-$(date%Y%m%d%H%M)# 示例develop-a3f5c2e1-202608071430分支名 commit短hash 時間戳既能追溯代碼版本又能區(qū)分構建時間。這個標簽規(guī)范在下一篇會詳細展開。四、Dockerfile 配套寫法流水線里調了docker build對應的 Dockerfile 也得跟上# 多階段構建減小最終鏡像體積 FROM maven:3.8-openjdk-8 AS builder WORKDIR /build COPY pom.xml . RUN mvn dependency:go-offline # 先下依賴利用Docker緩存層 COPY src/ ./src/ RUN mvn clean package -DskipTests FROM openjdk:8-jre-slim WORKDIR /app COPY --frombuilder /build/target/*.jar app.jar # 健康檢查K8s就緒探針會用到 HEALTHCHECK --interval30s --timeout3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1 EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]多階段構建的好處最終鏡像只包含JRE和jar包不含Maven和源碼體積從800MB降到180MB左右。在工控設備上部署時小鏡像就是快速度。五、GitHub Actions 簡版對照如果你用的是GitHub Actions邏輯完全一樣換套語法name:CI/CD Pipelineon:push:branches:[develop,main]jobs:build:runs-on:ubuntu-lateststeps:-uses:actions/checkoutv3-uses:actions/setup-javav3with:java-version:8distribution:temurin-name:Maven Buildrun:mvn clean package-DskipTests-name:Build Push Docker Imagerun:|docker login -u ${{ secrets.REGISTRY_USER }} -p ${{ secrets.REGISTRY_PASS }} registry.cn-shenzhen.aliyuncs.com docker build -t registry.cn-shenzhen.aliyuncs.com/alspd/smart-agri/${{ github.event.repository.name }}:${{ github.sha }} . docker push registry.cn-shenzhen.aliyuncs.com/alspd/smart-agri/${{ github.event.repository.name }}:${{ github.sha }}六、流水線提速技巧實際項目中流水線跑10分鐘以上很常見這里列幾個優(yōu)化點Maven依賴緩存把.m2/repository緩存到Runner第二次構建省去下載依賴的時間Docker層緩存Dockerfile中先COPY pom.xml再RUN mvn dependency:go-offline依賴不變時這層直接命中緩存并行Job把單元測試和代碼質量掃描SonarQube放到同一個Stage并行執(zhí)行按需觸發(fā)只有src/目錄變更時才觸發(fā)編譯文檔改動不浪費CI資源# 只在源碼變更時觸發(fā)編譯rules:-if:$CI_COMMIT_BRANCH developchanges:-src/**-pom.xml七、小結CI/CD的本質是把人的重復勞動交給機器。代碼提交后自動編譯、測試、打包、構建鏡像、推送倉庫、部署——一氣呵成。配置好之后開發(fā)人員只需要關心寫代碼部署的事全自動。下一篇我們會深入Docker鏡像版本管理講清楚標簽規(guī)范、版本留存策略和鏡像清理——別讓鏡像倉庫變成垃圾場。