En este post vas a aprender como crear una aplicacion Spring Boot con una base de datos PostgreSQL para que se ejecute dentro de un contenedor Docker.
Verás a continuación estos puntos para construir tu aplicación Spring Boot con una base de datos PostgreSQL en un contenedor Docker.
Ya hemos estado trabajando en otros post con Spring Boot, Java y Docker. Te dejo aquí algunos links que pueden ayudarte con este tema.
Dependencias para Spring Boot con Postgresql
Para este tutorial vas a utilizar Gradle para administrar las dependencias y el build del proyecto. La estructura de tu proyecto quedará al finalizar de este modo:
Necesitas definir las siguientes dependencias para utilizar Spring Boot con Postgresql:
'org.springframework.boot:spring-boot-starter-web'
'org.springframework.boot:spring-boot-starter-data-jpa'
'org.postgresql:postgresql'
El archivo build.gradle completo queda así:
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
El main de Spring Boot para el proyecto
Debes definir el main de tu aplicación con la anotación @SpringBootApplication
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
El resto de componentes para el proyecto: modelo, repositorio, controller y propiedades
Modelo
Vas a crear una entidad User que será un modelo muy simple para almacenar en la base de datos PostgreSQL
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class UserModel {
@Id
@GeneratedValue
private Long id;
private String name;
// set and get…
}
Repositorio
Creas un repositorio para nuestro modelo User. Extenderá la clase JpaRepository de Spring.
@Repository
public interface UserRespository extends JpaRepository<UserModel, Long> {
}
Controller
Creas un controller con rest points básicos para este ejemplo. Vas a definir tres endpoints:
- “/user/all” para devolver todos los user
- “/user/{id}” para devolver un solo User por el ID
- “/user/save” para guardar un User
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
@RestController
public class UserController {
private UserRespository userRespository;
@Autowired
public UserController(UserRespository userRespository) {
this.userRespository = userRespository;
}
@GetMapping("/user/all")
Iterable<UserModel> all() {
return userRespository.findAll();
}
@GetMapping("/user/{id}")
UserModel userById(@PathVariable Long id) {
return userRespository.findById(id).orElseThrow(() -> new ResponseStatusException(
HttpStatus.NOT_FOUND));
}
@PostMapping("/user/save")
UserModel save(@RequestBody UserModel user) {
return userRespository.save(user);
}
}
Archivo application.properties
Defines en el archivo la configuración que tendrá la base de datos con la url de la conexión, el username y el password. Veremos más adelante que estos valores por default salen de la imagen PostgeSql que usaremos en el archivo de configuración del docker compose.
La propiedad spring.jpa.hibernate.ddl-auto tiene estas opciones create, create-drop, validate, update De la documentación de spring tenemos:
- create: crea el schema de la base de datos destruyendo los datos.
- create-drop: borra el schema al finalizar la sesión.
- validate: solo valida el schema sin realizar cambios en las tablas de base de datos.
- update: actualiza el schema con los cambios que hagas en tus entidades.
Archivo _resources/application.properties _ .
spring.datasource.url=jdbc:postgresql://dbpostgresql:5432/mydb
spring.datasource.username=postgres
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=create
Configuración de Docker para Spring Boot con PostgreSQL
El archivo Dockerfile
En el archivo de Dockerfile le daremos las siguientes instrucciones a Docker.
FROM openjdk:8-jdk-alpine
MAINTAINER gustavopeiretti.com
VOLUME /tmp
EXPOSE 8080
ADD build/libs/springbootpostgresqldocker-0.0.1-SNAPSHOT.jar springbootpostgresqldocker.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/springbootpostgresqldocker.jar"]
FROM: usas aqui una (imagen de Docker)[https://hub.docker.com/_/openjdk] con un jdk8 y un server linux alpine.
MAINTAINER: datos de contacto
VOLUME: la carpeta donde se trabajara
EXPOSE: el puerto que se expondrá
ADD : copia el jar file de nuestra aplicación springbootpostgresqldocker-0.0.1-SNAPSHOT.ja en el contenedor docker con el nombre springbootpostgresqldocker.jar
ENTRYPOINT : ejecuta la sentencia al arrancar el contenedor docker
El archivo docker-compose.yml
Debes crear un archivo docker-compose.yml en el cual vas a establecer dos servicios.
El primer servicio que llamarás app hace referencia al servicio de SpringBoot que configuraste en el Dockerfile. Dentro de ese servicio la instrucción build indica que ese servicio viene del Dockerfile que previamente definiste.
El segundo servicio que llamarás dbpostgresql utiliza una imagen postgresql del hub de docker que docker descargará de allí. Dejamos el password, user, y nombre de la db que viene por defecto.
version: '3.1'
services:
app:
container_name: app-springboot-postgresql
image: app-springboot-postgresql
build: ./
ports:
- "8080:8080"
depends_on:
- dbpostgresql
dbpostgresql:
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_USER=postgres
- POSTGRES_DB=mydb
Ejecutar SpringBoot con PostgreSQL en el contenedor Docker
Build de tu proyecto para crear el archivo jar
En este ejemplo estamos usando gradlew. Por lo que lo que debes hacer es un build de este modo:
./gradlew build
Esto dejará el archivo jar de tu proyecto en la carpeta /build/libs de tu proyecto.
Build de docker compose para crear la imagen y ejecutar la aplicación dentro de docker
Luego de haber hecho un build de tu proyecto y tener disponible el archivo jar, puedes lanzar el contenedor.
docker-compose up --build
Probar tu aplicación Spring Boot + PostgreSQL + Docker
Recuerda que habíamos creado previamente un UserController con un post para guardar el User y un get para obtener los usuarios Ahora ejecutas este post. Observa que guardas un Usuario y el response te devuelve el mismo User con el id ya asignado.
Post /user/save
curl -s -X POST \
http://localhost:8080/user/save \
-H 'Content-Type: application/json' \
-d '{"name":"Moana"}'
Luego haces un get con el ID que del nuevo usuario que guardaste previamente.
Get /user/save
curl -s -X GET \
http://localhost:8080/user/1
Conclusión:
En este post creaste una app simple con Spring Boot utilizando dos imágenes de Docker. La primera para el servicio de SpringBoot y la segunda para PostgreSQL. Ejecutaste el contenedor de Docker con las imágenes y luego guardaste un nuevo User en la base de datos PostgreSQL utilizando los rest point que definiste para el User.
El código :
Como siempre puedes ver este código en github y gitlab.
https://github.com/gustavopeiretti/springboot-postgresql-docker-example
https://gitlab.com/gustavopeiretti/springboot-postgresql-docker-example