在本系列文章中,咱們將探討在容器時代如何在基於Docker的環境中建立連貫的工做流程和流水線來簡化大規模項目的部署。另外,咱們還將詳細介紹如何利用Docker和Rancher自動化處理這些工做流。git
在上文《將構建環境容器化》中,咱們開始了構建持續集成流水線的第一步工做——構建系統(Build System)的建立。咱們分析了【Build】這一環節的常見的三大挑戰——依賴管理、管理環境依賴、複雜項目的漫長構建時間,以及如何用傳統工具與方法解決這些問題。接着,咱們分享瞭如何利用Docker建立容器化的構建系統以更輕鬆地解決那些傳統挑戰,包括如何將構建環境容器化、如何使用Docker打包應用程序、如何使用Docker Compose建立構建環境,最終創造一個可重複的、集中管理的、良好隔離的、並行化的構建系統。github
如今咱們已經將【Build】系統建立好了,那麼在本文中,咱們將爲示例的應用建立一個持續集成流水線。這樣咱們既能夠確保遵循最佳實踐,又能夠確保彼此衝突的那些變化不會相互做用、引起問題。不過,在咱們爲代碼創建持續集成以前,咱們先花一點時間討論如何將代碼劃分到分支中。docker
分支模式shell
在咱們實現持續集成流水線的自動化時,一個須要考慮的重點是團隊遵循的開發模式。這個模式一般由團隊如何使用版本控制系統來決定。因爲咱們的應用程序託管在git倉庫中,所以咱們使用git-flow模型進行分支、版本化以及發佈咱們的應用程序。它是基於git倉庫上最經常使用的模型之一。簡而言之,該模型的思想是維護兩個分支:一個開發(者)分支,一個主分支。每當咱們想開發新功能時,就會從開發分支建立出新的分支,並在功能開發完成時,將它合併回來。全部功能分支都有開發人員單獨管理。一旦將代碼提交到開發分支,CI服務器將負責確保分支始終可以編譯、經過自動化測試而且能夠在服務器上進行QA測試和評審。當咱們準備進行發佈時,能夠從開發分支建立一個發佈,並將其合併到主分支中。被髮布的特定的commit hash也會使用版本號進行標記。被標記好的發佈項接着就能夠被推送到Staging/Beta或者生產環境中。數據庫
下面咱們將使用git-flow工具來幫助管理咱們的git分支。安裝git-flow請參考這裏的說明:https://github.com/nvie/gitflow/wiki/Installation。安裝好git-flow,你就能夠經過下面所示的git flow init命令配置你的倉庫。Git flow會問一些問題,咱們建議你使用默認的設置便可。執行過git-flow命令後,它將建立一個開發分支(若是原先沒有開發分支的話),並將其檢出做爲工做分支。服務器
如今,咱們使用git flow輸入git flow feature start [feature-name]命令建立一個新功能。一般作法是用ticket/issue id用做功能的名稱。好比,若是你使用的是Jira處理ticket,那麼ticket id(例如,MSP-123)就能夠做爲功能名稱。你還會發現當你使用git-flow建立新功能時,它將自動切換到功能分支。curl
到了這一步,你能夠去完成該功能所需的所有內容,而後運行自動化測試套件以確保一切正常運轉。一旦你準備好發佈工做,只需告訴git-flow去完成這一功能便可。根據你對該功能的實際須要,你想要進行多少次提交均可以。在個人這個示例中,從咱們的目的來看,咱們只需更新README文件,並經過輸入「git flow feature finish MSP-123」來完成更新。工具
須要注意的是,git flow合併了開發分支的功能,刪除了功能分支而且返回到了開發分支。此時,你能夠將開發分支推送到遠程倉庫(git push origin develop:develop)。 當你提交了開發分支,CI服務器就會接管持續集成流水線。對於更大的團隊來講,一種更合適的模式是在完成功能以前將功能分支推送到遠程,讓它們經評審(review)後,使用pull request來合併到開發分支中。post
使用Jenkins建立CI流水線單元測試
在這一節,咱們假設你已啓動並運行了一個Jenkins集羣。若是沒有的話,你能夠在這裏使用官方的Jenkins鏡像:https://hub.docker.com/_/jenkins/ ,在這裏能夠看到更多關於創建可擴展Jenkins集羣的內容:https://rancher.com/deploying-a-scalable-jenkins-cluster-with-docker-and-rancher/ 。在你有了運行的Jenkins集羣后,咱們須要在Jenkins服務器上安裝下面的插件和依賴項:
Jenkins Plugins 2.32.2+
Git Parameter Plugin 0.8.0+
Parameterized Trigger Plugin 2.33+
Copy Artifact Plugin 1.38.1+
Build Pipeline Plugin 1.5.6+
Mask Passwords Plugin 2.9+
Docker 1.13.1+
Docker Compose 1.11.1+
安裝好須要的插件後,咱們就能夠在【Build流水線】中建立最初的三個任務:編譯、打包和集成測試。這些將做爲咱們持續集成和部署系統的起點。
構建應用
序列中的第一個任務將會在每次提交後從源碼控制中檢出最新的代碼而且確保其可編譯。它還會運行單元測試。若是要在咱們的示例項目中設置第一個任務,選擇New Item->Freestyle Project。進入項目配置視圖中,選擇General選項卡以及「The project is parameterized」選項。添加一個叫作GO_AUTH_VERSION的git參數,將參數類型設置爲Branch(分支)或者Tag(標記)。接下來選擇Advanced配置參數,使用Tag Filter設置獲取匹配「v」的全部標記(好比v2.0)。將Default Value設置成develop(開發分支)。這將有助於從Git獲取版本標籤列表,併爲該任務填充選項菜單。若是該任務要在沒有給定值的狀況下自動觸發,那麼GO_AUTH_VERSION默認設成develop(開發)分支。
接下來,在Source Code Management選項卡部分添加倉庫url,指定分支爲${GO_AUTH_VERSION},這樣手動構建時將會使用git參數來選擇分支或標記進行構建及設置輪詢間隔。這樣一來,Jenkins就會持續追蹤咱們開發分支的將來全部更改,在咱們的CI(和CD)流水線中自動觸發第一個任務。這裏要注意的是,GO_AUTH_VERSION的默認值(好比開發分支)將用於自動檢測到的更改。
如今在Build選項卡部分選擇Add Build Step > Execute Shell並從本章前面部分複製docker run命令粘貼到這。這樣能夠從Github得到最新的代碼,並將代碼構建到go-auth可執行文件中。這裏須要安裝並運行docker。若是你使用的是Linux服務器,可能還須要在docker客戶機命令中添加sudo以便可以訪問docker守護進程。
在構建步驟以後,咱們須要添加兩個後續步驟,其中Archive the Artifacts(工件歸檔)將go-auth二進制文件和幫助腳本歸檔到項目中。咱們在任務中須要指定下列的工件進行歸檔。
接着咱們使用Trigger parameterized builds(觸發器參數化構建)啓動流水線中的下一個任務,以下圖所示。在添加Trigger parameterized build時,請確保是從Add Parameters中添加的Current build parameters。這樣可讓當前任務的所有參數(好比GO_AUTH_VERSION)用於下一個任務。請留意在Trigger parameterized build部分中用於下游任務的參數名稱,咱們將在下面的步驟中用到。
構建任務的日誌輸出應該像下面展現的這樣。你能夠看到咱們使用了docker化的容器來執行構建。構建時將使用go fmt來修復代碼中任何格式的不一致,而且執行咱們的單元測試。若是出現測試失敗或者編譯不經過,Jenkins就會檢測到失敗。此外,你應該經過email或者chat integrations(例如Hipchat或者Slack)設置通知,這樣在構建失敗時就能通知到你的團隊,快速地修復它。
打包應用
代碼編譯經過了,接下來咱們就能將它打包進Docker容器中。建立打包任務的方式是,選擇New Item > Freestyle Project並給你的第二個任務起一個名稱,該名稱對應於在先前任務中指定的內容。和以前同樣,該任務也是一個帶有GO_AUTH_VERSION參數的參數化構建。要注意的是,這裏和全部後續的任務中,GO_AUTH_VERSION只是一個默認值爲develop(開發分支)的string參數。咱們但願它的值是從上游傳過來的。
和以前同樣,添加構建步驟來執行shell。注意這裏你不須要指定SCM設置,由於咱們將從前一個構建生成的工件中提取所需的二進制文件和腳本。注意一下,咱們這裏是先建立未標記的usman/go-auth,以後再從新標記,這樣咱們就能夠在後面執行集成測試,搭建好未打標記的容器環境。
爲了構建Docker容器,咱們還須要前一步中構建的可執行文件。爲此,咱們增長一個構建步驟複製上游構建中的工件。這樣能夠保證咱們有可用於Docker構建命令的可執行文件,該命令能夠打包到Docker容器中。注意這裏咱們選擇了flatten目錄來保證全部工件都複製到當前項目的根目錄中。
咱們一直在使用GO_AUTH_VERSION變量標記咱們正在構建的鏡像。在默認狀況下,開發分支的變動,總會構建usman/go-auth:develop並覆蓋現有的鏡像。在下一章中,咱們會發布應用程序的新版本並從新審視這個流水線。
和以前相同,使用了Trigger parameterized builds下(包含了Current build parameters)的後構建(post-build)來觸發流水線中的下一個任務,該任務將使用咱們剛剛構建好的Docker容器以及在以前章節中詳述的Docker Compose來執行集成測試。
執行集成測試
接下來是執行集成測試,先要建立一個新任務。和打包任務相同,新任務是一個使用GO_AUTH_VERSION string變量的參數化構建。而後從構建任務中複製工件。這一次咱們將使用上面的Docker Compose模板來搭建一個多容器測試環境,並對咱們的代碼執行集成測試。集成測試(不一樣於單元測試)一般是與正在測試的代碼徹底隔離的。所以,咱們會用到一個shell腳本,它能夠針對咱們的測試環境執行http查詢。在執行shell命令中,將目錄修改成go-auth並執行integrationtest.sh。
腳本的內容能夠在這裏找到:https://github.com/usmanismail/go-messenger/blob/master/go-auth/integration-test.sh。咱們用Docker Compose搭建咱們的環境,而後使用curl發送http請求到搭建的容器中。這項任務的日誌將會和下圖顯示的類似。Compose將會啓動一個數據庫容器,並將它鏈接到goauth容器。數據庫鏈接以後你應該會看到一些列「Pass: …」信息,說明各項測試都在運行和驗證。測試完成後,compose模板將會自行清理數據庫和go-auth容器。
通過了三個任務的設置,你就能夠在Jenkins視圖中選擇【+選項卡】,選擇build pipeline view來建立一個新的構建流水線視圖。在彈出的配置界面中,選擇你編譯/構建的任務做爲初始任務,而後選擇ok。如今你應該能看到CI流水線已經成型。這將給你一個可視化引導,展現每一個提交是如何經過你的構建和部署流水線的。
當你更改開發分支時,你會注意到流水線是由Jenkins自動觸發的。若是要手動觸發流水線,選擇你第一個(構建)任務,運行它。系統會要求你選擇git參數的值(好比GO_AUTH_VERSION)。不指定的話會執行默認值,而且會運行鍼對開發分支中最新內容的CI流水線。固然,你能夠直接在流水線視圖中單擊「Run」。
咱們快速回顧一下到如今爲止咱們所作的工做。咱們經過如下步驟爲咱們的應用程序建立了CI流水線:
使用git-flow添加新功能,並將他們合併到開發分支中。
跟蹤開發分支的變化,在一個容器化環境中構建咱們的應用程序
將咱們的應用程序打包到docker容器中
使用Docker Compose搭建短生命週期環境
執行集成測試以及清理環境
經過上面的CI流水線,每當新功能(或者修復)合併到開發分支時,CI流水線就會執行上述全部的步驟,建立出「usman/go-auth:develop」 Docker鏡像。此外,咱們在接下來的章節中將構建更深層的集成部署流水線。另外由於該視圖有清晰的測試階段,你還可使用此視圖將應用程序版本推廣到各類部署環境中。
總 結
在本章中,咱們分享瞭如何利用Docker爲咱們的項目建立一個持續集成流水線,該流水線是集中管理的、可測試的,而且在機器和時間上可重複。咱們可以根據須要對各類組件的環境依賴進行隔離。這是咱們將來部署一條更長的基於Docker構建和部署的流水線的起點,咱們將在下一次的文章中繼續構建這一流水線的餘下部分並將過程經驗記錄下來。
咱們流水線的下一步是建立持續部署,後續文章咱們將展現如何使用Rancher部署整個服務器環境來運行代碼,咱們還將介紹如何爲大型項目設置長期運行的測試環境和持續部署流水線的最佳實踐。