通過Docker容器運行持續集成/持續部署
對于docker主流的應用場景:持續集成和持續部署(CI/CD)大家也許并不陌生.這篇文章從獨特的視角闡述了如何利用各種云平臺構建屬于自己的CI/CD容器,筆者還自己擴展了Gitlab CI引擎,對CI感興趣的同學對這個文章應該很感興趣.
我曾經使用Docker了一段時間,在過去的一年里伴隨著眾多的Docker容器涌入,幫助用戶們更容易的部署Docker容器到生產環境中。一 些工具是第三方公司提供,當然也包括Docker公司自己的容器工具(例如:Docker Swarm, Docker Machine, 和 Docker Compose)。盡管如此,最近我在測試一種新的Docker工作流,它可以允許我推送代碼并測試, 構建項目,并且部署在生產環境下的Docker宿主機中。
接下來隆重介紹我的新工具 bar service, ThreeBar ①,一個可以在Heroku上運行持續集成/持續部署(CI/CD)系統。通常情況下,新開發的代碼部署到服務器遵循下面的流程:
- 創建一個本地組件
- 推送代碼到git倉庫的feature/development分支
- Shippable ,一個持續集成引擎,一旦檢測到有的提交(commit),通過pull獲取最新的代碼并且運行相關的測試
- 如果測試全都通過了等著被部署到生產環境中,就會創建一個合并(merge)分支的請求并且執行該合并(merge)
- Shippable 一旦檢測到有新的提交到遠程master分支,同時會執行測試,并且推送源碼到Heroku的git倉庫中
- Heroku 將會自動構建這個應用程序并且部署它。
這個工具真的可以方便、快捷的部署項目并且保證所有部署到生產環境的代碼都經過了測試而且是可靠的。
盡管如此,還是由一個問題,那就是大規模部署Heroku需要花費高昂的費用。選擇使用heroku,你將會獲得heroku提供的免費使用優惠 ②,一個標準的512內存的由heroku提供的Dyno容器只需要35$。公平的說,heroku提供的虛擬主機服務已經夠實惠了,但是一些應用的復雜 程度要求heroku提供更靈活的定制化需求,收取一定費用也無可厚非。
Docker,當然可以替代heroku,提供相應的代碼部署服務。但是上面談到的問題仍舊存在。當你的代碼需要部署的時候,頻繁手動啟動和關閉服務是得不償失的。讓我們來比較一下不同持續集成/持續部署引擎和docker相比有什么不同。
尋找解決方案
Docker并不是第一個也不是最后一個端到端的持續集成工作流解決方案。因此我們需要將眾多不同的技術組合到一起用來完成我們想要的功能。下面將會介紹三個主流的提供構建引擎的服務:一個CI/CD的測試運行引擎,一個web容器,一個容器適配器。
CI/CD 服務器,測試運行引擎
當我們選擇一個CI/CD服務,你必須確定他們必須支持Docker容器的構建。下面的這些服務都包含了這一功能:
當然還有一些其他的服務,包括大名鼎鼎的Jenkins CI server。這里你可以自己去搜索這些服務。一些服務在容器上運行構建,但是他們相互之間是完全獨立的。稍后你就會看到,你可以在Docker-in- Docker上運行服務,同時可以使用在Docker 容器中運行的其他服務。
在我的試驗中,我選擇了和Gitlab 版本管理服務器端同時運行GitLab CI 系統。通過Gitlab版本管理服務器,我可以很清楚的看到每次commit。選擇Gitlab不僅是因為他是一個免費的開源源碼 托管倉庫 和對托管在上面的項目提供的 持續部署引擎 ,同時也是一個通過安裝gitlab運行你自己的服務的開源軟件。
如果你選擇使用Gitlab CI System搭建你的持續集成框架,你必須提供屬于自己的測試運行服務。宿主機的持續集成軟件只能運行特定的測試服務,實際上它自己并不能自己執行測試任 務,通常都是啟動由本機提供相應的測試服務來執行的,你不光可以通過服務提供商啟動引擎或者你直接運行你本機上的服務(虛擬機VM或Docker容器).
服務器托管提供商
當然你同時也需要一個服務器托管提供商讓Docker守護進程可以在它之上運行。不幸的是,使用Docker意味著經常需要運行和管理自己的服務 器,也就是你將要負責這個主機的運維。但是,我想通過下面的內容說明,你可以在Docker運行一個高可用、多數據中心架構,這意味著即便是停機一個小時 也不會像以前那樣對業務影響那么巨大。
常用的服務器托管提供商包括下面的幾個③:
業務流程
即是你有了一套構建好了的Docker容器和能夠運行docker守護進程的服務器。你還是需要一個能夠被輕易啟動的容器并且能夠在構建一個新鏡像的時候能重復部署他們。正如我最近正在使用的名叫 Tutum 的業務流程服務。
目前, Tutum 是一個能幫助你管理你的容器部署工作流的服務形式。與此同時,你還能在各種云平臺上快速動態增加節點,創建新服務,通過一個私有的register來部署你的應用。
此外, Tutum 還為你的容器創建了一個私有網絡,意味著可以通過你的Tutum賬戶你的Docker容器擁有自己的私有固定IP地址并且通過路由來訪問其他容器。無論你 的物理機是否在同一個數據中心,還是通過世界各地的不同的服務器托管提供商。它都將允許你創建一個基于多服務器、多云平臺的彈性的解決方案。如果你之前見 過 Flannel by CoreOS , Tutum 的私有網絡和它差不多。
我一直在尋找類似上面談到的這種服務。就在前不久,我剛做了一個實驗:在多容器docker之間通過V*N創建一個P2P網絡。這是很久之前的docker網絡配置達不到的需求,但是現在 Tutum 做到了。
Tutum 同時也整合了CI/CD組件,并且支持git推送(push)。當Tutum 完成功能的時候,它可能成為唯一的你需要包含的到源碼倉庫中的其他服務。
Tutum 擁有我們需要進行CI/CD的幾個關鍵組件:
- 一個私有的為容器鏡像準備的注冊中心
- 當新的鏡像推送到注冊中心的時候重新部署容器
- 簡便的容器擴容(在界面視圖上,可以通過滑動N或M的方式調整容器大小)
- 在Tutum的界面上添加節點
其他我們值得關注的組件:
*在對一個web應用容器縮放后,基于自省的方式的DNS動態解析。舉個例子,你的haproxy路由會自動發現新增容器并且添加到路由列表中。
- 私有的網絡覆蓋
- 不再受不同云供應商的限制,創建自己的節點
給所有東西組裝到一起
下面就挑干貨說下我的實驗過程:
- 宿主機使用Gitlab搭建的源碼遠程倉庫
- 宿主機使用Gitlab CI搭建的CI/CD引擎
- RunAbove作為服務器提供商對所有CI/CD運行引擎的容器托管④
- Tutum 作為業務流程和服務的管理服務提供
當所有的事情結束,也組裝完畢,git的提交記錄活動圖,如下圖所示:

部署Tutum 代理
正因為如此,我們事實上是使用Tutum 去部署GitLab CI runners。我給你的建議是,先安裝Tutum agents。啟動所有你希望使用的服務,這樣在 Tutum 的儀表盤上就能看到Bring your own node字樣的按鈕。點擊它,你將會收到一個如下面所示的命令行:
curl -Ls https://get.tutum.co/ | sudo -H sh -s XXXXXXXXXXXXXXXXXXX通常在某一個節點運行上述命令自動添加到你的Tutum賬戶,與此同時進程也會自動添加到其他節點(每次當你點擊Bring your own node按鈕的時候)。
一旦Tutum agent 安裝到你的所有節點上,你將會在儀表盤上看到它. 在這一點上,你也許想給這個節點貼上適當的標簽. 允許對應的服務器在哪個節點上運行。舉個例子,你可能有一組節點標記為tag或production目的是為了創建一套環境,亦或者是用來做持續集成的一個節點標記,這些只能在宿主機上運行。
你可以通過點擊節點名稱來標記一個節點,添加的標記將會顯示在左側邊欄。
部署一個Gitlab CI 運行引擎
現在你可以通過Tutum 來部署一個Gitlab CI 運行引擎.然而,我們需要一種特殊類型的持續運行引擎-需要能夠在這個容器中運行Docker并且能夠構建我們自己的Docker鏡像.
你可能想,這怎么可能呢?假如我們使用Tutum運行Gitlab CI 引擎,它只能運行在容器里。那么問題來了,如何在Docker容器里運行Docker呢?
其實這完全可以做到。事實上,我們可以運行在你能想象到的更深層Docker中. 我們的Docker容器架構如下圖所示:

正如你所看到的,在我們的節點的Docker容器里Tutum運行GitLab CI引擎。此外,該GitLab CI引擎實際上使用Docker構建鏡像并運行測試,這意味著我們有兩個嵌套層次.
通過fork GitLab CI Runner,我已經建立了相應功能的分支.這樣就可以有效的跟蹤在 github 和官方Docker注冊中心的變更.
在建立你的GiLab CI runner前,確保你已經存在一個GitLab的實例倉庫,并且能夠同時運行GitLab CI 引擎.正如前面提到的,你可以建立自己的實例,或者直接使用gitlab官方提供的免費托管倉庫和持續部署服務.
一旦你注冊了gitlab倉庫。你所做的只需要通過點擊鏈接你的Gitlab CI 賬號.在你關聯了Gitlab CI賬號之后,你將會通過Gitlab的儀表盤看到你的gitlab倉庫列表,并且通過點擊"Add project to CI" 按鈕來添加你的項目到Gitlab CI 引擎中.點擊完畢后,你就會在gitlab的儀表盤上看到你新添加的項目信息了.如下圖所示:

如果你輕戳gitlab的用戶界面,你將會注意到一個菜單標題為"Runners".在這個頁面有一個注冊標記,同時還有如何創建一個新 的"Runner"的功能說明. 在下面的例子中,我將會使用Tutum部署我們的Gitlab CI 鏡像.確定你已經復制了注冊標記和Gitlab CI的url地址-一會你將會用到他們.
在你的Tutum界面上,創建一個新的服務.在Tutum中服務的概念是一個Docker容器組,他們使用相同的軟件并運行著相同配置.
每個服務可以有零個或者多個容器在同一時間運行,并且Tutum將會管理你所有節點的協調和縮放工作.
在啟動向導的第一個界面,你將會看到幾個標簽,讓你選擇不同來源的Docker鏡像源.Tutum擁有一個內置的,私有的注冊中心,通過搜索其他 注冊中心同時支持一些具有特定功能的鏡像,當然這里也包括Docker的官方鏡像.切換到"公共鏡像"選項卡,搜索"wizardapps/dind- gitlab-ci-runner"鏡像,這就是我前面描述的在github上fork的GitLab CI 引擎源碼倉庫中我自己建立的分支.
你一旦確定選擇了鏡像,你將會看到一個界面上面你對兩個容器之間調度的功能選項和一些基本配置。對于部署策略,雖然默認的設置也可以運行持續集 成,但是我建議還是通讀下Tutum官方的說明文檔。You also will likely want to leave the number of containers at 1 unless you wish to do parallel builds.如果你先前已經對部署在Tutum的節點打了對應的標簽,請確保在"Delpoy Tags"輸入框輸入了正確的標簽名稱.從本質上講,Tutum會努力尋找所有滿足你要求"Delpoy Tags" 中聲明的標簽,并且部署他們到一個節點.
下圖說明當你第一次必須要改動的一個重要的配置信息,這是在"Advanced Options"部分的"Privileged Mode"選項,Docker需要選中這個選項,這樣保證Tutum可以很容易的獲得該信息.

在配置好私有模式后,你將會看到下一個屏幕-有關環境變量配置信息.
像Docker命令行一樣,Tutum允許你聲明一個環境變量使之可以在你的Docker容器里使用.
不僅如此,在Tutum中,每一個部署的容器都可以使用這個環境變量.盡管我們不會再Gitlab CI 引擎上使用link功能,我們使用的是Tutum提供的動態link,容器依然允許使用其他容器中的環境變量.
下面是三種需要設置的重要的環境變量:
- REGISTRATION_TOKEN: 注冊信息就是之前我們在Gilab CI 中拷貝的"Runner".
- CI_SERVER_URL: 在Gitlab CI頁面上之前提供給我們的url地址.如果你使用的是官方提供的gitlab CI服務,直接填寫" https://ci.gitlab.com/".
- GITLAB_SERVER_FQDN:這里聲明的是gitlab 的域名,這是用來執行一個ssh-keyscan.如果你用的是官方的托管服務,請填寫 "ci.gitlab.com".
在配置完這些變量之后,終于可以"創建并部署"我們的服務了.
一旦你的容器啟動完畢, 你可以返回GitLab CI的 "Runners" 頁面并且你看到一個新的入口. 現在你可以著手準備建立 GitLab CI 任務吧.
創建一個GitLab CI 任務
終于到最后一步了,我們在Gitlab CI 上添加一個實際的腳本目的是建立一個 持續集成/持續部署的工作流.現在,這將取決于你的實際項目的種類,但大體方向應該是相同的,你會使用Docker鏡像來構建Docker容器,然后上傳 到你的鏡像庫.在這種情況下,將會上傳到Tutum提供的私有鏡像庫.
在"工作"選項卡中,Gitlab CI工作可以進行修改.在這個部分,有兩個不同的子選項-"test"和"deploy".正如他們名字所暗示的,測試腳本通常用來運行單元和集成測試. 部署腳本只運行一旦測試完成后的特定分支.這樣就可以允許你在每次提交(commit)后運行你的測試腳本,與此同時部署腳本當且僅當所有測試全部通過的 時候部署遠程master分支.
下面是腳本實例:
```
docker login-u[USERNAME]-e[EMAIL]-p="[PASSWORD]"tutum.co
Build the Docker image and tag it for Tutum
docker build-twizardapps/app.
docker tag-fwizardapps/app tutum.co/wizardapps/app:latest
```
上面的測試腳本并沒有實際運行任何測試,但是他確能為我們的應用程序構建Docker鏡像并打上對應的標簽.如果你在初始化階段使用自己的腳本, 請確保你的用戶名,郵箱,密碼和Tutum上的注冊信息報紙一致.因為Tutum提供的是一個私有Docker注冊中心,確保你的測試腳本能通過相應的校 驗⑤.
然后,我們還可以創建一個部署腳本,實際上是推送我們的鏡像到Tutum的注冊中心,并開始構建.
docker push tutum.co/wizardapps/app自動部署
到了這一步,你的系統應該已經構建成功并運行,新代碼應該可以持續集成并上傳到Tutum的注冊中心.剩下的工作就是在Tutum上創建你自己的服務,確保重啟后還可以繼續使用.
這和我們創建Gitlab CI 服務類似,所不同的是我們讓服務"私有化",我們只需要打開"Auto Redeploy"開關即可.配置所有的服務端口,環境變量,鏈接和卷標,然后點擊一下部署即可.
恭喜你,你現在已經擁有了只有在經過測試后,可以快速進行持續部署,自動化部署的Docker 應用程序.
其他資源
GitLab CI Multi-Runner 地址: https://github.com/ayufan/gitlab-ci-multi-runner
我們通過在Tutum里建立每個項目上都需要的持續集成 "服務",可以很快上手.作為一種替代方案,你可以嘗試使用GitLab CI Multi-Runner,這個項目通過一個配置文件允許多個項目同時進行構建。
①. 我有一些很酷的東西和大家分享,這就是ThreeBar-一個遠遠超出你想象的工具.一旦你做好準備加入,你將會發現Docker持續-部署-應用的強大功能。
②. Heroku 運營模式,您只需要按小時支付使用費.每一個"虛擬機"運行你的代碼被稱之為"Dyno",你可以僅僅通過運行一個命令就可以做到一鍵部署,例如web服 務器或者其他請求隊列服務.你將會每個月獲得750小時的"Dyno"免費使用權.這意味著如果你愿意的話可以在Heroku上運行一個免費的web服務 器.
③. 我個人使用了以下所有的服務器提供商,我也通過博客鏈接點擊獲得了一些收入.但是,很可惜,任何一個服務器提供商都不會允許你在創建你自己Docker服務并運行在Linux實例上.
④. RunAbove的沙箱是一個偉大的實驗,因為在它上面有大量的RAM,SSD存儲,并且花費極低-每月只有3美金在一個2G內存的服務器上.盡管如此,在那個時候他們不被SAL所接受,因此你只能選擇其他的服務提供商.
⑤. 此時此刻,你必須把你的Tutum的賬號和密碼直接扔到腳本中.很不幸的是,Tutum不提供這樣的單獨密碼注冊表API,所以這個方案也因此留下一個潛在的安全漏洞.