Docker學習總結(13)——從零開始搭建Jenkins+Docker自動化整合環境
本文只簡單標記下大概的步驟,具體搭建各個部分的細節,還請自行搜尋。第一、二部分只是對Jenkins和Docker的簡單介紹,熟悉的同學請直接跳到第三部分。
一、關於Jenkins
Jenkins簡介
Jenkins可以幫你構建一個自動化的持續整合環境,你可以使用它來“自動化”編譯、打包、分發部署你的應用,它相容ant、maven、gradle等多種第三方構建工具,同時跟svn、git能無縫整合,也支援直接與知名原始碼託管網站,比如github、bitbucket直接整合。
Jenkins安裝
Jenkins的安裝十分簡單,你可以從官網http://mirrors.jenkins-ci.org/war/latest/ 直接下載war包,使用java -jar jenkins.war,或者放到Tomcat類似的容器裡執行都可以(JDK版本建議使用1.6以上來執行)。Jenkins預設啟動埠是8080,請注意端口占用。另外,Jenkins檔案其實都在~/.jenkins目錄下,執行過程中你可以在這裡找到你執行過的job和相應的日誌檔案。
首次安裝,可以把外掛都安裝上,自己都試試看。如果因為網路原因,外掛下載失敗的,可以從失敗詳情中把地址拷出來,下載後,以上傳hpi檔案的方式安裝。
系統設定
安裝完成的第一步,先到Blobal Tool Configuration中配置相關的環境,如JDK、MAVEN、GIT等,相應的路徑設定都是設定Jenkins這臺機子本地的目錄。建議把所有的配置都完善下,否則日後的執行中可能會出現一些小問題,可以試下點選?檢視幫助,還是很有用的。
Jenkins叢集配置
叢集配置也十分簡單,就是新增slave節點的過程。點選系統管理->管理節點->新建節點,各個配置後面都有詳細的幫助說明的。在啟動方法這裡推薦使用 Launch slave agents on UNIX machines via SSH,這樣master節點會主動使用SSH登陸到slave節點上,並執行java -jar slave.jar,這樣一個slave節點就新增完成了。
構建Job
其實到這一步,就是jenkins的常規流程了,你可以參照建立Job選項的介面的各個配置,制定你構建計劃,或者我們直接使用指令碼來完成我們的構建操作(建議)選擇構建Execute shell,文章末尾會附上一個完整專案的shell構建流程。
Pipeline
Pipeline字面意思就是流水線,很好用的Jenkins的一個外掛,將很多步驟按順序排列好,做完一個執行下一個。真實的工作環境有很多job,比如先編譯,然後執行靜態程式碼檢查、單元測試、然後部署伺服器、伺服器重啟、進行ui測試等。我們需要對這些job進行一些設定將它們的上下游關係配置好。
這時候Pipeline就派上用場了。在Jenkins主頁點選新建檢視,然後選擇Build Pipeline View,然後填寫Select Initial Job,構建後的操作可以選擇其他的Job,以此類推,這樣一個流水線就完成了。Pipeline提供檢視介面,你可以在檢視上形象地看到整個構建計劃的執行流程和完成度。
二、關於Docker
Docker 簡介
Docker現在是Github社群最火的專案之一,Docker是個容器,或許你聽過lxc,你可能知道Tomcat這個Web容器,容器是什麼概念,意會就好。問個問題,你想在一臺機子上執行一個java6的應用,又想執行一個java8應用怎麼辦;或者說你開發出一個軟體,mac版、windows版本,我都想執行,怎麼辦?裝虛擬機器?不不不,虛擬機器太浪費資源了,Docker這時候就派上用場了,在電腦上,你可以同時裝一個mac的容器和windows的容器哦。一個虛擬機器可能會消耗2到3G的記憶體,一個容器僅僅只消耗幾百M的資源哦。
Docker 安裝
具體安裝細節,可以參照https://docs.docker.com,文件說得很清楚了。 Docker原本是開發在Linux上的,Windows下是採用Docker machine的方式,起一個虛擬機器在虛擬機器裡面跑Docker。本來呢Mac也是採用虛擬機器的方式,後來有了Docker for mac,採用HyperKit,一種更輕量級的虛擬化方式。當然,你還是可以用Docker machine的方式執行。
Docker 基礎
搞清楚兩個概念,容器與映象。打個比方吧。裝機,容器就是裝完成後的系統,映象就是ISO安裝盤,系統映象。
作為一個合格的程式設計師,你一定用過Git的吧,pull,commit,push……寫程式碼過程就是這樣,先拉取程式碼pull,然後是在一個基礎的文字上不斷地增加commit,加積木一樣,一層層疊加,累積上去,最後再push上去。沒錯Docker就是採用這種形式。
簡單介紹下Docker命令:
-
Docker version / Docker info 檢視基本資訊,遇到使用問題或者BUG,可以到社群裡報告,記得帶著這些資訊哈。
-
Docker pull 拉取映象。
-
Docker run 從映象建立一個容器並執行指定的命令常用引數-i -d,建議用—-name命名這個容器,命名後可以使用容器名訪問這個容器。
-
Docker attach(不推薦使用)。
-
Docker exec -ti CONTAINER /bin/bash 連線到容器上執行bash
-
Docker logs CONTAINER 檢視日誌,如run命令後的執行結果,Docker logs -f 檢視實時的日誌。
-
Docker kill 殺死Docker容器程序,你可以使用Docker kill $(Docker ps -aq)殺死所有的Docker程序,後者打印出所有的容器的容器id(包括正在執行的,和沒有執行的)。
-
Docker rm CONTAINER 刪除一個容器,記得要先停止正在執行的容器,再去刪除它。
-
Docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/容器外向容器內複製檔案(也可以用掛載的形式哦)。
-
Docker commit -a “mike” -m “映象的一些改動” CONTAINER 當你在容器內做了某種操作後,如增加了一個檔案,你可以用這個命令把修改提交,重新打包為映象。
-
Docker push 推送映象。。到這裡是不是覺得跟Git的模式已經有點像了呢。
-
Docker history IMAGES 檢視映象的修改歷史。
-
Docker ps -a | grep "Exited" | awk '{print $1 }'| xargs Docker rm 刪除exited的容器。
-
Docker rmi $(Docker images | awk '/^<none>/ {print $3}') 刪除tag為NONE的容器。
Dockerfile基礎
Dokcerfile,是的,你還是要稍微掌握下Dockerfile的寫法。
-
From 每個Dockerfile映象的構建都會基於一個基礎映象,這是你一來的基礎映象name:tag,git。
-
MAINTAINER (不用記,作者簽名)。
-
ENV 配置環境變數。
-
COPY 複製本地。
-
EXPOSE 暴露容器的埠。
-
WORKDIR 後續命令的執行路徑。
-
RUN important!,執行相應的命令,這一步是在容器構建這一步中執行的命令,一般用作安裝軟體,操作的結果是持久化在容器裡面儲存下來的。
Tips:每次執行RUN的時候都是再預設路徑執行的,如果要到固定路徑下執行命令請在之前加WORKDIR,或者使用RUN (cd workpath && echo "mike")這樣把cd命令跟相應的執行命令用括號括起來。
-
ENTRYPOINT 容器啟動後執行的命令。
三、Jenkins+Docker自動化整合環境搭建
這一步,我們把Jenkins和Docker結合起來。Jenkins本身版本比較老,雖然外掛多,但許多外掛沒有人在維護更新,環境本身還是比較舊的,且各式各樣的工程如果都用外掛來安裝,這樣的外掛不一定滿足要求,所以建議配合Docker來搭建測試環境。
如果說好處的話,還有比較激進的一段話(建議略過哈):
我們把一個工程程式碼開發後的測試流程簡單分為編譯、部署(事實上可能更多,如專案程式碼有多個工程,工程間有相互依賴)。如果我們想在一個slave節點上既執行Java7應用,又執行Java8應用,哦,Jenkins有相應的外掛解決?那如果是NodeJs4應用和NodeJs5應用呢?JAVA升級到9了,外掛沒更新?像一些複雜的工程,如JDK自身的編譯、如Docker專案的編譯,我需要安裝各種依賴,就可能會汙染全域性空間,這時候就建議把編譯過程放到容器裡,或者說我要在Linux上編譯部署一個Windows應用,在一個Windows容器裡部署就可以了。
再比如,如果我們用omad部署web應用可能要考慮埠衝突,部在Docker容器裡,工程程式碼的埠,都不用變。還有,容器作測試環境的話,如果要保證線上,線下環境一致,甚至可以複製一個線下容器,直接在線上跑容器的。還有......
大致的想法是,我們用Jenkins來做節點控制、版本管理、流程設定、觸發Job,用Docker來搭建編譯部署環境。把這一切連線起來的就是流程指令碼和Dockerfile的編寫。
實現細節可以參照下面的示例。
觸發條件:由Jenkins控制,如設定定時執行,或者github中的每一個commit,或者每一個PR執行一次。
構建流程:各個環節,Job,之間用Pipeline來實現整個構建流程的控制。
構建Job:這裡,我覺得可以分為兩種情況,一種是把拉取程式碼的過程和構建編譯環境的過程都放到Dockfile裡面,這適用於比較複雜的編譯環境,如Docker本身的編譯需要安裝許多的依賴,對依賴的版本都有不同的要求,還是建議把編譯環境放在容器的裡面。另一種情況,為求省事方便,如java工程,編譯一般用maven等構建工具來完成的話,大可以放在外面,只是把執行環境搬到Docker容器裡。
Execute shell:
Dockerfile:
配置基礎執行環境。
如果需要編譯,配置編譯環境,可以在容器內拉取程式碼,執行編譯。
web應用暴露埠。
配置應用啟動命令。
另外,容器裡你都可以配置成8080埠,暴露8080埠,只要再Docker run -p *:8080,執行時改下相應的埠對映就可以了。