前言
在應(yīng)用還處于單體架構(gòu)的時候,交付周期通常都以周、月為單位,在這種情況下項目的部署一般都是由開發(fā)人員手動將程序代碼打成一個大的war包然后通過SSH工具拖拽到服務(wù)器上,執(zhí)行shell腳本進行部署,整個過程雖然缺乏一個完善、自動化的流程,但是基本可以滿足企業(yè)的需求,然而隨著業(yè)務(wù)的發(fā)展,用戶需求的個性化,原先的單體應(yīng)用逐步演進為微服務(wù)的架構(gòu),項目面臨著的大量構(gòu)建和部署工作,運維成本較高,我們希望通過docker等容器化技術(shù)加快項目的迭代并借助于jenkins的持續(xù)集成,可以快速把應(yīng)用打包成docker鏡像,實現(xiàn)自動部署,來降低運維的成本.
持續(xù)集成
持續(xù)集成(Continuous Integration簡稱CI)是利用一系列的工具鞠柄、方法與規(guī)則,做到快速的構(gòu)建代碼,并自動的進行測試,從而提高代碼的效率和質(zhì)量.
大致的步驟如下:
- 開發(fā)人員通過IDE工具將代碼推送到gitlab.
- jenkins從gitlab中獲取到源碼,并使用maven編譯、打包、自動構(gòu)建鏡像.
- jenkins在構(gòu)建腳本中調(diào)用docker命令將構(gòu)建好的鏡像push到本地Docker Registry.并啟動相應(yīng)的容器.
- jenkins構(gòu)建失敗或者成功,可以及時將結(jié)果推送給相關(guān)人員,比如測試人員,安排測試.
- 運維人員只需獲取相應(yīng)的鏡像就可以快速發(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服務(wù)
拉取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與域名的映射關(guān)系.
#在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登錄進去.
- Private表示私有項目,授予具體權(quán)限的用戶才能訪問.
- Internal表示內(nèi)部項目,可登陸的用戶都能克隆項目.
- Public表示公開項目,沒有任何權(quán)限的用戶都能克隆項目.
接著我們需要做的就是將本地java代碼推送至gitlab中.
在推送之前先全局設(shè)置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 啟用版本控制.
下一步本地提交代碼,右擊項目選擇Git->Commit Directory...這時本地提交成功,可以看見文件顏色從綠色變成了黑色.
最后就是將代碼push到遠程git倉庫了,右擊項目 Git->Repository ->Push
點擊ok按鈕彈出下面窗口
然后開始push...
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頁面.
在服務(wù)器上以下執(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ù)進入以下頁面:-
主目錄是存放Jenkins所有的文件的,工作空間根目錄和構(gòu)建記錄目錄默認都是在Jenkins主目錄下,這個設(shè)置一般不用進行變更.
-
執(zhí)行者數(shù)量:可以并發(fā)構(gòu)建的數(shù)量.
Restrict project naming:限制項目命名,勾選后可以看到具體設(shè)置,可以設(shè)置為默認或者使用正則表達式進行限制.
標記:用來記錄這個機器的名稱(為了分配節(jié)點使用,后面子節(jié)點會詳細介紹).
用法:設(shè)置這個節(jié)點的執(zhí)行策略(包括盡可能使用這個節(jié)點和只允許綁定到這臺機器的job.
生成前等待時間:這個時間為構(gòu)建開始前的等待時間.
scm簽出重試次數(shù):使用svn或者git拉取代碼失敗重試的次數(shù).
-
全局屬性
tool locations:設(shè)置全局工具,可以把需要的工具都在這里進行配置,比如maven,ant,jdk等.
environment variables:設(shè)置全局變量,在這里定義的全局變量可以在構(gòu)建或者發(fā)送郵件時引用.
-
設(shè)置時間格式
-
管理監(jiān)控默認選中所有
-
jenkins location
jenkins url :設(shè)置jenkins的url(發(fā)送郵件引用jenkins的地址會取這個值许昨,如果設(shè)錯了懂盐,郵件的連接就會打不開)
系統(tǒng)管理員郵件地址:管理員的郵件地址(在構(gòu)建需要發(fā)送郵件時,會用到這個郵件地址)
接著進入插件管理,選擇可選插件板塊,安裝并配置maven插件,如果缺少Maven Integration Plugin插件,在創(chuàng)建job時,不會有新建一個maven項目選項.
接下來使用jenkins創(chuàng)建一個構(gòu)建任務(wù).
從報錯提示中發(fā)現(xiàn)jenkins訪問gitlab.william.com時出現(xiàn)連接拒絕,可以斷定是由于jenkins容器與gitlab容器無法通訊導(dǎo)致的.
解決方法是在啟動jenkins容器時添加--link選項,并將其指定到需要連接的gitlab容器,重啟jenkins容器后重新填寫倉庫URL出現(xiàn)另一個錯誤:
添加構(gòu)建后操作
單擊保存回到主界面
構(gòu)建完成后,回到j(luò)enkins主界面可以看到構(gòu)建任務(wù)列表
在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目錄復(fù)制Dockerfile文件
cd $WORKSPACE/$API_NAME/target
cp classes/Dockerfile .
#構(gòu)建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
再次點擊立即構(gòu)建按鈕出現(xiàn)構(gòu)建失敗錯誤docker not found,說明jenkins容器中無法執(zhí)行docker命令,網(wǎng)上搜了一下,主要解決方案有以下幾種:
1.不使用Jenkins鏡像,直接在宿主機上安裝Jenkins服務(wù),可以調(diào)用宿主機上的docker命令.
2.使用dood方案:表示在docker容器中使用宿主機上的docker服務(wù).
3.使用dind方案:在docker鏡像中要再安裝docker服務(wù),此時在容器中的docker和宿主機的docker是兩個不同的程序,相互沒有關(guān)聯(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.重新構(gòu)建jenkins鏡像
[root@bogon jenkins-dood]# docker build -t jenkins .
4.在啟動Jenkins容器時,我們需要先創(chuàng)建一個Jenkins的配置目錄,并且掛載到docker 里的Jenkins目錄下.
[root@bogon /]# mkdir -p /opt/jenkins-dood
5.修改目錄權(quán)限.
[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時間設(shè)置:打開【系統(tǒng)管理】->【腳本命令行】運行下面的命令:
System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')
其他的配置步驟跟我們之前配置的一樣.編寫完自動部署腳本之后,我們同樣執(zhí)行立即構(gòu)建,這個時候報錯了:[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構(gòu)建,這回構(gòu)建成功了,執(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]#
返回結(jié)果為"hi",說明jenkins已經(jīng)可以正常從gitlab中獲取源碼來構(gòu)建生成docker鏡像并以docker容器的方式進行發(fā)布,供生產(chǎn)環(huán)境使用了.但目前還是以手動的方式來執(zhí)行構(gòu)建任務(wù),我們真正需要的是一款自動化的發(fā)布平臺,在開發(fā)人員將源代碼推送至gitlab后自動觸發(fā)jenkins構(gòu)建任務(wù),再次打開構(gòu)建配置,回到構(gòu)建觸發(fā)器配置:最后再來驗證下自動化發(fā)布的結(jié)果.
[root@bogon bin]# curl http://192.168.56.101:58080/hello/hi
hello world[root@bogon bin]#
返回結(jié)果為"hello world"說明jenkins已經(jīng)成功自動構(gòu)建并部署了.
參考資料:
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