1. 程式人生 > >github+jenkins+maven+docker自動化構建部署

github+jenkins+maven+docker自動化構建部署

前言

傳統的開發、測試、部署方式,是由開發人員本機或打包機進行打包,將war包提交給測試人員部署,測試通過後,再由實施人員負責部署到預發、生產環境中。中間的銜接不連貫,容易出錯,而且打包、部署存在重複的工作量。自動化構建部署(CICD)就是解決該問題,將從開發到部署的一系列流程變成自動化,銜接連貫,在構建失敗時能夠告知開發,構建成功後能夠告知測試和實施人員。無論大中小公司,都應該有此流程。

我本人在前公司搭建了基於svn(git)+jenkins+maven的自動化構建部署結構,所出的war包部署在tomcat中。此架構仍然不可避免要安裝jdk、tomcat、mysql、nginx等應用,而且需要配置環境變數,使用docker可解決上述問題,將所有服務打包成docker映象,推送到docker registry中。docker的優點就不在這裡贅述了
這裡寫圖片描述

目標

最終目標:在linux系統中,搭建jenkins服務,定時(或githook)的方式從github上拉取maven工程,構建war包。使用docker構建image,推送到docker registry上。

我使用的是ubuntu系統,使用docker形式的jenkins,拉取github工程,gitlab同理,構建war包,再在tomcat映象的基礎上將war包進去,構成新映象,推送到阿里的registry中,其他的registry(包括自建registry)同理。

為了更好的寫這個教程,我逐步完成最終目標,將目標拆分成3個部分。
- 第一步:github程式碼伺服器,提交maven專案
- 第二部:安裝jenkins,拉取github工程,構建war包
- 第三步:構建的war包自動推送到tomcat伺服器中
- 第四步:基於Dockfile將war包和tomcat映象構建出新映象推送到阿里雲

PS:讀者最好有linux使用經驗,會編寫shell指令碼。

第一步 git程式碼伺服器

這裡以github為例,其他如svn、gitlab、碼雲等VCS也都大同小異。有時間我會補充私有的gitlab搭建方式。

第二步 jenkins整合

首先你需要有一臺linux系統,我使用VMWare搭建的Ubuntu16的虛擬機器(本人低配本,覺得VM比VB更快些,虛擬機器磁碟最好使用固態,並多分些cpu和記憶體)。

有些命令沒有時,要會使用apt-get install安裝。

安裝jenkins的docker版本(ps:docker版方便快捷)
開啟終端,先把docker安裝上
sudo apt install docker.io


使用docker安裝jenkins,直接呼叫run命令,會自動pull映象並執行

sudo docker run -d \
-p 8080:8080 \
-p 50000:50000 \
--name jenkins \
-u root \
-v ~/jenkins:/var/jenkins_home \
jenkinsci/jenkins:lts

8080埠是jenkins的埠,5000埠是master和slave通訊埠(jenkins叢集部署後期我再補充,本次為單機配置)。

順便說一句,此映象為jenkins原生,存在一些外掛和配置問題,比如不能使用sudo,可根據原聲映象自行擴充套件,由於不影響此次目標,就不進行再構建了。

初次啟動的時候,可以通過docker logs -f jenkins檢視控制檯的密碼,通過這個密碼登入系統。(~/jenkins的初始化檔案也有密碼)

啟動後就可以通過127.0.0.1:8080訪問jenkins了。輸入密碼,新建使用者,安裝預設外掛。手動需要安裝的外掛有:
Maven Integration plugin:有了它在新建Job時才能有Maven專案可以選擇
Deploy to container Plugin:將war包部署到tomcatshang
Publish Over SSH:通過ssh推送檔案,並可以執行shell命令

外掛安裝完成後最好重啟一下jenkins,有機率jenkins會不生效

還需要指定jenkins的jdk和maven,進入系統管理->全域性工具配置 ,jdk在jenkins中的/usr/lib/jvm/java-8-openjdk-amd64目錄中,maven需要讓他自動下載(這種方式不是很好,可以使用docker的volumn去掛載一個maven供jenkins使用)
這裡寫圖片描述
這裡寫圖片描述
下面開始新建一個Maven專案,在主頁左側點選新建,選擇構建一個Maven專案,點選確定,主頁列表會出現該專案。
這裡寫圖片描述
進入該專案,左側樹中有配置按鈕,點選進去出現如下介面。
這裡寫圖片描述
從上到下的配置是(構建時也是按照從上到下進行執行的):
描述:就是專案詳情,根據專案情況實際情況隨意填寫
原始碼管理Repositories裡面填寫giturl,由於開源沒有使用者密碼和ssh檔案,下面的Credentials為空即可,如果是gitlab私有庫或有許可權限制則需要AddBranches to build選擇你需要構建的分支。
構建觸發器:我選擇了兩個常用的觸發構建方式,觸發遠端構建讓git使用hook的方式訪問一個jenkins的url進行觸發,本例中觸發的url為127.0.0.1:8080/job/DataPlatform/build?token=zhangchx。輪訓SCM是定時檢查程式碼是否有變化,有變化則觸發構建,值為5個*,分別表示分鐘(0-59),小時(0-23),天(1-31),月份(1-12),周(0-7),其中H表示隨機,H/5表示每5分鐘檢查一次。
這裡寫圖片描述
構建環境:無需配置
Pre Steps:構建前的操作,可以增加執行shell,配置指令碼echo "Pre Steps指令碼啟動成功",此內容會在構建控制檯中打印出來
BuildRoot POM配置pom.xml(要構建的工程必須是maven,有pom檔案),Goals and options配置clean package(也就是mvn的構建命令)
Post Steps:構建完成後的操作,可以增加執行shell,配置指令碼echo "Post Steps指令碼啟動成功${WORKSPACE}"${WORKSPACE}為jenkins的環境變數。上方的3個單選項分別代表構建成功後執行、構建成功或不穩定執行、總是執行
這裡寫圖片描述
構建設定:可以配置構建完成後Email通知,我這裡沒有配置。(很簡單,在設定-全域性設定中配置Email的發件人賬戶,這裡再配置收件人即可)
構建後操作:這一步先不配置
到此基本的配置都已經完成了,可以使用jenkins將github上的程式碼拉下來進行構建了。返回專案頁面,在左側點選立即構建或修改程式碼等待5分鐘或訪問觸發遠端構建的URL。jenkins就會開始構建了。
這裡寫圖片描述
這裡寫圖片描述
檢視控制檯,我們可以看到日誌,如果失敗需要根據日誌判斷失敗原因,是工程build失敗還是和jenkins配置有關。

第一次構建時由於maven要下載jar包,所以有些慢,實在不行就修改pom.xml,把倉庫映象改成國內地址。

第三步 推送war包到tomcat伺服器

上一步已經可以構建出war包,並在target中。這一步我們將war包推送到遠端的一臺tomcat伺服器上去(tomcat我部署在執行VM的宿主機器上)。
進入jenkins的專案配置,修改構建後操作這一項
構建後操作:由於前面安裝了Deploy to container PluginPublish Over SSH外掛,這裡就會有兩個選項
這裡寫圖片描述
這一步我們只用到Deploy to container Plugin,選擇它之後,會出現下面這個配置窗。
這裡寫圖片描述
WAR/EAR files:war包相對workspace的地址
Context path:部署到tomcat的上下文名稱,例如:127.0.0.1:8080/DataCollect可以訪問到該專案
Containers:指定部署到的tomcat版本,tomcat伺服器的地址以及使用者名稱密碼,這裡使用者需要在tomcat中有manager的許可權,你需要修改tomcat目錄下conf/tomcat-user.xml,新增類似如下的使用者。

<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="njzcx" password="njzcx" roles="manager-gui,manager-script"/>

先啟動你的tomcat,再在jenkins構建你的專案,最後war包會被推送到tomcat中去。看構建日誌和tomcat日誌如下。
這裡寫圖片描述
訪問tomcat的專案地址,可以訪問。
這裡寫圖片描述

這裡我碰到一個坑,就是WAR/EAR files一定要存在,不然每次構建都不會執行構建後操作,jenkins也不會報錯。我一直找不到原因,後來發現war包名稱讓我寫錯了
還有就是選擇的tomcat版本和你tomcat伺服器版本要對應,不然有些介面發生變化jenkins會訪問不到的。

第四步 基於Dockerfile構建映象

這一步也很簡單,首先你不考慮jenkins,只寫一個Dockerfile,能夠基於tomcat的映象+war包構建一個新的映象就可以了。jenkins的作用就是遠端呼叫一下Dockerfile的build指令碼。

Dockerfile在的github裡也已經提供了,這裡再粘一份。

#基礎映象
FROM tomcat:7.0.86

#作者
LABEL maintainer="zhangchx <[email protected]>"

#執行安裝telnet和nc
RUN apt-get install -y telnet nc; exit 0

#
VOLUME ["/home/zhangchx/tomcat"]

#TOMCAT環境變數
ENV CATALINA_BASE:   /usr/local/tomcat \
    CATALINA_HOME:   /usr/local/tomcat \
    CATALINA_TMPDIR: /usr/local/tomcat/temp \
    JRE_HOME:        /usr

#啟動入口
ENTRYPOINT ["catalina.sh","run"]

#健康檢查
# HEALTHCHECK --interval=10s --timeout=3s \
#   CMD nc -z localhost 5198 >/dev/null || exit 1

#拷貝war包到tomcat
COPY target/DataCollect.war ${CATALINA_HOME}/webapps/

Dockerfile如何編寫這個需要各位讀者自行學習,我這裡使用的是tomcat的標準映象,並通過COPY命令將target的war包拷貝到webapps中。

此Dockerfile在github中,jenkins在拉取原始碼時,該檔案也會被拉取。我們只需要讓jenkins把Dockerfile和war包傳給docker打包伺服器,再呼叫打包命令就可以生成新的docker映象,再推送到阿里的registry。

這裡我使用的docker打包機器是VM虛擬機器,也就是jenkins的宿主機

由於之前安裝了Publish Over SSH這個外掛,就可以完成上述傳輸操作。
首先需要到系統管理->系統設定配置Publish over SSH內容。我這裡使用的是使用賬戶密碼方式登入(可以使用ssh檔案登入)。配置如下:
這裡寫圖片描述
Passphrase:登入密碼
Name:伺服器名稱(自定)
Hostname:遠端伺服器地址
Username:登入使用者
Remote Directory:訪問的遠端目錄

再進入jenkins的專案配置,修改構建後操作這一項
構建後操作:使用Publish Over SSH這個外掛,對應的選項是Send build artifacts over SSH
Send build artifacts over SSH進行配置如下:
SSH server Name:需要SSH連線的Name(剛才配置好的)
Source files:要拷貝的檔案地址(相對workspace
Remove prefix:去掉Source files的字首部分
Remote directory:要拷貝到host機器的哪個目錄(這個目錄是相對Remote Directory的目錄)
Exec command:拷貝完成執行的命令

我這裡需要傳輸兩個檔案,一個是war包,另一個是Dockerfile。我的配置如下:
這裡寫圖片描述
第一個Exec command呼叫的test.sh是隨便echo點東西
第二個Exec command是呼叫一個shell指令碼,裡面docker會執行build、push等一系列命令,這裡貼出來
/home/zhangchx/docker/docker-datacollect.sh "`pwd`/docker/DataCollect" $BUILD_NUMBER

echo "當前位置:"`pwd`
echo "當前使用者:"`whoami`

# 環境變數ps:我本地的docker在snap中,如果沒有這句話下面docker命令找不到
export PATH=$PATH:/snap/bin

# 定義變數
WORKHOME=$1
BUILD_NUMBER=$2
API_NAME="datacollect"
API_VERSION="1.0"
API_PORT=8081
DOCKER_REGISTRY="registry.cn-hangzhou.aliyuncs.com/zhangchx/test"
IMAGE_NAME="$API_NAME:$BUILD_NUMBER"
CONTAINER_NAME=$API_NAME-$API_VERSION
docker --version

# 進入target 目錄複製Dockerfile 檔案
#cd $WORKSPACE/target
#cp classes/Dockerfile .
cd $WORKHOME

#構建docker 映象
docker build -t $IMAGE_NAME .

#推送docker映象
docker push $DOCKER_REGISTRY$IMAGE_NAME

#刪除同名docker容器
cid=$(docker ps -a| grep "$CONTAINER_NAME" | awk '{print $1}')
if [ "$cid" != "" ]; then
   docker rm -f $cid
fi

#啟動docker 容器
docker run -d -p $API_PORT:8080 --name $CONTAINER_NAME $IMAGE_NAME

#刪除 Dockerfile 檔案
#rm -f Dockerfile

這裡有坑,由於使用的DooD的形式(docker裡的jenkins訪問宿主機構建),登入使用者必須對docker命令有許可權,不能加sudo。同時宿主機的docker是在snap目錄下,宿主機可以正常使用docker命令(宿主機環境變數裡有配置snap),而jenkins遠端過來使用的環境變數是jenkins這臺docker虛擬機器的,所有無法訪問docker命令,必須先對PATH進行擴展才行。
非root執行docker的命令,使用者名稱jmh新增到docker組內:sudo gpasswd jmh docker,修改sock許可權:sudo chmod a+rw /var/run/docker.sock

執行jenkins的構建,可以從控制檯看到日誌
這裡寫圖片描述

進入Ubuntu裡面檢視docker映象和容器,可以看到容器在執行,也可以正常訪問。
這裡寫圖片描述
這裡寫圖片描述

結尾

至此,github+jenkins+maven+docker自動化構建已經達成。該構造可執行在中小公司完全沒問題,如果構建頻繁等原因效能跟不上,可在此結構上進行擴充套件,增加jenkins叢集和docker伺服器。