Building a Spring Boot Microservices Example with Docker

In this tutorial, we will explore how to create a Spring Boot microservices example with Docker. We will cover the setup, configuration, and deployment of a simple e-commerce application using microservices architecture.

Introduction to Microservices

Microservices is an architectural style that structures an application as a collection of small, independent services. Each service is responsible for a specific business capability and can be developed, tested, and deployed independently.

Microservices offer several benefits, including:

  • Improved scalability and resilience
  • Increased flexibility and maintainability
  • Enhanced fault tolerance and error handling

Prerequisites

To follow this tutorial, you will need:

  • Java 11 or later installed on your machine
  • Spring Boot 2.5 or later installed on your machine
  • Docker 20.10 or later installed on your machine
  • A code editor or IDE of your choice (e.g., Eclipse, IntelliJ IDEA, Visual Studio Code)

Step 1: Create a New Spring Boot Project

Let’s start by creating a new Spring Boot project using the Spring Initializr web application.

Go to https://start.spring.io and fill in the following details:

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 2.5
  • Project Metadata: Group = com.example, Artifact = microservices-example, Name = Microservices Example, Description = Demo project for Spring Boot
  • Dependencies: Web, Actuator, DevTools

Click on the Generate Project button to download the project template.

Step 2: Create the Microservices

Our e-commerce application will consist of three microservices:

  • Product Service: responsible for managing products
  • Order Service: responsible for managing orders
  • Customer Service: responsible for managing customers

Let’s create each microservice as a separate Spring Boot application.

Product Service

Create a new Java class called Product.java in the com.example.microservices.example.product package:

public class Product {
  private Long id;
  private String name;
  private Double price;

  // Getters and setters
}

Create a new Java class called ProductController.java in the com.example.microservices.example.product package:

@RestController
@RequestMapping("/products")
public class ProductController {
  @Autowired
  private ProductRepository productRepository;

  @GetMapping
  public List<Product> getAllProducts() {
    return productRepository.findAll();
  }

  @GetMapping("/{id}")
  public Product getProduct(@PathVariable Long id) {
    return productRepository.findById(id).orElseThrow();
  }
}

Order Service

Create a new Java class called Order.java in the com.example.microservices.example.order package:

public class Order {
  private Long id;
  private Long customerId;
  private List<OrderItem> items;

  // Getters and setters
}

Create a new Java class called OrderController.java in the com.example.microservices.example.order package:

@RestController
@RequestMapping("/orders")
public class OrderController {
  @Autowired
  private OrderRepository orderRepository;

  @GetMapping
  public List<Order> getAllOrders() {
    return orderRepository.findAll();
  }

  @GetMapping("/{id}")
  public Order getOrder(@PathVariable Long id) {
    return orderRepository.findById(id).orElseThrow();
  }
}

Customer Service

Create a new Java class called Customer.java in the com.example.microservices.example.customer package:

public class Customer {
  private Long id;
  private String name;
  private String email;

  // Getters and setters
}

Create a new Java class called CustomerController.java in the com.example.microservices.example.customer package:

@RestController
@RequestMapping("/customers")
public class CustomerController {
  @Autowired
  private CustomerRepository customerRepository;

  @GetMapping
  public List<Customer> getAllCustomers() {
    return customerRepository.findAll();
  }

  @GetMapping("/{id}")
  public Customer getCustomer(@PathVariable Long id) {
    return customerRepository.findById(id).orElseThrow();
  }
}

Step 3: Configure Docker

Let’s create a Dockerfile for each microservice.

Product Service Dockerfile

FROM openjdk:11-jdk-alpine
COPY target/microservices-example-product-0.0.1-SNAPSHOT.jar /app/
EXPOSE 8081
ENTRYPOINT ["java", "-jar", "/app/microservices-example-product-0.0.1-SNAPSHOT.jar"]

Order Service Dockerfile

FROM openjdk:11-jdk-alpine
COPY target/microservices-example-order-0.0.1-SNAPSHOT.jar /app/
EXPOSE 8082
ENTRYPOINT ["java", "-jar", "/app/microservices-example-order-0.0.1-SNAPSHOT.jar"]

Customer Service Dockerfile

FROM openjdk:11-jdk-alpine
COPY target/microservices-example-customer-0.0.1-SNAPSHOT.jar /app/
EXPOSE 8083
ENTRYPOINT ["java", "-jar", "/app/microservices-example-customer-0.0.1-SNAPSHOT.jar"]

Let’s create a docker-compose.yml file to manage the containers:

version: '3'
services:
  product-service:
    build: ./product-service
    ports:
      - "8081:8081"
    depends_on:
      - db
    environment:
      - DATABASE_URL=jdbc:postgresql://db:5432/microservices-example
      - DATABASE_USERNAME=postgres
      - DATABASE_PASSWORD=postgres

  order-service:
    build: ./order-service
    ports:
      - "8082:8082"
    depends_on:
      - db
    environment:
      - DATABASE_URL=jdbc:postgresql://db:5432/microservices-example
      - DATABASE_USERNAME=postgres
      - DATABASE_PASSWORD=postgres

  customer-service:
    build: ./customer-service
    ports:
      - "8083:8083"
    depends_on:
      - db
    environment:
      - DATABASE_URL=jdbc:postgresql://db:5432/microservices-example
      - DATABASE_USERNAME=postgres
      - DATABASE_PASSWORD=postgres

  db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=microservices-example

Step 4: Run the Application

Let’s run the application using Docker Compose:

docker-compose up -d

Our microservices application is now up and running. We can test the APIs using a tool like Postman or cURL.

Common Mistakes

Here are some common mistakes to avoid when building a Spring Boot microservices example with Docker:

  • Not using a consistent naming convention for the microservices
  • Not using a consistent port numbering scheme for the microservices
  • Not configuring the Docker containers correctly
  • Not using a reliable database connection

Conclusion

In this tutorial, we learned how to create a Spring Boot microservices example with Docker. We covered the setup, configuration, and deployment of a simple e-commerce application using microservices architecture.

We also learned how to avoid common mistakes and ensure that our application is scalable, resilient, and maintainable.

I hope this tutorial has been helpful. If you have any questions or need further assistance, please don’t hesitate to ask.


Leave a Reply

Your email address will not be published. Required fields are marked *