Spring Boot with PostgreSQL Using Docker Compose

Docker Compose is a tool for defining and running multi-container Docker applications. With Docker Compose, you can define a multi-container environment that includes your Spring Boot application and a PostgreSQL database. This guide will walk you through the process of setting up a Spring Boot application with PostgreSQL using Docker Compose.

Prerequisites

  • JDK 17 or later
  • Maven or Gradle
  • Docker and Docker Compose installed on your machine
  • IDE (IntelliJ IDEA, Eclipse, etc.)

Step 1: Set Up a Spring Boot Project

Use Spring Initializr to create a new project with the following configuration:

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 3.2.x
  • Dependencies: Spring Web, Spring Data JPA, PostgreSQL Driver

Download and unzip the project, then open it in your IDE.

Example Spring Boot Application

Create a simple Spring Boot application that connects to PostgreSQL and includes a REST controller.

1.1 Application Class

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

1.2 Entity Class

Create a Student entity in the com.example.demo.entity package.

package com.example.demo.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // Getters and setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

1.3 Repository Interface

Create a StudentRepository interface in the com.example.demo.repository package.

package com.example.demo.repository;

import com.example.demo.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
}

1.4 Service Class

Create a StudentService class in the com.example.demo.service package.

package com.example.demo.service;

import com.example.demo.entity.Student;
import com.example.demo.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class StudentService {

    @Autowired
    private StudentRepository studentRepository;

    public List<Student> getAllStudents() {
        return studentRepository.findAll();
    }

    public Student saveStudent(Student student) {
        return studentRepository.save(student);
    }
}

1.5 REST Controller

Create a StudentController class in the com.example.demo.controller package.

package com.example.demo.controller;

import com.example.demo.entity.Student;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping("/students")
    public List<Student> getAllStudents() {
        return studentService.getAllStudents();
    }

    @PostMapping("/students")
    public Student saveStudent(@RequestBody Student student) {
        return studentService.saveStudent(student);
    }
}

1.6 application.properties Configuration

Configure your application to use PostgreSQL. In the src/main/resources directory, create or update the application.properties file.

# src/main/resources/application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=password
spring.datasource.driver-class-name=org.postgresql.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

Step 2: Create Docker Compose Configuration

Docker Compose allows you to define and run multi-container Docker applications. You will create a docker-compose.yml file to define the services for your Spring Boot application and PostgreSQL database.

2.1 Create docker-compose.yml

Create a docker-compose.yml file in the root directory of your project.

version: '3.8'

services:
  postgres:
    image: postgres:14
    environment:
      POSTGRES_DB: testdb
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  app:
    image: demo-app
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/testdb
      SPRING_DATASOURCE_USERNAME: postgres
      SPRING_DATASOURCE_PASSWORD: password
    depends_on:
      - postgres

volumes:
  postgres_data:

Explanation:

  • postgres: Defines the PostgreSQL database service.
    • image: Specifies the Docker image to use.
    • environment: Sets the environment variables for the database.
    • ports: Maps the container port to the host port.
    • volumes: Persists the PostgreSQL data.
  • app: Defines the Spring Boot application service.
    • image: Specifies the Docker image to use.
    • build: Builds the Docker image using the specified Dockerfile.
    • ports: Maps the container port to the host port.
    • environment: Sets the environment variables for the Spring Boot application.
    • depends_on: Ensures the PostgreSQL service is started before the Spring Boot application.

2.2 Create a Dockerfile

Create a Dockerfile in the root directory of your project.

# Use the official OpenJDK base image
FROM openjdk:17-jdk-alpine

# Set the working directory inside the container
WORKDIR /app

# Copy the built jar file into the container
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar

# Expose port 8080
EXPOSE 8080

# Run the application
ENTRYPOINT ["java", "-jar", "app.jar"]

Step 3: Build and Run the Application

3.1 Build the Jar File

Run the following command to build the jar file of your Spring Boot application:

./mvnw clean package

3.2 Build and Run Docker Compose

Run the following command to build and start the Docker Compose services:

docker-compose up --build

3.3 Verify the Application

Open a web browser or a tool like Postman and navigate to the following URL to test the endpoints:

  1. Retrieve all students:

    • URL: http://localhost:8080/students
    • Method: GET
  2. Create a new student:

    • URL: http://localhost:8080/students
    • Method: POST
    • Body:
      {
        "name": "Ramesh Fadatare",
        "email": "ramesh.fadatare@example.com"
      }
      

Conclusion

In this tutorial, you have learned how to set up and run a Spring Boot application with PostgreSQL using Docker Compose. We covered:

  • Setting up a Spring Boot project with PostgreSQL.
  • Creating a Dockerfile for the Spring Boot application.
  • Creating a docker-compose.yml file to define the services.
  • Building and running the application using Docker Compose.

By following these steps, you can easily manage and deploy your Spring Boot application and its dependencies using Docker Compose.

Comments