在企業級的架構中,CI/CD是必不可少的一個環節,它可以讓開發人員只關注于開發,而不必去關注項目的構建和部署,從而提高開發人員的效率。
本文我們來介紹一下使用jenkins 的pipeline來進行java項目的自動構建以及部署。我們通過腳本來生成docker鏡像,并推送到鏡像倉庫,供k8s使用。
整體思路是先通過maven構建項目,然后通過build_docker.sh腳本來打包生成鏡像,該腳本接收3個參數,-j 需要執行的jar包的名字,-F 項目文件名 -p ,鏡像需要推送的環境
根據參數會打包成相應的鏡像,并且推送到鏡像倉庫。
一?基礎鏡像環境
1 因為是基于springboot的java項目啟動項目需要java環境,我們構建一個自己的jdk環境,使用jdk8。
Dockerfile 如下
FROM ubuntu
WORKDIR /usr/local/jdk1.8.0_301
ADD jdk-8u301-linux-x64.tar.gz /usr/local
ENV JAVA_HOME=/usr/local/jdk1.8.0_301
ENV PATH=$JAVA_HOME/bin:$PATH
CMD ["java","-version"]
構建自己的jdk8鏡像
docker build -f Dockerfile -t jdk8img .
2 Jenkins我們也通過docker的方式來運行,基于官方jenkins鏡像我們加進去自己的jdk版本(因為目前項目大部分使用jdk8,而最新jenkins官方鏡像為jdk11),以及使用宿主機的maven,docker環境,來制作一個jenkins鏡像。
這里基于官方鏡像,這里安裝libltdl7是為了運行宿主機docker環境需要。
FROM jenkins/jenkins
ADD jdk-8u301-linux-x64.tar.gz /usr/local
ENV JAVA_HOME=/usr/local/jdk1.8.0_301
ENV PATH=/usr/local/maven/bin:$JAVA_HOME/bin:$PATH
USER root
RUN apt-get update && apt-get install -y libltdl7
? ??
這里的前提是宿主機提前安裝好maven和docker環境,具體安裝方式這里就不詳細講述了。
啟動jenkins
這里啟動命令掛載了宿主機的docker,以及maven目錄
docker run --name jenkins -d -v /etc/localtime:/etc/localtime:ro -v /data1/services/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker -v /usr/local/maven:/usr/local/maven -p 8080:8080 -p 50000:50000 --dns=8.8.8.8 jenkins
二 腳本編寫
前面我們制作好了各個基礎鏡像,現在需要編寫腳本來將鏡像編譯打包以及鏡像生成,并推送到鏡像倉庫
我們有4個腳本要編寫
1 jenkins pipeline的配置文件Jenkinsfile,這個是jenkins多分支流水線作業必須的配置文件
2 Dockerfile:構建應用鏡像的描述文件
3 build_docker.sh:打包鏡像的腳本,我們的項目通過maven打包以后,需要按一定規范存放文件,并且執行啟動應用的腳本
4 start.sh項目啟動的腳本,用于在鏡像啟動時執行
Jenkinsfile
pipeline {agent anystages {stage('package') {steps {sh 'mvn -Dmaven.test.skip=true -Dmaven.source.skip=true -am clean package -U'}}stage('Test') {steps {sh './build_docker.sh -j smart4-api-1.0-SNAPSHOT.jar -F smart4-api'sh './build_docker.sh -j smart4-web-1.0-SNAPSHOT.jar -F smart4-web'}}}
}
? ?Dockerfile
FROM jdk8img
ARG jarfile
RUN rm -f /etc/localtime && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \&& echo "Asia/Shanghai" > /etc/timezoneWORKDIR /data/app/smart4ENV DWPROJECTNO=smart4
ENV EXECJAR=$jarfileADD workspace /data/app/smart4EXPOSE 8081CMD ["sh","-c","shell/start.sh $EXECJAR"]
? ??build_docker.sh
#!/bin/bash
DOCKER_REGISTRY="harbor.udblogin.87yy.com:4443"
NAMESPACE="yygame"
BASEDIR=$(pwd)
PRONAME=`basename $BASEDIR`
DIRNAME=`dirname $BASEDIR`
folder=`basename $DIRNAME`
dockerfile="Dockerfile"
product="test"
jarfile=""while getopts "f:F:p:j:" option
docase "$option" inf)dockerfile="$OPTARG";;F)folder="$OPTARG";;p)product="$OPTARG";;j)jarfile="$OPTARG";;\?)usageexit 1;;esac
doneecho "begin copy workspace"
rm -rf $BASEDIR/workspace
mkdir -p $BASEDIR/workspace/web
mkdir -p $BASEDIR/workspace/lib
mkdir -p $BASEDIR/workspace/shell
mkdir -p $BASEDIR/workspace/configfind . -maxdepth 4 -regex ".*/target/[^\/]*.war" -exec cp -f {} $BASEDIR/workspace/web/ \;
find . -maxdepth 4 -regex ".*/target/[^\/]*.jar" -exec cp -f {} $BASEDIR/workspace/lib/ \;
cp -Rf config/* $BASEDIR/workspace/config/
cp ./start.sh $BASEDIR/workspace/shellecho "workspace is ready"echo "begin build docker"timestamp=$(date "+%Y%m%d%H%M%S")echo "build -f $dockerfile -t ${DOCKER_REGISTRY}/${NAMESPACE}/${folder}:$timestamp . --build-arg jarfile=$jarfile"docker build -f $dockerfile -t ${DOCKER_REGISTRY}/${NAMESPACE}/${folder}:$timestamp . --build-arg jarfile=$jarfileecho "docker build done"echo "start push to registry"
docker login --username=yygame harbor.udblogin.87yy.com:4443 -p xxxxxx
if [[ $product == "test" ]];thendocker push ${DOCKER_REGISTRY}/${NAMESPACE}/${folder}:$timestamp
fi
echo "folder $folder"
echo "product $product"
echo "exec jarfile $jarfile"
start.sh?
#!/bin/bash
jarfile=$1
echo "exec $jarfile"
echo "start app"
echo "java -Xss1m -server -d64 -XX:MaxGCPauseMillis=200 -Dnetworkaddress.cache.ttl=600 -Xms256m -Xmx2048m -cp /data/app/smart4/lib/$jarfile org.springframework.boot.loader.JarLauncher"
java -Xss1m -server -d64 -XX:MaxGCPauseMillis=200 -Dnetworkaddress.cache.ttl=600 -Xms256m -Xmx2048m -cp /data/app/smart4/lib/$jarfile org.springframework.boot.loader.JarLauncher
? ?
三 jenkins新建多分支流水線
新建任務,選擇多分支流水線。主要配置git地址,憑據。配置發現分支策略,這里可以按項目代碼規范來配置,比如開發版本就過濾掉,因為每次構建都會去打包生成鏡像,如果不過濾會構建所有分支的鏡像,比較耗時,耗費資源。配置好以后,運行構建,會自動打包并推送鏡像到鏡像倉庫了。
四 構建
我們在jenkins后臺選擇smart4項目的master分支,點擊構建
然后查看構建日志
待構建完成以后,去鏡像倉庫后臺查看鏡像倉庫是否生成
我們看到已經生成了新的鏡像了。整個流程完成。??