構建基于Springboot+Docker+Jenkins+Github+Maven的持續(xù)集成系統(tǒng)

最近在做基于Docker+Jenkins+Github+Maven的持續(xù)集成環(huán)境,目的是自動化構建springboot項目并發(fā)布到生產環(huán)境扒接。小公司沒有自動化構建系統(tǒng)纷纫,項目發(fā)布過程是這樣的:

1、在本地寫好代碼、測試募狂,測試通過后打成war包或jar包;
2、將war包或jar包拷貝到云服務器上锌蓄;
3、重啟服務撑柔。

整個過程瘸爽,特別是第2、3步靠手工操作可能會引入錯誤(比如命令行下不小心可能會刪掉某個文件)铅忿,不利于項目的可靠性剪决。為此,想起上家公司采用了Jenkins實現(xiàn)了項目的自動化構建,不需要本地打包柑潦、上傳享言,因此干脆就做一回運維,花點時間自己搭建一個持續(xù)集成系統(tǒng)渗鬼,以實現(xiàn):
只需本地寫好代碼并完成測試览露,然后將代碼push到Github,后面的編譯譬胎、打包差牛、發(fā)布等工作交由持續(xù)集成系統(tǒng)自動完成。

恩堰乔,理想很豐滿偏化,現(xiàn)實嘛骨感。以前工作中都是使用現(xiàn)成镐侯,第一次自己搭建踩了無數(shù)的坑侦讨。好在經過一段時間的學習、實操苟翻,今天終于初步達成了目標韵卤。在此,要對Google搜索同學提出表揚崇猫。

由于比較忙怜俐,先大致說一下整個過程。

本地開發(fā)環(huán)境:
操作系統(tǒng):Ubuntu 16.04
Java開發(fā)集成環(huán)境:Intellij idea 2019.1.3(Ultimate Edition)
JDK版本:1.8.0_191
數(shù)據(jù)庫:Mongodb 4.0.10邓尤、Redis 3.0.6
Maven:3.6.1
Tomcat:8.5.41

云服務器環(huán)境:
操作系統(tǒng):阿里云ECS拍鲤,Ubuntu 16.04
JDK版本:使用鏡像openjdk8,目前版本1.8.0_212
數(shù)據(jù)庫:Mongodb 4.0.10汞扎、Redis 3.0.6
Maven:3.6.1
Tomcat:2.1.1季稳,Springboot自帶

大致步驟(后面有時間再補充):
注意:我的賬戶默認是root,因此下面的命令均不需要sudo前綴
第1步:安裝Docker(按照官網安裝即可)
(1)apt-get update
(2)apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
(3)curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
(4)add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
(5)apt-get update
(6)apt-get install docker-ce docker-ce-cli containerd.io
安裝好后澈魄,運行“docker run hello-world”看是否安裝正確景鼠。

第2步:安裝Jenkins
這里通過Jenkins鏡像來安裝。注意:Jenkins鏡像版本越高越好痹扇,否則可能會出現(xiàn)某些插件不兼容的問題铛漓。安裝過程見我的另一篇博客http://www.reibang.com/p/15c1addd1733。這篇博客中的漢化方法有些問題鲫构,重啟Jenkins后會出現(xiàn)部分中文部分英文的情況浓恶,問題還沒有找到。在此建議先不要漢化结笨,因為很多問題可以在google上搜索包晰,漢化后搜索結果的質量你懂的湿镀。

第3步:配置Jenkins和Github
這一步的目的是,當我們將本地項目push到Github后伐憾,會主動觸發(fā)Jenkins從Github上拉取該項目勉痴,然后運行配置好的腳本。具體配置過程見我的另一篇博客http://www.reibang.com/p/29d2a339a57a树肃。

第4步:配置Springboot項目
這一步主要是在項目pom.xml中引入dockerfile-maven-plugin插件蒸矛,在該插件中可以指定項目打包后的名稱、版本以及本地JAR包的位置胸嘴。另外雏掠,還需要在項目根目錄下編寫Dockerfile以及build.sh、run.sh腳本筛谚。
Dockerfile:用于構建Springboot項目的鏡像
build.sh:包含編譯Dockerfile的命令
run.sh:用于基于項目鏡像啟動Docker容器,即運行項目
注意:這三個文件在項目根目錄下停忿,與src同級驾讲,見下圖


image.png

4.1 引入dockerfile-maven-plugin插件
4.1.1 在pom.xml的plugins下插入一下配置:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>

<mainClass>com.company.testproject.TestProjectApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.10</version>
            <configuration>
                <repository>testproject</repository>
                <tag>20190628-1.0</tag>
                <buildArgs>
                    <JAR_FILE>/target/testproject-0.0.1-SNAPSHOT.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>

注意:如果你原來將項目打包為war包,那么需要將pox.xml中的<packaging>war</packaging>注釋掉(如果有的話)
4.1.2 配置Tomcat
由于在本地開發(fā)及測試時使用的是單獨安裝的Tomcat席赂,沒有使用Springboot自帶的Tomcat吮铭,因此在pom.xml中是將該自帶的Tomcat依賴去掉了的,即原配置如下:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>-->
            <exclusion>-->
                <groupId>org.springframework.boot</groupId>-->
                <artifactId>spring-boot-starter-tomcat</artifactIyincid>-->
            </exclusion>-->
        </exclusions>-->
    </dependency>

由于阿里云內存空間有限颅停,為了減少不必要的內存開銷谓晌,同時啟動/停止項目均通過容器來實現(xiàn),不需要顯式執(zhí)行Tomcat的startup.sh腳本來啟動項目癞揉,因此沒必要單獨安裝Tomcat纸肉。故將上面的依賴修改為:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

同時,因為使用內置的Tomcat喊熟,因此還要增加:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>

4.2 編寫Dockerfile
Dockerfile用于構建項目鏡像柏肪。在項目的根目錄下新建文件Dockerfile,內容如下:

FROM openjdk:8
ARG JAR_FILE
RUN apt-get update
RUN apt-get install vim -y
RUN echo "Asia/Shanghai" > /etc/timezone
RUN dpkg-reconfigure -f noninteractive tzdata
RUN mkdir /testproject
ADD ${JAR_FILE} /testproject
EXPOSE 9081
ENTRYPOINT ["java","-jar","/testproject/testproject-0.0.1-SNAPSHOT.jar"]

這里芥牌,我沒有使用宿主機中安裝的JDK烦味,而是基于基礎鏡像openjdk:8來構建項目鏡像。
這里簡要說明該Dockerfile的內容:
第1行:表示當前要構建的鏡像的基礎鏡像是openjdk:8
第2行:設置環(huán)境變量壁拉,暫未指定值谬俄,在后面指定
第3、4行:可選弃理。這兩行目的是更新并安裝vim溃论,這兩行主要是為了安裝vim,因為基礎鏡像中除了jdk之外痘昌,沒有其他軟件可用蔬芥。為了容器啟動后可用對某些配置進行編輯或查看(當然也可以用cat命令查看梆靖,但我習慣了用vim)。如果你不需要vim笔诵,可以不安裝
第5返吻、6行:設置容器中的時區(qū)為東八區(qū)(北京時間)。容器的默認時區(qū)不是東八區(qū)乎婿,因此需要進行設置测僵。需要注意的是,通過這兩行設置后的時間也早于當前時間8小時谢翎。網上有方法是在啟動容器時捍靠,加上參數(shù)-v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone,但我沒有驗證此方法森逮。
第7行:在阿里云服務器上創(chuàng)建目錄testproject榨婆,用于保存testproject-0.0.1-SNAPSHOT.jar
第8行:將環(huán)境變了JAR_FILE指向/testproject
第9行:將容器的端口9081暴露到容器外,即在宿主機可以訪問該端口(即訪問服務的端口)
第10行:指定容器啟動時執(zhí)行的程序及參數(shù)褒侧。這里表示在容器啟動后就發(fā)布項目良风,如果不想立即發(fā)布項目,可以替換為其他命令闷供,比如ENTRYPOINT ["ls", "-l", "/testproject"]

4.3 編寫build.sh
這里不多說烟央,見下面的代碼:

mvn clean
mvn package -DskipTests
docker rmi -f testproject:20190628-1.0
mvn Dockerfile:build
docker images

其中,第3行表示刪除上一個版本的鏡像(可選歪脏,如果要考慮回滾的話就不要刪除)疑俭;第四行是根據(jù)Dockerfile重新生成新鏡像。

4.4 編寫run.sh
這個腳本主要是用于啟動容器婿失,代碼如下:

docker ps -a

aa-remove-unknown

docker stop ruleparser
docker rm -f ruleparser
docker run -d --name ruleparser --network jids --network-alias jids -p 9081:9081 -v /var/jenkins_home/workspace/java_tale/data:/data -v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone ruleparser:20190628-1.0

這里要稍微解釋一下:
第2行:防止第3行命令執(zhí)行后出現(xiàn)”cannot stop container”的情況
第3钞艇、4行:停止前一版本的容器,并刪除該容器(不刪的話豪硅,第5行的docker run命令會因存在相同名稱的容器而失斚懔А)
第5行:啟動容器。參數(shù)說明如下:
--name:指定了容器名稱舟误;
--network:指定該容器所在的網橋葡秒,該網橋要與后文的mongodb容器所在網橋相同,否則容器不能訪問mongod嵌溢;
--network-alias:表示網橋的別名眯牧,如果沒有別名的話不需要此參數(shù);
-p:端口映射赖草,格式為"-p 宿主機端口:容器端口"学少;
-v /var/jenkins_home/workspace/java_tale/data:/data:表示將宿主機的目錄/var/jenkins_home/workspace/java_tale/data映射到容器目錄/data。宿主機目錄存放的是項目需要的數(shù)據(jù)秧骑,在項目中位于data目錄下版确,data目錄與src目錄同級扣囊,見第4步附圖。這樣配置后绒疗,需要在項目的properties文件中侵歇,制定數(shù)據(jù)路徑,如下圖:


image.png

-v /etc/localtime:/etc/localtime -v /etc/timezone:/etc/timezone:指定容器中的時區(qū)吓蘑,主要是方便查看日志
ruleparser:20190628-1.0:鏡像名稱及標簽惕虑,注意:名稱及標簽要與pom.xml中的配置相同。

第5步:mongodb容器及配置主從節(jié)點
參考博客https://outmanzzq.github.io/2019/01/30/docker-mongo-replica/
這里貼出我的配置過程磨镶。

5.1 運行mongodb replica的三個容器
docker run -dit -p 27000:27017 --name mongo-master -v /server/data/mongodb-docker/db/master:/data/db --network jids --network-alias jids mongo mongod --replSet rs

docker run -dit -p 27001:27017 --name mongo-slave-1 -v /server/data/mongodb-docker/db/slave-1:/data/db --network jids --network-alias jids mongo mongod --replSet rs

docker run -dit -p 27002:27017 --name mongo-slave-2 -v /server/data/mongodb-docker/db/slave-2:/data/db --network jids --network-alias jids mongo mongod --replSet rs

其中:
-p 27000:27017 表示映射宿主機27000端口到容器的27017端口
--name mongo-master 表示容器名為mongo-master
-v /server/data/mongodb-docker/db/master:/data/db 表示映射宿主機目錄到mongodb容器/data/db目錄 (mongodb容器運行時的默認目錄)溃蔫,兩個目錄可以自定義
--net jids 指定容器網絡為local-mongo-cluster
mongo 容器使用的mongodb鏡像
mongod --replSet rs 執(zhí)行mongod命令,將該實例(容器)添加到名為rs的副本集

5.2 進入mongo-master容器的mongo命令行
docker exec -it mongo-master mongo
(進入容器的命令是docker exec -it mongo-master /bin/bash琳猫,不要搞混)

5.3 配置主從節(jié)點
use jids
(1)確定主從配置
config = {
"_id" : "rs",
"members" : [
{
"_id" : 0,
"host" : "mongo-master:27017"
},
{
"_id" : 1,
"host" : "mongo-slave-1:27017"
},
{
"_id" : 2,
"host" : "mongo-slave-2:27017"
}
]
}
(2)初始化
rs.initiate(config)
(3)切換到MASTER節(jié)點(如果切換后還是SECONDARY伟叛,可能由于MASTER連接問題,多嘗試幾次即可)
rs.config()

5.4 從宿主機導入數(shù)據(jù)到容器
5.4.1 首先進入容器并在/root下創(chuàng)建data文件夾
docker exec -it mongo-master /bin/bash
mkdir /root/data
5.4.2 然后退出容器回到宿主機脐嫂,復制數(shù)據(jù)到容器统刮。命令格式為:docker cp 數(shù)據(jù)文件夾 容器名:容器內保存數(shù)據(jù)的目錄。例如:
//假設在宿主機中保存bson和json文件的jids文件夾在/root/jids/data下
docker cp /root/jids/data/jids mongo-master:/root/data

然后就可以驗證主從節(jié)點是否有效了(沒有包括更多驗證雹锣,如某個節(jié)點宕機)网沾,附常用命令:
(1)創(chuàng)建數(shù)據(jù)庫
use 數(shù)據(jù)庫名
(2)創(chuàng)建集合
db.createCollection("集合名")
(3)顯示所有數(shù)據(jù)庫
show dbs
注意:當使用show dbs時癞蚕,會提示Error: listDatabases failed:..."errmsg" : "not master and slaveOk=false"蕊爵。此時執(zhí)行一下命令rs.slaveOk()即可
(4)顯示所有集合
show collections
(5)顯示集合中的所有文檔
db.集合名.find()

第6步:在項目中配置mongodb和redis
修改項目的properties文件,根據(jù)宿主機及容器情況配置mongodb和redis的IP和Port
6.1 配置mongodb
spring.data.mongodb.uri=mongodb://172.17.0.1:27000,172.17.0.1:27001,172.17.0.1:27002/jids?replicaSet=rs
這里的172.17.0.1是宿主機中輸入ifconfig后桦山,docker0對應的虛擬IP地址攒射。這個地址被所有容器共享,相當于容器組成的虛擬網絡的localhost恒水。注意会放,不要使用127.0.0.1來試圖使用宿主機的服務,因為容器所在的虛擬網絡與宿主機所在的網絡是隔斷的钉凌。

mongodb.png

6.2 配置redis
redis.host=172.17.0.1
redis.port=6379
這里的host同6.1中的IP咧最。

redis.png

第7步:訪問項目
這里有個坑。假如測試項目的controller如下


controller.png

要訪問的功能模塊如下:


method.png

如果將war包扔在tomcat的webapps中御雕,那么訪問該模塊時需要采用"IP:PORT/testproject/test_parser?"這樣的URI矢沿。然而,由于我們在Docker中使用的是Springboot內置的Tomcat酸纲,訪問的URI變?yōu)榱?IP:PORT/test_parser?"捣鲸。這一點需要注意。

到此闽坡,整個構建過程基本完成了栽惶。過程這么長愁溜,可以想象遇到了多少坑。上面的流程都是在填完坑后的總結外厂,其中的心酸就不提了冕象。還有很多細節(jié)還可以優(yōu)化,只有待后面熟悉Docker和Jenkins后再做打算了酣衷。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末交惯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子穿仪,更是在濱河造成了極大的恐慌席爽,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啊片,死亡現(xiàn)場離奇詭異只锻,居然都是意外死亡,警方通過查閱死者的電腦和手機紫谷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門齐饮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人笤昨,你說我怎么就攤上這事祖驱。” “怎么了瞒窒?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵捺僻,是天一觀的道長。 經常有香客問我崇裁,道長匕坯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任拔稳,我火速辦了婚禮葛峻,結果婚禮上,老公的妹妹穿的比我還像新娘巴比。我一直安慰自己术奖,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布轻绞。 她就那樣靜靜地躺著采记,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铲球。 梳的紋絲不亂的頭發(fā)上挺庞,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音稼病,去河邊找鬼选侨。 笑死掖鱼,一個胖子當著我的面吹牛,可吹牛的內容都是我干的援制。 我是一名探鬼主播戏挡,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼晨仑!你這毒婦竟也來了褐墅?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤洪己,失蹤者是張志新(化名)和其女友劉穎妥凳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體答捕,經...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡逝钥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拱镐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艘款。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沃琅,靈堂內的尸體忽然破棺而出哗咆,到底是詐尸還是另有隱情,我是刑警寧澤益眉,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布晌柬,位于F島的核電站,受9級特大地震影響呜叫,放射性物質發(fā)生泄漏空繁。R本人自食惡果不足惜殿衰,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一朱庆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闷祥,春花似錦娱颊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悟衩,卻和暖如春剧罩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背座泳。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工惠昔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留幕与,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓镇防,卻偏偏與公主長得像啦鸣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子来氧,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353