本文學習前提:Java, Spring Boot, Docker, Spring Cloud
一、准備工作
1.1 安裝Docker環境

這一部分請參考我的另一篇文章《ASP.NET Core on Docker》,本文不再贅述。需要注意的是,如果你是Windows想要安裝Docker,Docker for Windows需要64bit Windows 10 Pro,且需要開啟Hyper-V。如果你不想開啟Hyper-V,而又事先安裝了VMware Workstation,可以參考曉晨的《Docker for Windows 使用VMware Station》。
1.2 准備Java鏡像
(1)拉取java鏡像
# docker pull java => 默認為最新版本的鏡像
# docker pull java:8 => 標簽為8的java鏡像版本
(2)查看java鏡像
# docker images java

PS:java鏡像有點大啊,643MB
二、部署Spring Boot微服務到Docker
2.1 Spring Boot示例准備
這里以一個spring boot應用程序:eureka-service來介紹,它是基於spring cloud eureka的一個服務注冊與發現的微服務應用程序,你可以從這里獲取其源碼。

2.2 快速借助Dockerfile部署到Docker
(1)使用Maven打包項目:執行下面的命令,將其構建成jar包
MVN> mvn clean package
(2)在jar包所在目錄,創建Dockerfile文件,並添加以下內容
# 基於Java8鏡像 FROM java:8 # 將本地文件夾掛在到當前容器 VOLUME /tmp # 復制文件到容器 ADD eureka-service-sn-0.0.1-SNAPSHOT.jar app.jar RUN bash -c 'touch /app.jar' # 聲明需要暴露的端口 EXPOSE 9000 # 配置容器啟動后執行的命令 ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
(3)通過FTP工具將jar包和Dockerfile文件一起傳送到服務器端,然后通過Shell工具登錄並跳轉到這個目錄下,執行以下命令打包鏡像:
# docker build -t edc/discovery-service-eureka:0.0.1 . => 不要忘記這里有個 .

# docker images => 可以看到在Java8的鏡像基礎之上,針對eureka-service的鏡像已准備好

(4)啟動鏡像:
# docker run --name eureka-service -d -p 8761:8761 edc/service-discovery-eureka:0.0.1

(5)驗證是否已成功啟動:訪問http://docker宿主機IP:8761/,可以正常顯示Eureka Server首頁。

三、使用Docker Compose編排微服務
3.1 Docker Compose簡介
在實際的微服務架構中,一般包含很多個微服務,而且每個微服務都會部署多個實例,如果每個微服務都需要手動啟停,那么效率會很低下,維護量也會很大。
Compose是一個用於定義和運行多容器的Docker應用程序的工具,非常適合在開發、測試、構建CI工作流等場景。
Compose的安裝請參考:https://docs.docker.com/compose/install/#install-compose

安裝后驗證如下:# docker-compose --version

PS:我這里使用的Compose版本是1.22.0
3.2 Docker Compose快速入門示例
首先,我們來了解下使用Compose的3個基本步驟:
- 使用Dockerfile(或其他方式)定義應用程序環境,以便於在任何地方重現該環境
- 在docker-compose.yml文件中定義組成應用程序的服務,以便各個服務在一個隔離的環境中一起運行
- 運行docker-compose up命令,啟動並運行整個應用程序
其次,我們仍然以上面的eureka-service為例,來快速實踐一下Compose的基本步驟:
(1)打包eureka-service,同上,不再贅述
(2)創建Dockerfile文件,同上,不再贅述
(3)在Dockerfile同一路徑下創建docker-compose.yml,並添加以下內容:
version: '3'
services:
eureka: # 指定服務的名稱
build: . # 指定Dockerfile所在路徑,注意這里是個 .
ports:
- "8761:8761" # 指定端口映射,類似docker run的-p選項,注意使用字符串形式
(4)通過FTP工具將jar包、dockerfile以及docker-compose.yml一同拷貝到docker宿主機指定文件夾中
(5)在這個目錄下執行以下命令,啟動容器。
# docker-compose up

PS:也可以使用docker-compose up -d 來通過后台運行的方式啟動並運行這些容器
(6)驗證容器是否成功啟動:訪問http://docker宿主機IP:8761/,可以正常顯示Eureka Server首頁。

最后,說說Docker Compose將所管理的容器分為三層,分別是工程(Project)、服務(Service)以及容器(Container)。Docker Compose運行目錄下的所有文件(docker-compose.yml、extends文件或環境變量文件等)組成一個工程(默認為docker-compose.yml所在目錄的目錄名稱)。一個工程可以包含多個服務,每個服務定義了容器運行的鏡像、參數和依賴,一個服務可以包括多個容器實例。

對應上圖中的名稱,工程名稱是eureka-service(對應docker宿主機上的目錄名稱),該工程包含了1個服務,服務名稱是eureka。當執行docker-compose up命令時,啟動了eureka服務的1個容器實例eureka_1。
3.3 Docker Compose編排Spring Cloud微服務
這里仍然會采用在2.1節提到的部分示例來(詳情請參見github的part5部分)演示,將要編排的微服務列表如下表所示:
| 微服務項目名稱 | 項目微服務中的角色 |
| eureka-service | 服務發現&注冊組件 |
| zuul-service | API網關 |
| user-service | 服務提供者 |
| movie-service | 服務提供者 |
(1)分別通過maven打成jar包,不再贅述。
PS:可以通過使用maven插件來構建docker鏡像,需要在pom.xml添加一些內容,這里不闡述,有興趣的可以百度一下。此外,由於Docker默認網絡模式是bridge,各個容器的IP都不相同,因此如果在服務提供者的配置文件中設置了http://localhost:8761/eureka/會無法滿足要求。這時,我們可以為Eureka Server所在容器配置一個主機名(例如discover),並讓各個微服務使用主機名來訪問Eureka Server。所以,這里講所有微服務關於Eureka地址的配置改為如下內容:
eureka: client: serviceUrl: defaultZone: http://discovery:8761/eureka/
(2)編寫docker-compose.yml文件
version: '3' services: # 指定服務名稱 eureka-service: build: context: eureka-service/ # 指定服務所使用的的鏡像,后續不再贅述 image: edc/eureka-service:0.0.1 # 暴露端口信息 ports: - "8761:8761" zuul-service: build: context: zuul-service/ image: edc/zuul-service:0.0.1 # 連接到 eureka-service,這里使用的是SERVICE:ALIAS的形式 links: - eureka-service:discovery user-service: build: context: user-service/ image: edc/user-service:0.0.1 links: - eureka-service:discovery movie-service: build: context: movie-service/ image: edc/movie-service:0.0.1 links: - eureka-service:discovery
PS:這里我將各個服務都放在了分別的目錄下,可以參考下圖這個目錄結構:

(3)通過以下命令在docker-comopose.yml所在的目錄下進行build,統一打包鏡像
# docker-compose build

打包后查看已經build好的鏡像列表

(4)執行以下命令啟動項目
# docker-compose up -d
PS:這里加上了-d,表示后台運行,否則你的整個屏幕都是日志輸出...

最終效果如下圖所示:

3.4 Docker Compose編排高可用的Eureka Server
針對Eureka Server,實現高可用的話,也可以通過Compose來編排Eureka Server集群(比如一個2個節點的高可用最小規模集群)。
首先,需要針對Eureka Service的配置文件進行改造,以便通過同樣的配置屬性就可以實現兩個節點的配置,這里仍然使用2.1節中的github中的示例(參見part1部分)。下面是eureka-service-ha-1的配置項,eureka-service-ha-2同理,不再贅述。
spring: application: name: eureka-service-ha-1 --- spring: # profile=peer1 profiles: peer1 server: port: 8761 eureka: instance: # when profile=peer1, hostname=peer1 hostname: peer1 client: service-url: # register self to peer2 defaultZone: http://peer2:8762/eureka --- spring: # profile=peer2 profiles: peer2 server: port: 8762 eureka: instance: # when profile=peer2, hostname=peer2 hostname: peer2 client: service-url: # register self to peer1 defaultZone: http://peer1:8761/eureka
從上面的配置文件中,兩個節點是通過spring.profiles.active來區分配置屬性的。
然后,再來編寫一個針對高可用eureka server的docker-compose.yml文件:
version: '3' services: # 指定服務名稱 eureka-service-ha-1: hostname: peer1 # 指定hostname image: edc/eureka-service-ha:0.0.1-SNAPSHOT links: - eureka-service-ha-2 # 注冊到另一個eureka-service中 ports: - "8761:8761" environment: - spring.profiles.active=peer1 # 指定服務名稱 eureka-service-ha-2: hostname: peer2 # 指定hostname image: edc/eureka-service-ha:0.0.1-SNAPSHOT links: - eureka-service-ha-1 # 注冊到另一個eureka-service中 ports: - "8762:8762" environment: - spring.profiles.active=peer2
其他步驟如3.3所述,這里不再進行演示。
3.5 Docker Compose編排可伸縮的微服務
這里仍然以3.3中的movie-service為例,執行以下命令來達到微服務節點的擴展(這里從1個節點變為2個節點):
# docker-compose scale movie-service=2

從上圖可以看出,movie-service實例已從1個變為了2個。
同理,要伸縮為1個節點,只需要將2改為1即可,不再贅述。
四、小結
本文極簡地介紹了如何通過借助dockerfile的方式部署一個spring boot應用程序到docker,docker compose的快速入門示例以及如何通過docker compose編排spring cloud微服務應用程序,還介紹了實現編排高可用eureka server以及可伸縮的微服務的實現思路。關於docker與docker compose,還有許許多多的內容,其官方文檔已經寫得非常詳細,並對常見的問題也已經有了很多詳細的總結,大家可以參見:https://doc.docker.com/compose/faq/ 瀏覽。此外,十分感謝本文參考資料周立老師著的《Spring Cloud與Docker微服務架構實戰(第二版)》,帶我快速入門Spring Cloud的世界,謝謝!
參考資料

周立,《Spring Cloud與Docker微服務架構實戰(第2版)》
