Jenkins+Docker+Gitlab+Maven搭建持續(xù)集成環(huán)境

前言

在應用還處于單體架構的時候,交付周期通常都以周、月為單位,在這種情況下項目的部署一般都是由開發(fā)人員手動將程序代碼打成一個大的war包然后通過SSH工具拖拽到服務器上,執(zhí)行shell腳本進行部署,整個過程雖然缺乏一個完善、自動化的流程,但是基本可以滿足企業(yè)的需求,然而隨著業(yè)務的發(fā)展,用戶需求的個性化,原先的單體應用逐步演進為微服務的架構,項目面臨著的大量構建和部署工作,運維成本較高,我們希望通過docker等容器化技術加快項目的迭代并借助于jenkins的持續(xù)集成,可以快速把應用打包成docker鏡像,實現(xiàn)自動部署,來降低運維的成本.

持續(xù)集成

持續(xù)集成(Continuous Integration簡稱CI)是利用一系列的工具、方法與規(guī)則,做到快速的構建代碼,并自動的進行測試,從而提高代碼的效率和質(zhì)量.


image.png

大致的步驟如下:

  • 開發(fā)人員通過IDE工具將代碼推送到gitlab.
  • jenkins從gitlab中獲取到源碼,并使用maven編譯、打包、自動構建鏡像.
  • jenkins在構建腳本中調(diào)用docker命令將構建好的鏡像push到本地Docker Registry.并啟動相應的容器.
  • jenkins構建失敗或者成功,可以及時將結果推送給相關人員,比如測試人員,安排測試.
  • 運維人員只需獲取相應的鏡像就可以快速發(fā)布到生產(chǎn)環(huán)境.

環(huán)境搭建

本地開發(fā)環(huán)境為windows環(huán)境,開發(fā)工具為IntelliJ IDEA.
1.本地下載并安裝配置git客戶端Git-2.14.1-64-bit
2.在虛擬機上搭建gitlab服務
拉取gitlab鏡像

[root@bogon /]# docker pull gitlab/gitlab-ce
Using default tag: latest
latest: Pulling from gitlab/gitlab-ce
8ee29e426c26: Pull complete 
6e83b260b73b: Pull complete 
e26b65fd1143: Pull complete 
40dca07f8222: Pull complete 
b420ae9e10b3: Pull complete 
a218309dd589: Pull complete 
5c60fd7ba0ce: Pull complete 
659c2144b5a3: Pull complete 
8289bbac0d0e: Pull complete 
31bbd150e8a7: Pull complete 
9114e78243fa: Pull complete 
Digest: sha256:3fcabe86e077db438240b214048a1561c6b89c259dbffdaa191f8f3d3119b4cb
Status: Downloaded newer image for gitlab/gitlab-ce:latest

啟動gitlab容器

[root@bogon /]# docker run --detach \
> --hostname gitlab.william.com \
> --publish 8443:443 --publish 48080:80 --publish 8022:22 \
> --name gitlab \
> --restart always \
> --volume /opt/gitlab/config:/etc/gitlab \
> --volume /opt/gitlab/logs:/var/log/gitlab \
> --volume /opt/gitlab/data:/var/opt/gitlab \
> gitlab/gitlab-ce:latest
e19375a8f2b2a76e6dae2ecd5e7b0d5864c7a2e9975bfc4274cb166cd5091b7b

注意上面的docker run命令指定了域名為gitlab.william.com,必須通過該域名才能訪問gitlab,所以在gitlab容器啟動前要先在虛擬機和本地配置ip與域名的映射關系.

 #在linux下:
 vi /etc/hosts
 #在windows下:
 cd C:\Windows\System32\drivers\etc\hosts

修改host文件在最下面添加

192.168.56.101 gitlab.william.com

另外我們指定了三個端口,22表示ssh端口,80表示http端口,443表示https端口,分別映射到宿主機上的8022、48080和8443端口,我們還通過--volume指定目錄映射,其中

  • /etc/gitlab表示gitlab的配置目錄,映射到宿主機的/opt/gitlab/config目錄.
  • /var/log/gitlab表示gitlab的日志目錄,映射到宿主機的/opt/gitlab/logs目錄.
  • /var/opt/gitlab表示gitlab的數(shù)據(jù)目錄,映射到宿主機的/opt/gitlab/data目錄.

啟動gitlab容器后打開瀏覽器輸入地址http://gitlab.william.com:48080發(fā)現(xiàn)訪問不了
先查看48080端口是否開啟

[root@bogon /]# firewall-cmd --zone=public --query-port=48080/tcp
no

很明顯需要開啟48080端口

[root@bogon /]# firewall-cmd --zone=public --add-port=48080/tcp --permanent
success
[root@bogon /]# firewall-cmd --reload
success

再次打開瀏覽器輸入地址http://gitlab.william.com:48080后重定向進入修改管理員密碼頁面,我們將密碼修改為12345678.
修改完密碼后接著進入管理登錄頁面,輸入登錄用戶名密碼root/12345678登錄進去.

image.png
接下來新建一個空的項目hello,其中hello為項目名稱,可設置可見性級別:

  • Private表示私有項目,授予具體權限的用戶才能訪問.
  • Internal表示內(nèi)部項目,可登陸的用戶都能克隆項目.
  • Public表示公開項目,沒有任何權限的用戶都能克隆項目.

項目創(chuàng)建完畢之后,開始進入主頁面:
image.png

接著我們需要做的就是將本地java代碼推送至gitlab中.
在推送之前先全局設置git

[root@bogon /]# git config --global user.name "william.zhang"
[root@bogon /]# git config --global user.email "952408421@qq.com"

3.使用IntelliJ IDEA 將項目發(fā)布(提交)到GitLab
首先需要啟用項目的版本管理功能,點擊VCS 啟用版本控制.

image.png
然后右擊項目,選擇Git->add,將項目中的文件加入到git add中等待本地提交,add 后的文件都會由橙色變成綠色.
下一步本地提交代碼,右擊項目選擇Git->Commit Directory...這時本地提交成功,可以看見文件顏色從綠色變成了黑色.
最后就是將代碼push到遠程git倉庫了,右擊項目 Git->Repository ->Push
image.png
在Define Remote窗口里面的URL中填入http://gitlab.william.com:48080/root/hello.git
點擊ok按鈕彈出下面窗口
image.png
輸入用戶名密碼:root/12345678
然后開始push...
image.png
push成功之后刷新http://gitlab.william.com:48080/root/hello可以看到本地代碼已經(jīng)推送至gitlab了.
image.png

4.安裝jenkins
拉取jenkins鏡像

[root@bogon ~]# docker pull jenkinsci/jenkins
Using default tag: latest
latest: Pulling from jenkinsci/jenkins

然后開啟38080端口,并啟動jenkins容器.

[root@bogon ~]# docker run \
> -d \
> -p 38080:8080 \
> -p 50000:50000 \
> --name jenkins \
> --link gitlab:gitlab.william.com \
> -u root \
> -v /opt/jenkins:/var/jenkins_home \
> jenkinsci/jenkins:latest
f7fa42d4e010833da5d9e5258855ac53d7d1c4855549e12992ceac236f3d583a

其中8080端口是jenkins的端口,38080是映射宿主機的端口,50000端口是master和slave通信端口.以root用戶來啟動容器,同時通過配置--link連接gitlab,因為要與gitlab容器通訊下載代碼.
打開瀏覽器http://192.168.56.101:38080/訪問跳轉(zhuǎn)到解鎖jenkins頁面.


image.png

在服務器上以下執(zhí)行命令查看密碼

[root@bogon ~]# cat /var/jenkins_home/secrets/initialAdminPassword
cat: /var/jenkins_home/secrets/initialAdminPassword: 沒有那個文件或目錄

由于之前啟動jenkins容器時我們做了目錄映射 -v /opt/jenkins:/var/jenkins_home,所以要將執(zhí)行命令改為:

[root@bogon ~]# cat /opt/jenkins/secrets/initialAdminPassword
aa42541900b146f59007de7c0cdc4d3a
[root@bogon ~]# 

在解鎖頁面上輸入上述密碼,繼續(xù)進入以下頁面:
image.png

建議選擇安裝推薦的插件,基本上一些常用的插件都會被安裝,安裝過程如圖:
image.png
安裝完后進入以下頁面:
image.png
單擊開始使用Jenkins按鈕進入jenkins系統(tǒng),點擊左側菜單中的系統(tǒng)管理進入Jenkins管理模塊,查看系統(tǒng)設置:
  • 主目錄是存放Jenkins所有的文件的,工作空間根目錄和構建記錄目錄默認都是在Jenkins主目錄下,這個設置一般不用進行變更.
    image.png
  • 執(zhí)行者數(shù)量:可以并發(fā)構建的數(shù)量.
    標記:用來記錄這個機器的名稱(為了分配節(jié)點使用,后面子節(jié)點會詳細介紹).
    用法:設置這個節(jié)點的執(zhí)行策略(包括盡可能使用這個節(jié)點和只允許綁定到這臺機器的job.
    生成前等待時間:這個時間為構建開始前的等待時間.
    scm簽出重試次數(shù):使用svn或者git拉取代碼失敗重試的次數(shù).

    Restrict project naming:限制項目命名,勾選后可以看到具體設置,可以設置為默認或者使用正則表達式進行限制.
    image.png
  • 全局屬性
    environment variables:設置全局變量,在這里定義的全局變量可以在構建或者發(fā)送郵件時引用.

    tool locations:設置全局工具,可以把需要的工具都在這里進行配置,比如maven,ant,jdk等.
    image.png
  • 設置時間格式
    image.png
  • 管理監(jiān)控默認選中所有
    image.png
  • jenkins location
    jenkins url :設置jenkins的url(發(fā)送郵件引用jenkins的地址會取這個值,如果設錯了,郵件的連接就會打不開)
    系統(tǒng)管理員郵件地址:管理員的郵件地址(在構建需要發(fā)送郵件時,會用到這個郵件地址)


    image.png

接著進入插件管理,選擇可選插件板塊,安裝并配置maven插件,如果缺少Maven Integration Plugin插件,在創(chuàng)建job時,不會有新建一個maven項目選項.


image.png
image.png

接下來使用jenkins創(chuàng)建一個構建任務.


image.png
輸入項目名稱hello,選中構建一個maven項目點擊確定按鈕進入項目配置頁面:
image.png
在源碼管理板塊中我們選擇git并在repository url填寫git倉庫名稱,但此時會報錯:
image.png

從報錯提示中發(fā)現(xiàn)jenkins訪問gitlab.william.com時出現(xiàn)連接拒絕,可以斷定是由于jenkins容器與gitlab容器無法通訊導致的.
解決方法是在啟動jenkins容器時添加--link選項,并將其指定到需要連接的gitlab容器,重啟jenkins容器后重新填寫倉庫URL出現(xiàn)另一個錯誤:


image.png
通過錯誤提示可知:我們所填入的URL是需要身份認證的,可單擊Credentials下拉框右側的Add按鈕,并選擇Jenkins選項,彈出身份認證信息對話框:
image.png
上面填寫的是gitlab的用戶名密碼驗證,添加完后需要選中它,這個時候可以看到已經(jīng)不報錯了.
image.png
緊接著我們在build板塊中配置maven:
image.png
在Goals and options使用clean package -q可以加快maven構建速度.
添加構建后操作
image.png
點擊增加構建后操作步驟,選擇歸檔成品,在文本框中輸入需要存檔的文件路徑:**/target/*.jar.

單擊保存回到主界面


image.png
單擊左側菜單的立即構建并在控制臺輸出中查看構建日志:
image.png
由日志可看出構建過程報錯了提示找不到pom文件,根據(jù)提示回到build板塊中修改maven配置Root POM為hello/pom.xml,再重新手工構建即可.
構建完成后,回到jenkins主界面可以看到構建任務列表
image.png
小球圖標表示構建狀態(tài),藍色表示構建成功,但我們的目的是搭建一個持續(xù)集成的環(huán)境,在開發(fā)階段我們會不斷的推送代碼到gitlab,所以我們需要利用jenkins來幫我們實現(xiàn)自動構建發(fā)布.
在Post step板塊中填寫shell腳本實現(xiàn)自動化發(fā)布.
#定義變量
API_NAME="hello"
API_VERSION="1.0.0"
API_PORT=58080
IMAGE_NAME="192.168.56.101:5000/hello/$API_NAME:$BUILD_NUMBER"
CONTAINER_NAME=$API_NAME-$API_VERSION

#進入target目錄復制Dockerfile文件
cd $WORKSPACE/$API_NAME/target
cp classes/Dockerfile .

#構建docker鏡像
docker build -t $IMAGE_NAME .

#推送docker鏡像
docker push $IMAGE_NAME

#刪除docker容器
cid=$(docker ps | 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

再次點擊立即構建按鈕
image.png

出現(xiàn)構建失敗錯誤docker not found,說明jenkins容器中無法執(zhí)行docker命令,網(wǎng)上搜了一下,主要解決方案有以下幾種:
1.不使用Jenkins鏡像,直接在宿主機上安裝Jenkins服務,可以調(diào)用宿主機上的docker命令.
2.使用dood方案:表示在docker容器中使用宿主機上的docker服務.
3.使用dind方案:在docker鏡像中要再安裝docker服務,此時在容器中的docker和宿主機的docker是兩個不同的程序,相互沒有關聯(lián).
4.使用https與docker后臺程序通訊,通過https暴露socket,并且可以使用宿主的鏡像,但因為打開了端口增加了攻擊面,可以說是最不安全的.
下面我們使用第2種方案即dood來解決這個問題.
1.先刪掉之前建好的jenkins容器和鏡像,然后在虛擬機上創(chuàng)建一個空的Dockerfile文件.

[root@bogon jenkins-dood]# touch Dockerfile

2.編寫Dockerfile腳本

[root@bogon jenkins-dood]# vi Dockerfile
FROM jenkins:latest
USER root
ARG dockerGid=999

RUN echo "docker:x:${dockerGid}:jenkins" >> /etc/group

USER jenkins

3.重新構建jenkins鏡像

[root@bogon jenkins-dood]# docker build -t jenkins .

4.在啟動Jenkins容器時,我們需要先創(chuàng)建一個Jenkins的配置目錄,并且掛載到docker 里的Jenkins目錄下.

[root@bogon /]# mkdir -p /opt/jenkins-dood

5.修改目錄權限.

[root@bogon /]# chown -R 1000 /opt/jenkins-dood

6.開始運行jenkins容器

[root@bogon /]# docker run \
> -d \
> -p 38080:8080 \
> -p 50000:50000 \
> --name jenkins \
> -v /var/run/docker.sock:/var/run/docker.sock \
> -v $(which docker):/bin/docker \
> -v /opt/jenkins-dood:/var/jenkins_home \
> -u root \
> --link gitlab:gitlab.william.com \
> jenkins:latest
a5904b8c7f50234b52c3772ab13cca4d61f02cb887e0524ff4f6cf53bb63b501

注意這兩個-v參數(shù)(將jenkins容器內(nèi)的docker命令指向了宿主機):
-v /var/run/docker.sock:/var/run/docker.sock
-v $(which docker):/bin/docker
之后直接在jenkins里面就可以使用docker命令了.同樣的啟動jenkins容器后找回管理員密碼:

 cat /opt/jenkins-dood/secrets/initialAdminPassword
d1291723c28848cda642d8ba8351e439

進去系統(tǒng)后先修改jenkins時間設置:打開【系統(tǒng)管理】->【腳本命令行】運行下面的命令:

System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')

其他的配置步驟跟我們之前配置的一樣.編寫完自動部署腳本之后,我們同樣執(zhí)行立即構建,這個時候報錯了:
image.png

根據(jù)錯誤日志提示可知:找不到libltdl.so.7這個文件,網(wǎng)上搜了一下,在jenkins容器啟動命令增加文件映射-v /usr/lib/x86_64-linux-gnu/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7.重新構建,這次報另一個錯誤:
image.png
原因是centos7上沒有裝libltdl.so.7這個library,我們通過下面這個命令來安裝:
[root@bogon /]# yum install libltdl.so.7

安裝完之后找到安裝的位置:/usr/lib64/libltdl.so.7,接著再重啟jenkins容器:

[root@bogon /]# docker run \
> -d \
> -p 38080:8080 \
> -p 50000:50000 \
> --name jenkins \
> -v /var/run/docker.sock:/var/run/docker.sock \
> -v $(which docker):/bin/docker \
> -v /opt/jenkins-dood:/var/jenkins_home \
> -v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7
> -u root \
> --link gitlab:gitlab.william.com \
> jenkins:latest

再次執(zhí)行jenkins構建,這回構建成功了,執(zhí)行docker images查看一下jenkins自動部署的鏡像.

[root@bogon bin]# docker images
REPOSITORY                            TAG                 IMAGE ID            CREATED             SIZE
192.168.56.101:5000/hello/hello       9                   231daf17317c        18 hours ago        673MB
192.168.56.101:5000/hello/hello       7                   c9b2c721e7e1        18 hours ago        673MB
192.168.56.101:5000/hello/hello       6                   29b676b8d273        19 hours ago        673MB
192.168.56.101:5000/hello/hello       5                   f1bdfbf7977e        20 hours ago        673MB
jenkins                               latest              cfa26ddfdfaa        24 hours ago        696MB
gitlab/gitlab-ce                      latest              d87e1ba8aa5f        7 days ago          1.46GB
192.168.56.101:5000/hello/hello-api   1.0.0               68bbcea2575f        7 days ago          673MB
nginx                                 latest              c82521676580        13 days ago         109MB
jenkins                               <none>              cd14cecfdb3a        2 weeks ago         696MB
registry                              latest              b2b03e9146e1        4 weeks ago         33.3MB
java                                  8                   d23bdf5b1b1b        18 months ago       643MB

測試jenkins自動發(fā)布的容器是否正常運行

[root@bogon bin]# curl http://192.168.56.101:58080/hello/hi
hi[root@bogon bin]# 

返回結果為"hi",說明jenkins已經(jīng)可以正常從gitlab中獲取源碼來構建生成docker鏡像并以docker容器的方式進行發(fā)布,供生產(chǎn)環(huán)境使用了.但目前還是以手動的方式來執(zhí)行構建任務,我們真正需要的是一款自動化的發(fā)布平臺,在開發(fā)人員將源代碼推送至gitlab后自動觸發(fā)jenkins構建任務,再次打開構建配置,回到構建觸發(fā)器配置:
image.png

選中Poll SCM,Poll SCM表示定時檢查源碼變更(根據(jù)SCM軟件的版本號),如果有更新就checkout最新code下來,然后執(zhí)行構建動作.如果需要每隔30分鐘檢查一次源碼變化,有變化就執(zhí)行則可以在日程表中輸入一個基于CRON表達式,比如:H/30 * * * *表示每30分鐘執(zhí)行一次構建.我們來測試一下,在idea中修改測試代碼將原來的返回值"hi"改為"hello world",然后push到gitlab中,觀察jenkins是否會自動構建.
image.png
從上圖中我們可以看到jenkins已經(jīng)開始自動構建了.
最后再來驗證下自動化發(fā)布的結果.
[root@bogon bin]# curl http://192.168.56.101:58080/hello/hi
hello world[root@bogon bin]# 

返回結果為"hello world"說明jenkins已經(jīng)成功自動構建并部署了.

參考資料:
https://blog.csdn.net/bingoxubin/article/details/78720976
https://www.cnblogs.com/leolztang/p/6934694.html
https://www.cnblogs.com/stulzq/p/8627360.html
http://www.dockone.io/article/431
https://blog.csdn.net/kikajack/article/details/79806520
https://www.cnblogs.com/caoj/p/7815820.html

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容