[自動建置實戰]Jenkins+Github+Docker

Reading time ~2 minutes

發跡

以前就聽過”好的工程師,要把自己的工作流程自動化,讓工作更有效率”一說,剛好這個禮拜研究室老師給我們放了一週假,讓我有機會玩一玩,把實驗室的一些部署自動化。

我們實驗室有很多專題生,每組專題生都要把他們的Web伺服器部署到一個人人都訪問到的地方。我們實驗室以往的做法都是,在實驗室電腦開VM,轉8080 port和3389 port出去給專題生,讓專題生他們自己遠端進他們的VM手動部署。這過程常常抱怨不斷,像是VM太慢,操作很卡等問題…而讓我想自動化的真正動機是,我和一組專題生有個共同合作的計畫,我做後端邏輯,專題生做前端UI,他們前端Ajax的部分一直出現CORS問題,導致他們要將結果部署到我的Tomcat後才能做他們前端的測試,這個部署過程太過頻繁,讓他們對VM的慢速更是無法忍受。所以我決定試著用Jenkins+Github+Docker幫他們自動部署Tomcat Web服務,來取代以往傳統的手動部署,減輕大家的痛苦。

我規劃的流程如下,專題生上傳他們的前端作品到Github,Github會觸發我們實驗室的Jenkins的作業,驅動本機電腦做docker的部署工作,整個過程都能在Jenkins看到並追蹤,部署完後,專題生就能直接用瀏覽器查看更新。

process

安裝Jenkins

Jenkins是一套好的自動化整合/部署工具,可以幫忙跑專案測試,測試完成後部署到相對應的伺服器,也可以自動寄信給開發者或者是指定的內部人員。很多人看中他良好的視覺化介面和豐富的trigger plugin,我們這次實作就會使用到Github plugin。

jenkins

我的OS是Ubuntu 16.04,而在Ubuntu安裝Jenkins基本上毫無壓力,詳細可以參考這一篇做操作。再來跟大家講一個我遇到的坑Orz,一定要設定Jenkins User,否則會一直遇到類似Jenkins script cannot open .git/FETCH_HEAD: Permission denied等…權限問題,雖然可以手動chmod更改文件權限,但設定Jenkins User比較一勞永逸。設定請參考這篇How to run Jenkins under a different user in Linux,他能解決之後run script的很多問題。

架起來後,就會出現類似以下畫面!

jenkins

因為要提供帳號給專題生做使用,所以必須設定專題生的帳號權限。

(1) 左邊欄點選“管理Jenkins”,到右邊滾輪往下拉,會看到”管理使用者”,點入。

(2) 點選左邊欄的”建立使用者”,建立給專題生的帳號

jenkins

(3) 回到儀板表,點選”管理Jenkins”的”設定全域安全性”

jenkins

(4) 關於安全性領域,選擇內建使用者資料庫,建議不要開放外人註冊比較好,雖然可以設定匿名使用者的權限,但如果有一些亂七八糟的人註冊還是會增加管理上的負擔。

jenkins

接下來是用戶權限配置,如果懶得設定可以直接選用Jenkins的專案型矩陣授權策略,這裏的矩陣是不同身份對應不同權限的一個table。 如果要和我一樣自己設定每個帳號的權限,就勾選”矩陣型安全性”,詳細設定解說可以參考這一篇,滑鼠移到每個項目上會有說明,我把重點放在設定作業的權限上,我希望學弟妹們在自動建置出問題時,能自己透過手動建置或取消建置,但無法更改建置的script的內容。打勾workspace可以讓學弟妹看到建置的程式碼。

jenkins
jenkins

設定好就按Apply和存檔,會馬上生效!

Docker部署Tomcat

docker

在開始前,希望大家都對Docker images, container的運作有了基本的認識,這裏推薦這一篇原理解說,講得非常讚!docker常被運用在微服務框架裡。一個docker一個服務,每個服務間,互相建立通道傳遞數據 (Ex. Tomcat docker和MySQL docker通訊) ,雖然也有一個docker多個服務的解決方案,但我認為遵循docker設計的情境去使用比較不會遇到奇怪的問題,畢竟docker還是不能完全當VM用,他比較像是”服務+環境設定”的打包檔。歡迎查閱這裏docker的坑

然後跟著這篇的Tomcat部署教學玩一遍,快速部署Tomcat docker! 要注意的是,Jenkins和Tomcat服務,所監聽的port都是8080,所以將docker的port映射到實體電腦的port時,請使用8080以外的port,Ex. -p 18080:8080。

我希望在Tomcat docker把後端的war檔和dependency (我後端有使用到WordNet等…) 都先部署好,測試過後再壓成image或輸出成Dockerfile。部署的shell命令如下。部署前先準備好war檔和dependency (WordNet之類)…

#!bin/bash
docker run --name servrel -p 7778:8080 -d tomcat:7.0.57-jre8 
docker cp /home/app/servrel.war servrel:/usr/local/tomcat/webapps #war檔複製到docker
#Tomcat設定等位置,可以查閱https://hub.docker.com/_/tomcat/
docker cp /home/app/wordnet servrel:/usr/local/tomcat/ #資料夾複製到docker
docker exec -it servrel /bin/bash  #使用bash進入docker查看
docker restart servrel #重開

Tomcat部署簡單,以上幾行就輕鬆解決,之後我就都使用同一個container,此時也建議docker commit將這版的container壓成image,留下紀錄。

Jenkins要驅動的script解說

短短幾行就把學弟妹的前端部署到Tomcat docker,流程為: 將GitHub的專案更新到本機端–>將本機專案更新至Tomcat docker的前端資料夾–>重啟–>印出docker資訊。

cd ~/project/servrel/servrel-front-end
git pull  #將GitHub的前端資料pull下來,各位可能問為何不直接拿workspace的內容,因為權限問題無法取用自如,所以我乾脆另外git pull
docker cp ./. servrel:/usr/local/tomcat/webapps/servrel #用name當成container的編號並對其做操作
docker restart servrel
docker inspect --format='finish! Container:   -> Host:  ' servrel  #docker inspect取得docker資訊提供給部署者

Jenkins & Github plugin建立專案

設定遠端觸發建置有很多方法,但我們在設定時一定要考慮到Jenkins的安全性,所以我以下列出的是,在安全性為”矩陣型”的狀態下,設定trigger的解決方案:

  1. 基本驗證 (Basic Authentication) 方式通過 API 驗證
  2. Build Token Root Plugin 外掛避開遠端觸發建置的身分驗證要求
  3. 安裝 GitHub Plugin 直接支援 GitHub 服務整合

以上三種選項的詳細作法可以移步至本篇部落格了解,以下我只針對安裝 GitHub Plugin 直接支援 GitHub 服務整合做解說。

(1) 使用本整合服務請先安裝GitHub plugin,一般在安裝Jenkins的時候就能先行點選安裝,安裝完要重啟Server。

(2) 進入 [管理 Jenkins] / [設定系統]

(3) 找到 GitHub Plugin Configuration,並新增一個 GitHub Server Config,千萬不要勾選 manage hook,GitHub整合服務 會自動幫我們管理,這個坑搞了我好久,詳見Jenkins GitHub Hooks Problems

jenkins
jenkins

完成後,按Apply和確定存檔。

(4) 至Jenkins左欄建立新作業 (Job),輸入新作業的名稱與類型,第一項的free-Style彈性較大。

jenkins
jenkins

(5) 設定作業

jenkins
jenkins
jenkins

完成後按Apply和確定儲存。

(6) 再來我們到要觸發的Github專案,到setting後點擊 webhooks&services

jenkins
jenkins

(7) 選擇Add service,找到Jenkins後點入,設定hook url,完成後還可以點選test service測試!

jenkins
jenkins

完成後,如果已經成功建立起trigger,我們可以看到如下畫面。

jenkins

我們可以點入任何一次建置,查看建置的過程是否符合我們預期。

jenkins

當然Jenkins的好用遠遠高於此,這只算是小試身手!等我嘗試更多功能後,再釋出給各位分享~


後續與補充

老師提議我要用MySQL取代SQLite,並架phpMyAdmin讓學妹方便更改資料庫的資料。我最近也想試試利用logstash,elsticsearch與kibana來分析log,就改成以下這種新架構。

jenkins

以上的MySQL, phpMyAdmin, logstash,elsticsearch與kibana全部都是Docker container,我用的是這個Docker ELK stack,並自己定義logstash的conf.d裡的grok,將log data轉換成各種資料欄位。elasticsearch是一個的資料搜尋引擎,它能夠以JSON的形式儲存資料,並且做即時的分析和搜尋。Kibana連接elasticsearch,把資料用圖表的方式呈現,方便開發者做監控。

完成後的監控畫面如下:

jenkins

提供我參考的ELK教學,說得非常詳細:Docker ELK Quickstart: Elasticsearch, Logstash, Kibana

[Javascript]非同步的救星Promise

本篇介紹Javascript的Asynchronous Coding,並說明Promise如何使用,和淺談Promise和Monad的關聯 Continue reading

[讀書心得]Rapid learner

Published on January 26, 2017