Docker Compose : Spring Boot + PostgreSQL
Pourquoi Docker Compose : Spring Boot + PostgreSQL ?
Docker Compose est une outil de configuration et d'orchestration multi-conteneur pour les applications modernes en utilisant Docker. Il permet aux développeurs de définir et exécuter des applications avec plusieurs conteneurs en utilisant un simple fichier docker-compose.yml. Dans le contexte du développement Spring Boot, PostgreSQL est une base de données SQL populaire utilisée pour stocker des données persistantes.
Un cas d'usage concret pourrait être l'utilisation d'un service de gestionnaire de tâches. Vous voudriez peut-être exécuter un backend Spring Boot qui utilise PostgreSQL pour stocker les tâches, tout en développant le frontend en React ou Angular dans un autre conteneur.
Prerequis
- Connaissance Java et Spring Boot
- Familiarité avec Docker
- Postgres installé sur votre machine (ou accès à une base de données Postgres existante)
- Installation de Docker Compose
Outils à installer :
- JDK 1.8 ou plus tard
- Maven ou Gradle pour le build du projet
- Docker CE
- Docker Compose
Concepts fondamentaux
1. Dockerfile
Le Dockerfile est un fichier texte qui contient des instructions pour construire une image Docker.
## Définit la base d'image sur laquelle se basera le conteneur
FROM openjdk:17-jdk-slim
## Copie les fichiers de l'application dans le conteneur
COPY target/myapp.jar /app/myapp.jar
## Expose le port 8080 pour l'application Spring Boot
EXPOSE 8080
## Démarre l'application Spring Boot
CMD ["java", "-jar", "/app/myapp.jar"]
2. docker-compose.yml
Le docker-compose.yml définit et configure les services, les réseaux et les volumes pour une application multi-conteneur.
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/myapp
- SPRING_DATASOURCE_USERNAME=myuser
- SPRING_DATASOURCE_PASSWORD=mypassword
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
Mise en pratique : projet fil rouge
Étape 1 : Créer le projet Spring Boot
Créons un nouveau projet Spring Boot avec les dépendances suivantes :
- Spring Web
- Spring Data JPA
- PostgreSQL Driver
mvn archetype:generate -DgroupId=com.example -DartifactId=myapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
cd myapp
Étape 2 : Créer le modèle et l'entité JPA
Créons une entité Task pour stocker les tâches.
package com.example.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
private boolean completed;
// Getters and Setters
}
Étape 3 : Créer le repository JPA
Créons un repository pour gérer les opérations CRUD sur la table Task.
package com.example.repository;
import com.example.model.Task;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TaskRepository extends JpaRepository<Task, Long> {
}
Étape 4 : Créer le controller REST
Créons un contrôleur pour exposer des endpoints pour gérer les tâches.
package com.example.controller;
import com.example.model.Task;
import com.example.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/tasks")
public class TaskController {
@Autowired
private TaskRepository taskRepository;
@GetMapping
public List<Task> getAllTasks() {
return taskRepository.findAll();
}
@PostMapping
public Task createTask(@RequestBody Task task) {
return taskRepository.save(task);
}
@PutMapping("/{id}")
public Task updateTask(@PathVariable Long id, @RequestBody Task taskDetails) {
Task task = taskRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Task not found with id " + id));
task.setDescription(taskDetails.getDescription());
task.setCompleted(taskDetails.isCompleted());
return taskRepository.save(task);
}
@DeleteMapping("/{id}")
public void deleteTask(@PathVariable Long id) {
Task task = taskRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Task not found with id " + id));
taskRepository.delete(task);
}
}
Étape 5 : Créer le fichier docker-compose.yml
Créons un docker-compose.yml pour définir les services du projet.
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/myapp
SPRING_DATASOURCE_USERNAME: myuser
SPRING_DATASOURCE_PASSWORD: mypassword
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
Étape 6 : Construire et exécuter le projet avec Docker Compose
Construisons l'image du conteneur et démarrons les services.
docker-compose up --build
Erreurs frequentes et debugging
Erreur 1: Connection to database failed
Code incorrect :
spring.datasource.url=jdbc:mysql://localhost:3306/myapp
Code correct :
spring.datasource.url=jdbc:postgresql://db:5432/myapp
Erreur 2: Unable to start embedded database
Code incorrect :
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Code correct :
spring.datasource.driver-class-name=org.postgresql.Driver
Erreur 3: Could not connect to server: Connection refused
Cause : Le conteneur de base de données n'est pas prêt à accepter les connexions.
Solution : Ajoutez une dépendance dans le docker-compose.yml pour attendre que le service soit prêt avant de démarrer l'application.
depends_on:
db:
condition: service_healthy
Pour aller plus loin
1. Utilisation de volumes Docker
Les volumes permettent de persister les données même après la suppression d'un conteneur.
2. Sécurité des bases de données
Utilisez des mots de passe forts et configurez l'accès à votre base de données en fonction des besoins.
Configuration de sécurité pour PostgreSQL
3. Monitoring et logging
Ajoutez des outils comme Prometheus et Grafana pour surveiller les performances de vos conteneurs et leurs applications.
Docker Compose avec Prometheus et Grafana
Défi pratique
Créez un service CLI (Command Line Interface) qui interagit avec votre API Spring Boot pour ajouter, modifier et supprimer des tâches. Utilisez Docker Compose pour exécuter le CLI dans le même réseau que votre application Spring Boot.
Ce tutoriel a couvert les concepts de base de Docker Compose en utilisant un projet Spring Boot avec PostgreSQL. Vous avez appris à créer une image Docker, à configurer un fichier docker-compose.yml, et à construire et exécuter un projet multi-conteneur. Vous avez également été guidé à travers des erreurs courantes lors du développement d'applications avec Docker Compose.