本文的重點不是討論Docker的基本原理或實現機制(網上有太多的資料文檔可以參考,比如這篇博客《Docker,雲時代的程序交付方式》),而是基於前一段時間的探索實踐,分享一些我們對Docker的認識與思考,期待有更多的同行參與進來,一起推動Docker在國內的應用,享受到其發展的紅利。因此,我們這裏着眼於以下三個問題:爲什麼Docker有價值?什麼是Docker思維?如何把Docker玩起來?
爲什麼Docker有價值
爲什麼Docker這麼有價值?在回答這個問題之前,我們先想一個相似的問題,爲什麼阿里巴巴這麼有價值?
傳統的商業存在兩大弊端:一是買賣雙方相對分散,加大了需求收集、營銷、運輸的成本;二是買賣雙方信息不對稱,對交易產生了抑制作用。
電子商務的出現則將商品從賣方到買方的流通過程變得集中化、標準化、透明化:
- 集中化:買家足不出戶就能從各個商戶集中購買商品,賣家根據買家需求集中配貨、根據下單情況集中發貨。
- 標準化:買家支付下單-賣家發貨-快遞包裹-物流運輸-買家收貨確認,整個流程都是標準化的。
- 透明化:買家可以在網上瀏覽商品評價、比較商品價格。買賣雙方的信用等級也是完全透明的。
綜上所述,可以說阿里巴巴這樣的電商帶來的最大價值在於降低了商品的社會交易成本。
現在我們把商業發展的邏輯搬到軟件交付這裏。傳統的軟件交付面臨同傳統商業類似的問題:
-
軟件發佈分散化,使用者搜索和安裝軟件的成本較高。當然,我們有類似yum、brew這樣的工具來集中處理軟件安裝與軟件依賴問題。但是,不要忘記開源軟件已經佔據越來越重要的位置,它們的發展速度和協作方式使傳統的工具很難跟上節奏。
-
軟件開發者和軟件使用者雙方信息不對稱。儘管開發者對軟件的代碼編譯、參數配置、運行環境等信息瞭如指掌,但使用者卻很可能一知半解。因此,我們會經常看到使用者抱怨,明明按照用戶手冊一步步操作,卻仍然跑不起來。這種情況也時常出現在軟件流程中,開發將程序和文檔交付給測試或運維,測試或運維卻總是無法重現期望的運行狀態,幾經輾轉發現是機器環境 、系統環境、軟件依賴版本、參數配置等等原因導致。這樣低效的軟件流程將使持續集成與持續交付很難真正實施起來,僅僅流於形式。
Docker的出現則將軟件從開發方到使用方的交付過程變得集中化、標準化、透明化:
- 集中化:軟件使用者可以從Docker倉庫找到琳琅滿目的軟件鏡像,一個鏡像包含商業軟件或開源軟件,也可以包含單個軟件或任意的軟件組合。
- 標準化:Docker鏡像的“構建-發佈-存儲-下載-運行”是標準化的,統一通過Docker工具來執行,而且所有操作都可以移植到任意的機器或平臺。
- 透明化:Docker鏡像是自包含的,包括程序、軟件依賴、參數配置等所有運行環境,使用者無需瞭解細節,只需運行同樣的Docker命令就能達到與開發者同樣的運行狀態。
綜上所述,可以說Docker帶來的最大價值在於降低了軟件的交付成本。
什麼是Docker思維
這年頭流行思維主義,什麼互聯網思維、大數據思維格外賺人眼球。這裏我們跟風一下,提出一個Docker思維,其實歸納起來就兩句話:
-
做爲軟件使用者,避免直接安裝軟件包,總是以Docker鏡像形式獲取軟件、以Docker容器形式運行軟件。
-
做爲軟件開發者,避免直接發佈軟件包,總是以Docker鏡像形式發佈到Docker倉庫。
怎樣理解這兩句話?下面通過一個簡單的實踐來說明。假定現在我們在開發一個Java程序,從編譯到運行需要使用以下幾個軟件工具:1) git,源碼版本控制; 2) maven,源碼編譯; 3) mysql,存儲數據庫。
遵循Docker思維,做爲使用者,我們應該避免直接安裝git、maven及mysql,而是通過Docker來獲取。
首先,從github上獲取源代碼:
docker run -it --rm -v "$(pwd)":/app switchback/git-debian git clone https://github.com/spring-by-example/spring-by-example.git /app
運行以上命令將在當前文件夾clone指定github地址的源代碼。簡單解析一下命令:
- switchback/git-debian,是git的Docker鏡像URL。
- -it,指定以交互方式啓動容器。
- --rm,指定命令結束自動刪除容器。
- -v "$(pwd)":/app, 指定將宿主機的當前文件夾mount到容器裏的/app文件夾。
然後,通過maven來編譯源碼:
docker run -it --rm -v "$(pwd)":/app -w /app docker.cn/docker/maven mvn clean package
運行以上命令將在當前源碼文件夾編譯maven項目。簡單解析一下命令:
- maven:3.2-jdk-7,是maven的Docker鏡像URL。
- -w /app,指定容器的工作路徑爲"/app"。
最後,搭建mysql數據庫:
docker run -e MYSQL_ROOT_PASSWORD=mypassword -d -p 3306:3306 docker.cn/docker/mysql
運行以上命令將在本機啓動一個mysql數據庫。簡單解析一下命令:
- docker.cn/docker/mysql,是mysql的Docker鏡像URL。
- -e MYSQL_ROOT_PASSWORD=mypassword,-e選項用於向Docker容器裏注入環境變量,這裏通過MYSQL_ROOT_PASSWORD環境變量傳遞mysql的root密碼。
- -d,指定後臺方式啓動容器
- -p 3306:3306,指定將容器的3306端口綁定到宿主機的3306端口。
可以看到,三條Docker命令就滿足了我們對git/maven/mysql的使用需求,而且可以完全移植到有Docker環境的任意機器。那麼,接下來的問題是,如何發佈我們的Java程序?
遵循Docker思維,做爲開發者,應該通過Docker來發布軟件。
首先,編寫一個Dockerfile來製作Docker鏡像,它有點類似Makefile的作用:
#每個Docker鏡像需要基於某個基礎鏡像來構建
#新鏡像的構建操作會在基礎鏡像上疊加
FROM docker.oa.com:8080/docker/java7
#將源碼編譯後產生的jar文件拷貝到鏡像裏
ADD target/myapp.jar /app/myapp.jar
#指定容器的啓動命令
CMD java -jar /app/myapp.jar
保存以上的Dockerfile,運行以下命令製作鏡像,指定鏡像名爲myapp,版本爲1.0:
docker build -t myapp:1.0 .
鏡像製作完成後,可以提交到Docker倉庫,軟件發佈就完成了:
docker push myapp:1.0
可以看到,兩條Docker命令加一個Dockerfile就滿足了我們對軟件的發佈需求。更重要的是,使用者可以像我們之前使用git/maven/mysql那樣,通過Docker獲取並運行該軟件。
如何把Docker玩起來
君子動口又動手,纔是好程序員。要想玩轉Docker,首先得動手把Docker環境搭建起來。下面讓我們花5分鐘的時間在Windows上搭建Docker環境。
方式一
最簡單的方式是直接安裝boot2docker,它是一個爲體驗Docker而打造的輕量級Linux發行版。在Windows上可以直接運行boot2docker安裝文件,它默認會綁定安裝VirtualBox以便在虛擬機中運行boot2docker。
boot2docker極其輕量,安裝簡單,但是它完全是運行在內存中的,這意味着你在系統中修改的配置或保存的文件,在重啓後都會丟失。在某些情況下,可能你希望永久創建某個用戶賬號,或者永久保存某些文件(例如Dockerfile),這時候boot2docker就無法滿足了,可以嘗試方式二。
方式二
通過vagrant安裝coreos。coreos是另一個爲Docker而打造的輕量級Linux發行版,但它的目標是大規模生產環境部署,而不僅僅是體驗;vagrant是一個創建可移植的開發環境的工具。我們通過以下幾步來安裝coreos:
1. 安裝virtualbox
2. 安裝vagrant
3. 下載coreos的vagrant box——coreos_production_vagrant.box
4. 運行以下命令添加vagrant box:
vagrant.exe box add --name coreos coreos_production_vagrant.box
5. cd到一個新的文件夾,運行以下命令啓動coreos虛擬機:
vagrant.exe init coreos
vagrant.exe up
6. 現在就可以ssh到coreos了:
vagrant.exe ssh
7. 當然也可以通過putty這樣的工具來ssh到coreos:IP=127.0.0.1,Port=2222。
到目前爲止,相信你已經能夠在Windows上自由體驗Docker了,不妨試試將自己的軟件製作成鏡像,發佈到倉庫,再讓其他人通過Docker獲取運行,你會發現原來軟件交付真的是如此便捷!
接下來更進一步,你可以考慮將複雜一點的分佈式應用遷移到Docker,這時候就需要搭建Docker集羣,而更關鍵的問題是,如何做資源調度、擴縮容、服務發現、自動容錯、集羣監控。Docker自身目前還不能解決集羣應用的問題(雖然已經在朝着這個方向努力),這需要在Docker之上構建集羣管理系統,業界有名的開源項目包括Kubernetes和Flynn,具體介紹可參考筆者的文章《Kubernetes初探:原理及實踐應用》和《Flynn初探:基於Docker的PaaS平臺》。
總結
經過本文的分享,希望大家對Docker有更了清晰的認識,並且能動手玩起來。有任何疑問或者想法,歡迎通過郵件[email protected]交流,讓我們攜手走進Docker時代,做新時代的弄潮兒。