Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Building Microservices Using Spring Boot and Docker - Part 1

DZone's Guide to

Building Microservices Using Spring Boot and Docker - Part 1

In this tutorial, you will learn how to build microservices using Spring Boot and its different components, and how to deploy your microservices using Docker containers.

· Microservices Zone ·
Free Resource

Learn how modern cloud architectures use of microservices has many advantages and enables developers to deliver business software in a CI/CD way.

In this tutorial, I will show you how to build microservices using Spring Boot and its different components, and in the last section, I will show you the deployment using Docker containers. 

We will learn about:

  1. Implementing different components of Microservices.

  2. Deployment of services through containerization.

Before starting, I will just touch base on the important components of microservice architecture.

While implementing Microservices, the following components are the pillar of the architecture:

1. Config servers: To keep the Properties file centralized and shared by all Microservices, we will create a config server which is itself a Microservice, and manages all microservices properties files and  those files are versioned controlled; any change in the properties will automatically publish to all microservices without restarting the services. One thing to remember is that every microservice communicates with the config server to get properties values, so the config server must be a highly available component; if it fails, then all microservices fail because it can't resolute the properties values! So, we should take care of the scenario - the config server should not be an SPF (single point of failure), so we will spin up more than one container for the config server.

2. Eureka Discovery server: The main goal of Microservices is decentralizing the different components based on the business features, so that each component - aka microservice - can be scaled as per need, so for a particular microservice, there are multiple instances and we can add and remove instances as per the need, so the way monoliths do load blancing is not going to work in a microservice paradigm. As it spawns containers on the fly, containers have dymanic IP addresses, so to track all instances of a service, a manager service will be needed, so when the containers are spawned, it registers itself to the manager and the manager keeps the track of the instances; if a service is removed, the manager removes it from the manager's service registry. If other services need to communicate with each other, it contacts a discovery service to get the instance of another service. Again, this is a highly available component; if the discovery service is down, microservices can't communicate with each other, so the discovery service must have multiple instances.

3. Components, aka services: Components are the key ingredients in Microservice architecture. By component, I mean a utility or business feature which can be managed or updated independently. It has a predefined boundary and it exposes an API by which other components can communicate with this service. The idea of microservices is breaking down a complete business functionality into several independent small features which will communicate with each other to produce the total business functionality. If any portion of the functionality changes in the future, we can update or remove that component and add a new component to the architecture. So, Microservice architecture produces a proper modular architecture with proper encapsulation and properly defined boundaries.

4. Gateway Service: A microservice is a collection of independent services which collectively produces a business functionality. Every microservice publishes an API, generally a REST API, so as a client, it is cumbersome to manage so many endpoint URLs to communicate with. Also, think about another perspective: if some application wants to build an authentication framework or security checking, they have to implement across all services, so that would be repeating itself against DRY. If we have a Gateway service, which is internet facing, the client will call only one endpoint and it delegates the call to an actual microservice, and all the authentication or security checking will be done in the gateway service.

Now we have a basic understanding how different parts of a microservice work together. In this tutorial, I will create an employee search service which will return employee information, an EmployeeDashBoard Service which will invoke the search service and show the results, a Eureka server so that these services can register themselves, and a gateway service to reach out to these services from outside. Then we will deploy our services in docker container and use DockerCompose to spawn the Docker containers. I will use Spring Boot for this tutorial.

Image title

Let's start to build our microservice project, as we have to create five individual services:

1. Config Server

2. Eureka server

3. Employee service

4. Employee Dashboard service

5. Zuul Proxy

The best place to start is going to http://start.spring.io/., shopping the requires modules, and hitting "generate project."

Image title

For this tutorial, we will use Spring Boot 1.5.4.

Creating the Config Server

To create the config server, first we need to check the config server module from starts.spring.io, and also check the actuator to see the endpoints. Then, download the zip file and open it in Eclipse.

The pom file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.example</groupId>
   <artifactId>MicroserviceConfigServer</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>MicroserviceConfigServer</name>
   <description>Demo project for Spring Boot</description>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.4.RELEASE</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Dalston.SR1</spring-cloud.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-config-server</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>


It downloads the spring-cloud-config-server artifacts.

Next, we have to create a bootstrap.properties file where we mention from which location the config server reads the property. In production mode, it should be the URL of the Git repository, but as this is a demo, I'll use my local disk. All properties files will be placed there, and the config server reads those property files.

Let's see the bootstrap.properties file:

server.port=9090
spring.cloud.config.server.native.searchLocations=file://${user.home}/MicroService/centralProperties/
SPRING_PROFILES_ACTIVE=native

Here, I instruct Spring Boot to spawn the embedded server in port 9090 and use a centralProperties folder as a folder to search all properties files. Note that in our Docker container, you have to create a central properties folder and place all the properties files there.

Now let's see the Java part:

package com.example.MicroserviceConfigServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigServer {

 public static void main(String[] args) {
  SpringApplication.run(ConfigServer.class, args);
 }
}


Here I use the @EnableConfigserver annotation, with which we instruct Spring Boot to consider this service as a config server application.

Now place few test properties files in centralProperties folder.

We are all set for the config server now. If we run this service and hit the http://localhost:9090/config/default URL, we see the following response:

{
   "name": "config",
   "profiles": [
      "default"
   ],
   "label": null,
   "version": null,
   "state": null,
   "propertySources": [
      {
         "name": "file:///home/shamik/MicroService/centralProperties/config.properties",
         "source": {
            "application.message": "Hello Shamik"
         }
      },
      {
         "name": "file:///home/shamik/MicroService/centralProperties/application.properties",
         "source": {
            "welcome.message": "Hello Spring Cloud"
         }
      }
   ]
}

It shows the all file names and key and values I placed in the centralProperties folder.

The next step is to create a Eureka server for service discovery.

Implementing Service Discovery

We will use Netflix's Eureka server for service discovery. To do that I am selecting the Eureka server module from start.spring.io and downloading the project.

The pom.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.example</groupId>
   <artifactId>EmployeeEurekaServer</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>EmployeeEurekaServer</name>
   <description>Demo project for Spring Boot</description>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.4.RELEASE</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Dalston.SR1</spring-cloud.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-config</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-eureka-server</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

Now create the bootstrap.properties:

spring.application.name=EmployeeEurekaServer
eureka.client.serviceUrl.defaultZone:http://localhost:9091/
server.port=9091
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

Here, I give a logical name EmployeeEurekaServer to this application, and the location of the Eureka server is http://localhost:9091; the embedded server will start on port 9091. Please note that the Eureka server itself can be a Eureka client; because there may be multiple instances of Eureka servers, it needs to be in sync with others. With this eureka.client.register-with-eureka=false, I explicitly instruct Spring Boot to not treat Eureka server as a client, because I created only one Eureka server, so it does not require to register itself as a client.

Now I will create the Java file:

package com.example.EmployeeEurekaServer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EmployeeEurekaServerApplication {

 public static void main(String[] args) {
  SpringApplication.run(EmployeeEurekaServerApplication.class, args);
 }
}


With the @EnableEurekaServer annotation, Spring Boot spawns this service as Eureka server. We are all set now; if I run the service and hit the http://localhost:9091/ in the browser, we will see the following screen:Image title

In Part 2, we will create the Employee Search and other services, then learn about deploying your microservices with Docker. Stay tuned!

Discover how to deploy pre-built sample microservices OR create simple microservices from scratch.

Topics:
microservices ,tutorial ,software architecture ,spring boot ,docker

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}