??
? ? ? ?首先說下為什么要寫這篇文章驾茴,網(wǎng)上基于jenkins自動話部署的文章很多戴陡,但是大多基于官方鏡像做的,官方的latest版本的鏡像部分插件不可用沟涨,筆者結(jié)合工作實際情況和本著學(xué)習(xí)的態(tài)度打算從零開始搭建一套自動化部署環(huán)境,記錄這個過程中遇到的問題和如何解決問題异吻。
?? ?本文重點介紹jenkins裹赴,自建jenkins鏡像,以及jenkins如何在docker容器中運行诀浪,jenkins和docker私有倉庫又是怎么玩的棋返。docker說明、安裝和git說明雷猪、安裝睛竣,maven說明、安裝求摇,gitlab說明射沟,安裝。在本文中不會特別詳細的介紹与境。
本文部分引用 網(wǎng)上51CTO圖片?验夯。
背景說明
Jenkins是一個開源軟件項目,是基于Java開發(fā)的一種持續(xù)集成工具摔刁,用于監(jiān)控持續(xù)重復(fù)的工作挥转,旨在提供一個開放易用的軟件平臺,使軟件的持續(xù)集成變成可能共屈。
先來了解一下比較典型的java項目發(fā)布工作流程:
1.java項目開發(fā) >> 2.提交項目代碼到(git或svn) >> 3. 拉取項目代碼(jenkins或手動) >> 4.編譯項目代碼(jenkins或手動) >> 5.發(fā)布java項目绑谣,并運行java項目 >> 6.測試
在來看看用docker+jenkins+git發(fā)布java項目流程又是怎樣的呢:
1.java項目開發(fā) >> 2.提交項目代碼git容器 >> 3.jenkins容器拉取項目代碼 >> 4.maven編譯構(gòu)建項目 >> 5.jenkins發(fā)布項目到tomcat容器 >> 6.測試
看到上面的流程后,在沒有jenkins的情況下這些步驟都是手工完成的拗引,有了Jenkins的幫助借宵,在這6步中,除了第1步寺擂,后續(xù)的5步都是自動化完成的暇务。當(dāng)你完成了提交泼掠,Jenkins會自動運行你的編譯腳本,編譯成功后垦细,再運行你的測試腳本择镇,這一步成功后,接著它會幫你把新程序發(fā)布出去括改,特別的腻豌,在最后一步,你可以選擇手動發(fā)布嘱能,或自動發(fā)布吝梅。
1、 環(huán)境描述
1惹骂、服務(wù)器部署信息
服務(wù)器主機名IP運行服務(wù)
jenkins服務(wù)器:jenkins192.168.154.128 安裝docker苏携、 運行jenkins容器、gitlab对粪、jdk右冻、maven,docker私有庫
app 服務(wù)器docker 192.168.154.128??安裝docker著拭、創(chuàng)建鏡像運行java項目 gateway
說明:
本文中完全是模擬生產(chǎn)環(huán)境中服務(wù)器的規(guī)劃:git單獨部署纱扭、jenkins單獨部署。如果你沒有這么多服務(wù)器儡遮,可以把git服務(wù)器和jenkins服務(wù)器放在一起來測試乳蛾。前提是不要搞暈了就可以。
gateway是 springcloud 的gateway鄙币,基于springboot和maven?
2肃叶、版本信息
名稱版本軟件包說明
服務(wù)器 Centos 7 及內(nèi)核信息
docker 版本:
JDK環(huán)境 1.8.211?
maven 版本信息:? apache-maven-3.6.1-bin.tar.gz
jenkins 采用2.150 版本 的war包,下載地址:https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.150/jenkins.war
registry最新版本docker hub下載最新registry鏡像docker私有倉庫
3十嘿、 準備工作
? ?3.1? JDK的安裝
????????????這里就不介紹了被环。通過rpm包的免配置自動安裝或者tar.gz包配置安裝網(wǎng)上有很多文章 。
? ?3.2 docker 的安裝
????安裝下一些必要的系統(tǒng)工具:
```
? ??sudo? yum install -y yum-utils device-mapper-persistent-data lvm2
```
????添加阿里的yum的源:
```
? ??sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
```
????更新 yum緩存 :
```
? ??sudo yum makecache fast
```
????安裝docker :
```
? ??sudo yum -y install docker-ce
```
????docker 啟動:?
```
? ??sudo systemctl start docker?
```
????docker 設(shè)置開機自啟動:
```
? ??sudo systemctl enable docker.service
```
? ? 3.3 docker 私有倉庫安裝(不使用私庫可以無視)
? ?sudo? docker search register?
選第一個鏡像就好?
拉取鏡像:
sudo docker? pull?register?
?這里就可以通過 docker images 查詢本地鏡像
然后通過該鏡像啟動一個容器:
```
sudo docker run? -d -p 5000:5000? -v /opt/data/registry:/tmp/registry ? --name?register?register?
```
說明這里是將本地的 /opt/data/registry? 掛載到 容器的 /tmp/registry 详幽,防止容器刪除的時候筛欢, 容器里面的鏡像會丟失。
將本地鏡像push到私庫:
```
sudo docker tag nginx 192.168.154.128:5000/nginx
```
這里注意唇聘。因為Docker從1.3.X之后版姑,與docker registry交互默認使用的是https,然而此處搭建的私有倉庫只提供http服務(wù)迟郎,所以當(dāng)與私有倉庫交互時就會報上面的錯誤剥险。
這個問題解決方法:
首先找到 docker.service? 文件?
```
find / -name??docker.service?
```
然后修改docker.service 文件
vim /usr/lib/systemd/system/docker.service
加一條這句話:--insecure-registry 192.168.154.128:5000
sudo docker push 192.168.154.128:5000/nginx
如果我們要查詢私庫中的所有鏡像可以用如下:curl -XGET http://registry:5000/v2/_catalog
3.4 jenkins 安裝
?所有準備jenkins 需要的tar包和war包:
apache-ant-1.9.14-bin.tar.gz
apache-maven-3.6.1-bin.tar.gz
apache-tomcat-9.0.21.tar.gz
git-2.14.2.tar.gz
jdk-8u211-linux-x64.tar.gz?
jenkins.war
然后編寫Dockerfile?
代碼如下:
```
FROM centos:7
USER root
# author info
MAINTAINER wupeng 513943544@qq.como
#安裝一些必要的系統(tǒng)工具:
# install git
ADD git-2.14.2.tar.gz /opt/
RUN yum install -y? gcc gcc-c++ automake autoconf libtool make curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
# 切換上下文
WORKDIR /opt/git-2.14.2
RUN ./configure --prefix=/usr/local/git \
? ? && make && make install \
? ? && ln -s /usr/local/git/bin/git /usr/sbin/git
# install jdk
ADD jdk-8u211-linux-x64.tar.gz? /opt/
ENV JAVA_HOME /opt/jdk1.8.0_211
ENV CLASSPATH .:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $JAVA_HOME/bin:$PATH
# install maven
ADD apache-maven-3.6.1-bin.tar.gz /opt/
ENV MAVEN_HOME /opt/apache-maven-3.6.1
ENV PATH $MAVEN_HOME/bin:$PATH
RUN mkdir -p /var/jenkins_home
ENV JENKINS_HOME /var/jenkins_home
ADD apache-tomcat-9.0.21.tar.gz /opt/
# startup tomcat
ADD jenkins.war /opt/apache-tomcat-9.0.21/webapps
CMD /opt/apache-tomcat-9.0.21/bin/catalina.sh run?
CMD systemctl start docker
# expose memcached port
EXPOSE 8080
```
ps:想在dockerfile里面加上安裝docker,結(jié)果測試發(fā)現(xiàn)容器是不能用systemctl 的宪肖,導(dǎo)致docker 啟動不了表制,不過沒關(guān)系健爬,不裝docker,可以用宿主機的docker 完成push到私庫的操作么介。
然后通過docker build 創(chuàng)建鏡像
dcoker build -t jenkins_2.150 -f /home/Dockerfile .
注意 . 別漏掉了娜遵。
?
創(chuàng)建成功。
將鏡像運行成容器:
```
docker run -d -p 8080:8080 -p 50000:50000 -v /soft/jenkins/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime --name jenkins_2.150 jenkins:2.150
```
查詢?nèi)萜?:
docker ps?
驗證docker jenkins 環(huán)境是否正常壤短。
進入容器 :
```
docker exec -it jenkins_2.150 /bin/bash
```
驗證 jdk 和maven git docker是否正常设拟。
其他都沒問題。 然后查看 jenkins 是否正常久脯,退出容器纳胧,然后docker logs -f jenkins_2.150?
可以看到j(luò)enkins的 初始化密碼:
這里需要注意,jenkins 官方的源下載插件的時候帘撰,各種被墻跑慕,所以這里修改成清華大學(xué)的源。
修改文件在:
/soft/jenkins/jenkins_home/hudson.model.UpdateCenter.xml
這個目錄就是之前啟動容器的時候掛載的目錄摧找,然后找到這個文件相赁。
https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
然后 重啟docker 容器
docker restart jenkins_2.150?
然后登陸到j(luò)enkins?
http://192.168.154.128:8080/jenkins
密碼就是之前 打印 的密碼,如果找不到 慰于,直接查看下面路徑的初始密碼?
cat?/var/jenkins_home/secrets/initialAdminPassword?
此路徑是jenkins容器內(nèi)部的路徑,可以直接看掛載的jenkins_home
登錄之后唤衫,選擇第一個婆赠,安裝建議的插件。
部分插件裝不成功的插件佳励, 直接過也沒事休里, 進去之后還能針對性安裝,接下來基本操作赃承, 不細說了妙黍。安裝好了 重啟下容器。
4瞧剖、gitlab 配置
4.1創(chuàng)建測試項目
創(chuàng)建gateway 項目拭嫁,然后把本地測試項目push到gitlab倉庫,具體操作省略抓于,gitlab有詳細步驟做粤。
4.2 配置ssh key
進入jenkins 容器。 然后配置git user.name 和 user.email 捉撮。然后生成ssh key 配置上即可怕品。
生成ED25519 SSH key?
ssh-keygen-ted25519-C"email@example.com" 這里郵箱填配置的郵箱 配置 git config --global? user.email? "email@example.com"
生成之后默認在是 ~/.ssh/目錄下面。 然后cat 下巾遭, 把內(nèi)容復(fù)制gitlab里面即可肉康。記得是公鑰 闯估!
5、Jenkins 配置
? ??????首先這里說下jenkins 做了寫什么吼和。
???????Jenkins 主要是在git倉庫拉取代碼涨薪,然后在本地 mvn package? 成jar 包 然后用已經(jīng)寫好的Dockerfile? docker build 成 鏡像,然后用 push 到本地的私庫纹安。之后再調(diào)用ssh 到appService 去從 私庫里面pull 鏡像尤辱, 然后再運行成容器。目的明確之后厢岂, 在來做這套就很好解決光督。
5.1、安裝插件
? ? 這里說下塔粒,Jenkins需要安裝下面這個插件才可以看到 創(chuàng)建maven項目?
5.2结借、jenkins 配置工具信息
在這里配置 maven JDK的配置信息。git因為已經(jīng)做了軟連接卒茬,不用船老。
例如 配置maven
????????這里需要注意的安裝的maven 默認是官方的源鏡像倉庫,國內(nèi)下載的話圃酵,各種被墻柳畔,所以這里需要修改maven settings.xml文件,我這里改成阿里的倉庫郭赐。
```
<mirrors>
? ? <mirror>
? ? ? <id>alimaven</id>
? ? ? <name>aliyun maven</name>
? ? ? <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
? ? ? <mirrorOf>central</mirrorOf>? ? ? ?
? ? </mirror>?
?</mirrors>
```
至于settings.xml的位置薪韩,可以用find 查詢下, 在/opt/maven/conf? 下面.
5.3捌锭、創(chuàng)建一個maven工程
然后配置
根據(jù)自己情況自己配置俘陷。
配置git 倉庫信息:
這里說明下:已經(jīng)配置了sshkey 結(jié)果還報錯,這么解決?
然后再配置 git repo信息观谦,就不報錯了拉盾。這里222端口是宿主機 映射gitlab 容器的 22端口
配置maven 打包指令
然后 可以嘗試跑一下,【立即構(gòu)建】
這里看到 已經(jīng)build成功了豁状。
接下來捉偏,要做的事是把jar build成鏡像,然后啟動泻红,
目前有兩種解決辦法:
????????一個簡單點的 直接用scp 指令將需要的jar直接傳輸?shù)綄?yīng)的服務(wù)器告私,
然后在目標(biāo)服務(wù)器(app服務(wù)器)上做build images 和? 啟動操作。
? ? ? ? 一個復(fù)雜點的方案就是使用私庫承桥,利用tag驻粟,構(gòu)建將鏡像在jenkins宿主機上build成image然后push到私庫,
然后目標(biāo)服務(wù)器(app服務(wù)器) 上pull images 然后啟動。(私庫沒有刪除鏡像的操作蜀撑,目前沒找到)
不管那個方案挤巡,先編寫jar build成images 的dockerfile,代碼如下:
首先準備下Dockerfile文件 酷麦。
```
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD ./target/gateway.jar gateway.jar
CMD java -Xms2G -Xmx2G -Xss256k -XX:PermSize=256m -XX:MaxPermSize=256m? -XX:+UseCompressedOops -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/dump -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/usr/dump/heap_trace.txt -XX:NewSize=512m -XX:MaxNewSize=512m -Djava.security.egd=file:/dev/./urandom -jar gateway.jar
EXPOSE 9988
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
```
這里解釋下矿卑,
FROM openjdk:8-jdk-alpine 基于?openjdk:8-jdk-alpine 構(gòu)建
VOLUME /tmp? 將 /tmp 掛載的宿主機/tmp 目錄,
ADD ./target/gateway.jar gateway.jar? 添加gateway.jar (注意路徑)
CMD java 這句 就是java -jar? xxx.jar 啟動jar包了沃饶。
EXPOSE 9988 聲明端口母廷。
最后兩句 就是定義時區(qū)和做了個軟連接。
第一種解決方案:使用scp指令 直接在appServer上拷貝jar
scp 可以寫個shell腳本糊肤, 也可以通過ssh加授信琴昆。
這里就說下加ssh授信怎么操作:
在appServer 生成rsa 非對稱密鑰對,
ssh-keygen -t rsa??
遇到提示直接回車就好馆揉。
然后生成的密鑰在~/.ssh下?
然后在將id_rsa.pub這個公鑰的內(nèi)容copy到目標(biāo)服務(wù)器(jenkins宿主機)的~/.ssh/ 目錄下的?authorized_keys 里面去 (沒有就創(chuàng)建一個authorized_keys 文件)业舍。
然后可以測試下 ssh? ip ,直接進去表示成功了升酣,
然后在jenkins 里面寫shell指令舷暮。
如圖:
```
docker stop gateway
docker rm gateway
docker rmi gateway
```
```
cd /soft/jenkinsdata/gateway
rm -rf *.jar
scp root@192.168.154.128:/soft/jenkins/jenkins_home/workspace/gateway/target/gateway.jar .
docker build -t gateway -f /soft/jenkinsdata/gateway/Dockerfile? .
docker run -it -d -p 9988:9988 -v /etc/localtime:/etc/localtime --name gateway? gateway
```
在build 之前先停止docker 容器,然后刪除鏡像噩茄。
然后再build成功之后下面。
重新scp jar 過來,build成鏡像绩聘,然后啟動成容器沥割。
然后啟動試一試:
Error response from daemon: No such container: gateway
Error: No such container:? gateway
Error: No such image: gateway
這里因為找不到容器,是因為 第一次還沒啟動過容器君纫,但是這樣寫會導(dǎo)致報錯,所以這里需要處理下芹彬。
當(dāng)有這個容器的時候就關(guān)掉 然后刪除容器及其image 如果沒有蓄髓,無事發(fā)生。這樣處理就OK了舒帮。
用一個shell腳本來做這個操作:
```
#!/bin/sh
if [ $# == 0 ];then
echo "請輸入需要關(guān)閉服務(wù)名稱"
exit 0
else
? cid=$(docker ps -a | awk '$2~/'$1'/{print $1,$2}')
? arr=($cid)
? len=${#arr[@]}
? if [[ len -eq 0 ]];then
? ? echo "沒有與$1相關(guān)的服務(wù)"
? elif [[ len -eq 2 ]];then
? ? echo "匹配到服務(wù)${arr[1]}"
? ? id=${arr[0]}
? ? echo "關(guān)閉containerId 為$id的服務(wù)"
? ? docker stop $id
? ? docker rm $id
? ? docker rmi ${arr[1]}
? else
? ? echo "匹配到多個與$1相關(guān)的服務(wù)"
? ? for i in "${!arr[@]}"
? ? ? ? do
? ? ? ? t=`expr $i % 2`
? ? ? ? if [ $t -eq 0 ];then
? ? ? ? ? ? let ii=i+1
? ? ? ? ? ? echo "${arr[$ii]}"
? ? ? ? fi
? ? ? ? done
? fi
fi
```
處理之后会喝,修改下 jenkins shell配置,然后再次執(zhí)行構(gòu)建項目玩郊,經(jīng)過一段時間等待肢执,到appServer 看下? gateway已經(jīng)啟動了。
到這里就OK了译红,簡版測試環(huán)境的自動化部署就大功告成预茄。
最后總結(jié):
Docker+Maven+Jenkins +Git 自動化部署解決方案,核心是利用jenkins的git和maven插件來完成項目的pull 和build操作,然后通過build的pre或者post的執(zhí)行shell的機制來執(zhí)行自己想要執(zhí)行的任何shell腳本耻陕,這里就是docker的創(chuàng)建鏡像和容器的指令拙徽。
需要注意的是shell 腳本執(zhí)行錯誤導(dǎo)致整個構(gòu)建失敗的情況。