Java微服务之Spring Boot on Docker

本文学习前提: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 版)

 

作者:周旭龙

出处:http://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。