最佳實戰Docker持續集成圖文詳解

前言

關於Docker的文章鋪天蓋地,但精品文章每每翻譯居多。都說Docker天生適合持續集成/持續部署,但一樣,可落地、實際可操做性的文章也很罕見。java

基於這些狀況,雖然咱們專欄定位爲運維管理性文字,但本篇是個特例,實操性的案例講解——JAVA項目如何經過Docker實現持續部署(只需簡單四步),即:git

  • 開發同窗經過git push上傳代碼,經Git和Jenkins配合,自動完成程序部署、發佈,全程無需運維人員參與。docker

這是一種真正的容器級的實現,這個帶來的好處,不只僅是效率的提高,更是一種變革:服務器

  • 開發人員第一次真正爲本身的代碼負責——終於能夠跳過運維和測試部門,自主維護運行環境(首先是測試/開發環境)。網絡

本文是cSphere Docker實戰視頻第二講的文字版,關於更多系列視頻,詳見希雲(https://csphere.cn/training)app

福利:點擊文末的「實戰視頻」便可手機欣賞本文對應的實戰視頻哦。運維

難者不會,會者不難。經過簡單的4個配置,便可優雅地實現持續部署。本文依慣例放上目錄,請享用。maven

  1. 持續部署的技術思路svn

  2. 效果展現性能

  3. 配置Git和Jenkins聯動

  4. 配置Jenkins自動更新代碼

  5. 效果圖文詳解

  6. FAQ

好吧,咱們正式開始。

1. 持續部署的技術思路

在本例中,假設咱們JAVA項目的名稱爲hello。簡要的技術思路以下。

本案例中假設代碼託管在git.oschina.com上,Jenkins和Docker Registry(相似於yum源)各運行在一個Docker容器中。JAVA項目本身也單獨運行在一個叫hello的容器中。

本文采起的持續部署方案,是從私有的Docker Reistry拉取代碼。有些變通的方案,把代碼放在宿主機上,讓容器經過卷組映射來讀取。這種方法不建議的緣由是,將代碼拆分出容器,這違背了Docker的集裝箱原則:

這也致使裝卸複雜度增長。從貨運工人角度考慮,總體纔是最經濟的。這樣,也才能實現真正意義的容器級遷移。

或者說,容器時代,拋棄過去文件分發的思想,纔是正途。本文最後的問環節對此有更多闡述。

容器即進程。咱們採用上述方案作Docker持續部署的緣由和意義,也在於此。容器的生命週期,應該遠遠短於虛擬機,容器出現問題,應該是當即殺掉,而不是試圖恢復。

2. 效果展現

本文最後實現的效果,究竟有多驚豔呢?且看以下的演示。

2.1 程序代碼更新前的效果

咱們以時間戳來簡潔、顯式的表述程序更新狀況。

2.2 提交程序代碼更新

本例中,咱們把首頁的時間戳從201506181750,修改成201506191410(見以下)。

2.3 上傳新代碼到Git

順序執行以下操做,輸入正確的git帳號密碼。

而後呢?

而後什麼都不用作了。端杯茶(若是不喜歡咖啡的話),靜靜地等待自動部署的發生, 旁觀一系列被自動觸發的過程,機器人似的運轉起來(請容稍候再加以描述)。

爲何須要3~5分鐘?只是由於本案例中的JAVA項目,須要從國外download Maven程序包,以供Jenkins調用和編譯JAVA。正式應用環境中,能夠把Maven源放在國內或機房。若是僅僅須要對PHP項目作持續部署,那就更快捷了。

2.4 查看代碼更新後的效果

在靜靜地等待幾分鐘後,新的代碼確實已經自動部署完畢。

那麼,這一切怎麼實現的呢?很複雜麼?否則。只要按照以下幾步,即可快速實現哦。

3. 配置Git和Jenkins聯動

這個過程也是難者不會,會者不難。主要分爲以下三步。

3.1 Jenkins配置Git源

Jenkins中新建項目java-app,並配置從Git拉取程序代碼。具體以下:

3.2 Jenkins配置遠程構建

Jenkins中配置token,以供git遠程調用時使用。

3.3 Git開啓鉤子

怎麼讓Git在接收到用戶更新的代碼後,把消息和任務傳遞給Jenkins呢?這藉助於Git的hook功能,配置起來也很是簡單,以下。

4. 配置Jenkins自動更新代碼

Jekins在接收到Git傳遞過來的消息後,再觸發一個遠程構建(到目標服務器),按照預約義的任務列表,執行一系列的工做,重建容器等。詳見以下:

咱們把其中最關鍵的Shell腳本內容摘抄出來。

5. 效果圖文詳解

在2.3這個章節中,咱們當時的操做以下,這個目的是向Git提交更新代碼。

當時並無細說後續發生的事情,既然上面已經說清楚了原理,那咱們就能夠接下來講說實際發生的事情啦。

5.1 上傳代碼到Git

這裏貌似整個過程已經完成並順利退出。其實,後臺的工做纔剛剛開始哦。

這時會觸發Git服務器向相應的Jenkins服務器發出一個操做請求,此工做太過迅速,也沒啥好說的,咱們接下來看Jenkins都幹啥子了。

5.2 Jenkins進行的精彩互動

1)Jenkins會自動冒出來一個構建任務。

2)咱們點進來,看看具體操做日誌。是的,正在接受來自Git的任務。

3)下載Maven相關的軟件包(就是這個過程慢)。

4)下載完成後,就開始利用maven BUILD 新的hello項目包。

5)而後重建Maven容器,構建新的Image並Push到Docker私有庫中。

6)最後,從新把Docker容器拉起來。這樣,又新生了。呵呵

6. FAQ

問題1:採用這麼相對複雜的辦法(而不是把更新代碼放在宿主機而後卷組映射),是由於項目基於JAVA麼;是否PHP項目就能夠採用更新代碼放在宿主機而後卷組映射這種方式?

回1:將代碼拆分出容器,違背了集裝箱原則。致使裝卸複雜度增長。從貨運工人角度考慮,總體纔是最經濟的。一切版本化。拋棄過去的文件分發。這是正途。至於文件大小,大的war包也就50M或100M,在現有網絡下不成問題,性能問題最好優化。另外建議關注docker 2 docker,p2p傳輸。

問題2:若是總體代碼超過500m或者1g以上,總體集裝箱是否就不太好了?若是容器與代碼分離,鏡像就100m左右(2層,base+服務),而後代碼的話,是放到共享存儲裏,每一個代碼有更新,好比svn的代碼,能夠直接在共享存儲裏進行svn update就能夠控制版本

回2:若是你的代碼500M,那隻能說明業務開發該打板子了。

問題3:若是測試環境使用您提供的完整集裝箱服務還行,但在生產環境,集羣裏運行docker作應用,若是每一個容器都是有完整的代碼,是否有點臃腫,不如每一個集羣節點裏就運行基礎服務鏡像,經過卷組功能綁定共享存儲裏的代碼,加上Crontab、Python和Shell腳本,這樣每次代碼更新就1次就好了。

回3:環境一致性,在過去歷來沒有解決好。10年前咱們作paas時,和這個作法相似。不是說很差,時代變了,用腳本東拼西湊,終究難有好的系統。不能只考慮如今的方便,容器技術和vm若是類比,我以爲會讓本身下決定時很糾結。

補充3:腳本通常是典型的運維工程師思惟,quick & dirty。通常很難作成一個產品或者系統。總體考慮和擴展性考慮都比較少。如今作docker的難點在於到底怎麼看待它。究竟是拿它作調度的基本單位,仍是部署的基本單位考慮清楚,再聊方案。

備註:上述問題的回,主要由王利俊@cSphere和陳爾冬@華爲完成。

相關文章
相關標籤/搜索