本篇是《使用Spring Boot和Docker構建微服務架構》系列的第二篇,本篇我們將會利用工具進行設置,深入探討如何使用Docker工作,然后搭建我們的第一個容器。原文作者為3Pillar環球旗下美國Adbanced技術集團的總監Dan Greene,Dan有十八年的軟件設計和開發經驗,包括在電子商務、B2B集成、空間分析、SOA架構、大數據以及云計算等領域的軟件產品架構經驗,他是AWS認證解決方案架構師,在3Pillar之前先后就職于Oracle、ChoicePoint和Booz Allen Hamilton。Dan畢業于喬治·華盛頓大學,他也是一個父親、業余木工愛好者,還參加過包括國際障礙大賽這樣的障礙賽跑。介紹和工具在本篇中,我們將會構建第一篇中討論的解決方案。我是在Mac上工作的,但是工具在Mac和PC上是相同的,所以在平臺上的操作是99%相同的,我將不會回顧如何安裝這些工具,而是直接從如何使用它們開始,你所需要的準備工作如下:Docker Toolbox:包含了VirtualBox(作用為創建虛擬機用來運行容器)、Docker Machine(在虛擬機內運行Docker容器)、Docker Kitematic(一個管理在Docker Machine里運行的容器的GUI)以及Docker Compose(多容器編排工具)
Git:我的GitHub鏈接在這兒,我在Windows上使用Git Extensions,在Mac上使用Source Tree,不過使用其他Git客戶端包括命令行都是可以的。
Java 8 SDK:Java 8在JVM永久代(PermGen)方面有了改進,另外對于Streams API和Lambda的支持也是非常贊的。
構建工具的選擇:讓我們使用Gradle吧,我推薦使用SDKMan,正式名稱為GVM來管理Gradle版本,如果你使用Windows工作,你可以使用Cygwin安裝SDKMan或者SDKMan的Powershell命令行工具,或者Gravy也是可替代的選擇。
IDE的選擇:我們使用Spring Tool Suite(STS)來工作,在本文寫作時最新的for Mac版本為3.7.0。
Rest工具:對于任何Web服務項目使用都非常方便,我是Chrome擴展工具Postman的粉絲,如果你擅長curl命令行,這個工具也是不錯的。
uMongo或者Mongo GUI:文檔型數據庫完美匹配自足性的模型——對象進行自動檢索,并且參考對象可以在微服務架構中通過ID來引用,這些ID可以很好地映射到文檔存儲中,另外地,MongoDB擁有運行很棒的“官方”Docker鏡像。
我們對于源代碼管理的第一個意見——似乎也是絕大多數的在線觀點,就是每個微服務都應該有自己的版本庫。微服務的一個基本理念就是跨服務之間不能共享代碼。就我個人而言,這對我架構師的小心臟是個小小的打擊,因為任何實用工具的重復代碼的數量可能會比較多,以及缺乏一個單一、統一的領域模型給我有點心痛的感覺。我理解這個原則——自足性意味著自力更生。為了這篇博文,我把所有的代碼都放到了一個單獨的代碼庫,然而,每個微服務在根目錄下都有它一個自己的目錄。這樣做是為了讓我可以隨著時間的推移展示分支的進展。在一個真實的解決方案中,你應該讓每一個微服務都有它自己的不同的版本庫,也許會有統一的版本庫引用其它的子模塊。總體思路因為我們要處理隔離的、可重用的組件,我們將做以下的映射:一個邏輯業務對象→一個微服務→一個Git版本庫目錄→一個Mongo集合因為業務對象可能由多個對象組成,任何我們認為可以作為其自身業務對象的子對象都可以劃分為其自身的組件棧。更多有關Docker如何工作的信息,以及我們的第一個容器為了理解如何構建一個完整的基于Docker容器的產品解決方案,我們將需要深入研究容器是如何在宿主機(或者是虛擬機,正如我們的例子)里運行的,使用Docker通常是有三個階段:鏡像構建、鏡像分發和容器部署。構建鏡像——Dockerfile的世界為了構建鏡像,你要寫一系列的指令用來獲取已有的鏡像,接著對該鏡像做些改變和配置。官方的Docker Hub Repository包含了許多的“官方”鏡像以及數以千計的用戶定制的鏡像。如果其中的鏡像不太符合你的需求,你可以創建一個定制的Dockerfile,用來在鏡像上逐步添加一些內容,,比如安裝系統軟件包、復制文件或者公開一些網絡端口,當我們構建微服務時,我們將會創建一個定制的Dockerfile,不過現在,我們將會利用一個標準鏡像來啟動一個MongoDB實例。容器聯網當容器啟動時,有一個它私有的網絡,容器宿主機端口將外部網絡通信轉發到單個的容器端口上,特定的容器端口可以通過Dockerfile來決定公開,并且端口轉發可以通過以下兩種方式之一來進行:你可以顯式地從宿主機映射端口到容器上,或者如果沒有顯式映射的話,Docker將映射已聲明的容器端口到宿主機一個可用的臨時端口上(通常的范圍是從32768到61000)。當我們可以對整個解決方案顯式地管理端口映射時,通常讓Docker處理這一切是一個更加好的主意,并且可以通過Link機制公開端口信息到容器上,這方面將在我們構建我們的第一個微服務容器時有所涉及。啟動MongoDB容器無論你是使用Kitematic還是Docker命令行,都可以非常簡單的啟動一個標準的容器。使用命令行的話,如果一切都安裝正確,命令提示符將會包含以下三個關鍵的環境變量:DOCKER_HOST=tcp://192.168.99.100:2376DOCKER_MACHINE_NAME=defaultDOCKER_TLS_VERIFY=1DOCKER_CERT_PATH=/Users/[username]/.docker/machine/machines/default
這些是按照你的情況設置的(如果是在安裝過程中打開的話,你可能需要重啟終端或者命令提示符)。這些都是必要的,因為Docker不能直接運行在我的Mac筆記本上,而是跑在筆記本運行的虛擬機上。Docker客戶端非常有效地將Docker命令從我的筆記本“代理”到虛擬機上,在我們啟動容器前,讓我們重溫一下一部分Docker命令是非常有益的,在使用任何圖形用戶界面之前,了解命令行的東西總是很好的。Docker級別的命令:docker ps該命令將會列出所有運行的容器,顯示的信息包括它們的ID、名字、基礎鏡像名字和端口映射信息等。docker build該命令用來定義一個鏡像——通過處理Dockerfile來創建一個新的鏡像,我們將用這個命令來構建我們的微服務鏡像。docker pull[鏡像名字]該命令從遠程Repository拉取鏡像并且存儲在本地。docker run該命令將基于一個本地或者遠程Repository(比如Docker Hub)啟動一個容器,我們將會相當多地探究這個命令。docker push該命令推送一個構建好的鏡像到一個Repository,通常是Docker Hub。容器特定的命令這些命令使用容器ID或者名字作為一個參數:docker status [容器名字/ID][容器名字/ID]這個命令將顯示指定的每一個容器的當前負載,比如CPU占用率、內存使用率以及網絡流量等。docker logs [-f][容器名字/ID]該命令顯示容器的最新的日志,-f選項就好比Shell終端中的“tail -f”中的-f選項。docker inspect [容器名字/ID]該命令將容器的所有配置信息以JSON的格式轉儲出來顯示。docker port [容器名字/ID]該命令顯示容器與宿主機之間的所有端口映射信息。docker exec [-i][-t][容器名字/ID]該命令將在目標容器上執行一條命令(-i表明以交互方式運行,-t表明以偽TTY終端運行),這個命令常用來獲得一個容器終端Shell:docker exec -it [容器名字/ID]sh一旦我們理解了這些參考材料,我們可以進入到下一步啟動一個Mongo容器。命令非常簡單:docker run -P -d —name mongo mongo解釋如下:P選項告知Docker在臨時端口范圍里公開容器聲明的任何端口
d選項告知以Daemon方式運行容器(比如在后臺)
name選項給容器分配一個名字(名字必須在所有運行的容器實例中唯一,如果你不提供這個選項,將會獲得一個隨機的半友好的名字比如modest_poitras)
最后的mongo表明了使用哪一個鏡像
Docker Hub鏡像的定義采用了[所有者]/[鏡像名字][:標簽]的命名格式,如果沒有指定所有者,那么使用的就是“官方”的Docker Hub鏡像——這是預留給Docker官方給軟件供應商的禮物也就是成為官方鏡像,如果最后的標簽部分省略的話,那么就會認為你需要獲得的是最新版本的鏡像。現在我們來嘗試確認我們的Mongo實例已經啟動并且運行了:docker exec -it mongo shmongo
MongoDB shell version: 3.0.6connecting to: testServer has startup warnings:2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten]2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten]2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten]> use microserviceblogswitched to db microserviceblog> db.createCollection('testCollection'){ "ok" : 1 }
在容器內部,Mongo看起來正在運行,但是我們可以從外部獲知嗎?為了嘗試這個,我們需要查看什么臨時端口被映射到了Mongo的端口上,我們運行如下命令:docker ps
從下面我們可以看到(為了可讀性省略了一些列):CONTAINER ID IMAGE PORTS NAMES87192b65de95 mongo 0.0.0.0:32777->27017/tcp mongodb
我們可以看到宿主機端口32777映射到了容器端口27017上,然而,記住我們的容器是運行在虛擬機上的,所以我們必須回到我們的環境變量:$ echo $DOCKER_HOSTtcp://192.168.99.100:2376
我們應該可以通過如下的地址訪問我們的Mongo容器的27017端口:192.168.99.100:32777,啟動Mongo然后點擊那個位置顯示數據庫可以外部訪問:[圖片上傳中。。。(1)]
在這里結束第二篇吧,在本系列的第三篇中,我們將繼續探討,通過創建一個或兩個微服務,管理它們的變化,然后運用持續集成以及產品部署技術進行工作。原文鏈接:BUILDING A MICROSERVICE ARCHITECTURE WITH SPRING BOOT AND DOCKER, PART II(翻譯:胡震)