持續集成軟件包括兩個部分java
經過部署本身私有的Docker鏡像registry,並創建本身的自動化構建,將Docker集成到持續集成工做流中。
除了持續集成和持續部署以外的自動化測試部分,只須要從Jenkins創建一個hook來啓動自動化腳本並生成測試報告。
關於本節須要作到git
經過Jenkins系統的Job觸發機制,咱們能夠方便的建立各類類型的集成Job用例。但缺少統一標準的Job用例使用方法,會致使項目Job用例使用的混亂,難於管理維護。這也讓開發團隊沒法充分利用好集成系統的優點,固然這也不是咱們指望的結果。因此,敏捷實踐方法提出了一個能夠持續交付的概念 DeploymentPipeline(管道部署)。經過Docker技術,咱們能夠很方便的理解並實施這個方法。
Jenkins的管道部署把部署的流程形象化成爲一個長長的管道,每間隔一小段會有一個節點,也就是Job,完成這個Job工做後才能夠進入下一個環節。形式以下: 正則表達式
開發同窗經過git push上傳代碼,經Git和Jenkins配合,自動完成程序部署、發佈,全程無需運維人員參與。
這是一種真正的容器級的實現,這個帶來的好處,不只僅是效率的提高,更是一種變革:
難者不會,會者不難。經過簡單的4個配置,便可優雅地實現持續部署。docker
在本例中,假設咱們JAVA項目的名稱爲hello。簡要的技術思路以下。 數據庫
本案例中假設代碼託管在git.oschina.com上,Jenkins和Docker Registry(相似於yum源)各運行在一個Docker容器中。JAVA項目本身也單獨運行在一個叫hello的容器中。
本文采起的持續部署方案,是從私有的Docker Reistry拉取代碼。有些變通的方案,把代碼放在宿主機上,讓容器經過卷組映射來讀取。這種方法不建議的緣由是,將代碼拆分出容器,這違背了Docker的集裝箱原則:
這也致使裝卸複雜度增長。從貨運工人角度考慮,總體纔是最經濟的。這樣,也才能實現真正意義的容器級遷移。
或者說,容器時代,拋棄過去文件分發的思想,纔是正途。本文最後的問答環節對此有更多闡述。
容器即進程。咱們採用上述方案作Docker持續部署的緣由和意義,也在於此。容器的生命週期,應該遠遠短於虛擬機,容器出現問題,應該是當即殺掉,而不是試圖恢復。安全
本文最後實現的效果,究竟有多驚豔呢?且看以下的演示。服務器
咱們以時間戳來簡潔、顯式的表述程序更新狀況。 網絡
本例中,咱們把首頁的時間戳從201506181750,修改成201506191410(見以下)。 app
順序執行以下操做,輸入正確的git帳號密碼。 運維
而後呢?
而後什麼都不用作了。端杯茶(若是不喜歡咖啡的話),靜靜地等待自動部署的發生, 旁觀一系列被自動觸發的過程,機器人似的運轉起來(請容稍候再加以描述)。
爲何須要3~5分鐘?只是由於本案例中的JAVA項目,須要從國外download Maven程序包,以供Jenkins調用和編譯JAVA。正式應用環境中,能夠把Maven源放在國內或機房。若是僅僅須要對PHP項目作持續部署,那就更快捷了。
在靜靜地等待幾分鐘後,新的代碼確實已經自動部署完畢。
那麼,這一切怎麼實現的呢?要按照以下幾步,即可快速實現。
這個過程也是難者不會,會者不難。主要分爲以下三步。
Jenkins中新建項目java-app,並配置從Git拉取程序代碼。具體以下:
Jenkins中配置token,以供git遠程調用時使用。
怎麼讓Git在接收到用戶更新的代碼後,把消息和任務傳遞給Jenkins呢?這藉助於Git的hook功能,配置起來也很是簡單,以下。
Jekins在接收到Git傳遞過來的消息後,再觸發一個遠程構建(到目標服務器),按照預約義的任務列表,執行一系列的工做,重建容器等。詳見以下:
咱們把其中最關鍵的Shell腳本內容摘抄出來。
在2.3這個章節中,咱們當時的操做以下,這個目的是向Git提交更新代碼。
當時並無細說後續發生的事情,既然上面已經說清楚了原理,那咱們就能夠接下來講說實際發生的事情啦。
這裏貌似整個過程已經完成並順利退出。其實,後臺的工做纔剛剛開始。
這時會觸發Git服務器向相應的Jenkins服務器發出一個操做請求,此工做太過迅速,也沒啥好說的,咱們接下來看Jenkins都幹啥子了。
Jenkins會自動冒出來一個構建任務。
咱們點進來,看看具體操做日誌。是的,正在接受來自Git的任務。
下載Maven相關的軟件包(就是這個過程慢)。
下載完成後,就開始利用maven BUILD 新的hello項目包。
而後重建Maven容器,構建新的Image並Push到Docker私有庫中。
最後,從新把Docker容器run起來。這樣,又新生了。
問題1:採用這麼相對複雜的辦法(而不是把更新代碼放在宿主機而後卷組映射),是由於項目基於JAVA麼;是否PHP項目就能夠採用更新代碼放在宿主機而後卷組映射這種方式?
回答1:將代碼拆分出容器,違背了集裝箱原則。致使裝卸複雜度增長。從貨運工人角度考慮,總體纔是最經濟的。一切版本化。拋棄過去的文件分發。這是正途。至於文件大小,大的war包也就50M或100M,在現有網絡下不成問題,性能問題最好優化。另外建議關注docker 2 docker,p2p傳輸。
問題2:若是總體代碼超過500m或者1g以上,總體集裝箱是否就不太好了?若是容器與代碼分離,鏡像就100m左右(2層,base+服務),而後代碼的話,是放到共享存儲裏,每一個代碼有更新,好比svn的代碼,能夠直接在共享存儲裏進行svn update就能夠控制版本
回答2:若是你的代碼500M,說明就須要精簡了。
根據項目需求,現要在團隊內部搭建一個統一的打包平臺,實現對iOS和Android項目的打包。並且爲了方便團隊內部的測試包分發,但願在打包完成後能生成一個二維碼,體驗用戶(產品、運營、測試等人員)經過手機掃描二維碼後就能直接安裝測試包。
該需求具備必定的廣泛性,基本上全部開發APP的團隊均可能會用到,所以我將整個需求實現的過程整理後造成此文,而且真正地作到了零基礎上手,到手即飛、開箱即用,但願能對你們有所幫助。
首先,先給你們展現下平臺建設完成後的總體效果: 該平臺主要實現的功能有3點:
Jenkins依賴於Java運行環境,所以須要首先安裝Java。
安裝Jenkins的方式有多種,能夠運行對應系統類型的安裝包,能夠經過docker獲取鏡像,也能夠直接運行war包。
我我的傾向於直接運行war包的形式,只需下載jenkins.war後,運行以下命令便可啓動Jenkins。
$ nohup java -jar jenkins_located_path/jenkins.war --httpPort=88 &
若是不指定httpPort,Jenkins的默認端口爲8080。
Jenkins有很是多的插件,能夠實現各類功能的擴展。
針對搭建的iOS/Android持續集成打包平臺,我使用到了以下幾個插件。
在Jenkins中,構建項目以Job的形式存在,所以須要針對每一個項目建立一個Job。有時候,一個項目中可能有多個分支同時在進行開發,爲了分別進行構建,也能夠針對每一個分支建立一個Job。
建立Job的方式有多種,本次只須要建立Freestyle project類型的便可。
Main page -> New Item -> Freestyle project
對於一個持續集成打包平臺,每次打包都由4步組成:觸發構建、拉取代碼、執行構建、構建後處理。對應的,在每一個Job中也對應了這幾項的配置。
要對項目進行構建,配置項目的代碼倉庫是必不可少的。因爲當前咱們的項目託管在GitHub私有倉庫中,所以在此須要對Git進行配置。
在【Source Code Management】配置欄目下,若是以前GIT plugin安裝成功,則會出現Git選項。
配置Git代碼倉庫時,有三項是必須配置的:倉庫URL地址(Repository URL)、倉庫權限校驗方式(Credentials),以及當前Job須要構建的代碼分支(Branches to build)。
在配置Repository URL時,選擇HTTPS URL或SSH URL都可。不過須要注意的是,Credentials要和Repository URL對應,也就是說:
代碼倉庫配置好了,意味着Jenkins具備了訪問GitHub代碼倉庫的權限,能夠成功地拉取代碼。
那Jenkins何時執行構建呢?
這就須要配置構建觸發策略,即構建觸發器,配置項位於【Build Triggers】欄目。
觸發器支持多種類型,經常使用的有:
觸發策略配置好以後,Jenkins就會按照設定的策略自動執行構建。但如何執行構建操做,這還須要咱們經過配置構建方式來進行設定。
經常使用的構建方式是根據構建對象的具體類型,安裝對應的插件,而後採用相應的構建方式。例如,如果構建Android應用,安裝Gradle plugin以後,就能夠選擇Invoke Gradle script,而後採用Gradle進行構建;如果構建iOS應用,安裝Xcode integration插件以後,就能夠選擇Xcode,而後選擇Xcode進行構建。
該種方式的優點是操做簡單,UI可視化,在場景不復雜的狀況下能夠快速知足需求。不過缺點就是依賴於插件已有的功能,若是場景較複雜時可能單個插件還沒法知足需求,須要再安裝其它插件。並且,有些插件可能還存在一些問題,例如對某些操做系統版本或XCode版本兼容不佳,出現問題時咱們就會比較被動。
我我的更傾向於另一種方式,就是本身編寫打包腳本,在腳本中自定義實現全部的構建功能,而後在Execute Shell中執行。這種方式的靈活度更高,各類場景的構建需求都能知足,出現問題後也能自行快速修復。
另外,對於iOS應用的構建,還有一個須要額外關注的點,就是開發者證書的配置。
若是是採用Xcode integration插件進行構建,配置會比較複雜,須要在Jenkins中導入開發證書,並填寫多個配置項。不過,若是是採用打包腳本進行構建的話,狀況就會簡單許多。只要在Jenkins所運行的計算機中安裝好開發者證書,打包命令在Shell中能正常工做,那麼在Jenkins中執行打包腳本也不會有什麼問題。
完成構建後,生成的編譯成果物(ipa/apk)會位於指定的目錄中。可是,若是要直接在手機中安裝ipa/apk文件還比較麻煩,不只在分發測試包時須要將好幾十兆的安裝包進行傳送,體驗用戶在安裝時也還須要經過數據線將手機與計算機進行鏈接,而後再使用PP助手或豌豆莢等工具進行安裝。
當前比較優雅的一種方式是藉助蒲公英(pgyer)或http://fir.im等平臺,將ipa/apk文件上傳至平臺後由平臺生成二維碼,而後只須要對二維碼連接進行分發,體驗用戶經過手機掃描二維碼後便可實現快速安裝,效率獲得了極大的提高。
無論是蒲公英仍是http://fir.im,都有對應的Jenkins插件,安裝插件後能夠在Post-build中實現對安裝包的上傳。
除了使用Jenkins插件,http://fir.im還支持命令上傳的方式,蒲公英還支持HTTP Post接口上傳的方式。
我我的推薦採用命令或接口上傳的方法,並在構建腳本中進行調用。靈活是一方面,更大的好處是若是上傳失敗後還能進行重試,這在網絡環境不是很穩定的狀況下極其必要。
Jenkins成功完成安裝包上傳後,pgyer/http://fir.im平臺會生成一個二維碼圖片,並在響應中將圖片的URL連接地址進行返回。
二維碼圖片的URL連接有了,那要怎樣才能將二維碼圖片展現在Jenkins項目的歷史構建列表中呢?
這裏須要用到另一個插件,description setter plugin。安裝該插件後,在【Post-build Actions】欄目中會多出description setter功能,能夠實現構建完成後設置當次build的描述信息。這個描述信息不只會顯示在build頁面中,同時也會顯示在歷史構建列表中。
有了這個前提,要將二維碼圖片展現在歷史構建列表中貌似就能夠實現了,能直觀想到的方式就是採用HTML的img標籤,將寫入到build描述信息中。
這個方法的思路是正確的,不過這麼作之後並不會實現咱們預期的效果。
這是由於Jenkins出於安全的考慮,全部描述信息的Markup Formatter默認都是採用Plain text模式,在這種模式下是不會對build描述信息中的HTML編碼進行解析的。
要改變也很容易,Manage Jenkins -> Configure Global Security,將Markup Formatter的設置更改成Safe HTML便可。
更改配置後,咱們就能夠在build描述信息中採用HTML的img標籤插入圖片了。
另外還須要補充一個點。若是是使用蒲公英(pyger)平臺,會發現每次上傳安裝包後返回的二維碼圖片是一個短連接,神奇的是這個短鏈接竟然是固定的(對同一個帳號而言)。這個短鏈接老是指向最近生成的二維碼圖片,可是對於二維碼圖片的惟一URL地址,平臺並無在響應中進行返回。在這種狀況下,咱們每次構建完成後保存二維碼圖片的URL連接就沒有意義了。
應對的作法是,每次上傳完安裝包後,經過返回的二維碼圖片短連接將二維碼圖片下載並保存到本地,而後在build描述信息中引用該圖片的Jenkins地址便可。
每次完成構建後,編譯生成的文件較多,可是並非全部的文件都是咱們須要的。 一般狀況下,咱們可能只須要其中的部分文件,例如.ipa/.app/.plist/.apk等,這時咱們能夠將這部分文件單獨收集起來,並在構建頁面中展現出來,以便在須要時進行下載。 要實現這樣一個功能,須要在【Post-build Actions】欄目中新增Archive the artifacts,而後在Files to archive中經過正則表達式指定成果物文件的路徑。 設置完畢後,每次構建完成後,Jenkins會在Console Output中採用設定的正則表達式進行搜索匹配,若是能成功匹配到文件,則會將文件收集起來。