Exécuter Spring Boot avec PostgreSQL dans Docker Compose

1. Introduction

Dans ce didacticiel, nous voulons exécuter une application Spring Boot avec la base de données open-source populaire PostgreSQL. Dans un article précédent, nous avons examiné Docker Compose pour gérer plusieurs conteneurs à la fois . Ainsi, au lieu d'installer PostgreSQL en tant qu'application distincte, nous utiliserons Docker Compose pour exécuter Spring Boot et PostgreSQL .

2. Création du projet Spring Boot

Passons à Spring Initializer et créons notre projet Spring Boot . Nous ajouterons le pilote PostgreSQL et les modules Spring Data JPA . Après avoir téléchargé le fichier ZIP résultant et l'avoir extrait dans un dossier, nous pouvons exécuter notre nouvelle application:

./mvnw spring-boot:run

L'application échoue car elle ne peut pas se connecter à la base de données:

*************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class 

3. Dockerfile

Avant de pouvoir démarrer PostgreSQL avec Docker Compose, nous devons transformer notre application Spring Boot en une image Docker . La première étape consiste à empaqueter l'application sous forme de fichier JAR:

./mvnw clean package -DskipTests

Ici, nous nettoyons d'abord nos versions précédentes avant d'empaqueter l'application. De plus, nous sautons les tests car ils échouent sans PostgreSQL.

Nous avons maintenant un fichier JAR d'application dans le répertoire cible . Ce fichier a le nom du projet et le numéro de version dans son nom et se termine par -SNAPSHOT.jar . Son nom pourrait donc être docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar .

Créons le nouveau répertoire src / main / docker . Après cela, nous y copions le fichier JAR de l'application:

cp target/docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar src/main/docker

Enfin, nous créons ce Dockerfile dans ce même répertoire:

FROM adoptopenjdk:11-jre-hotspot ARG JAR_FILE=*.jar COPY ${JAR_FILE} application.jar ENTRYPOINT ["java", "-jar", "application.jar"]

Ce fichier décrit comment Docker doit exécuter notre application Spring Boot . Il utilise Java 11 d'AdoptOpenJDK et copie le fichier JAR de l' application dans application.jar . Il exécute ensuite ce fichier JAR pour démarrer notre application Spring Boot.

4. Fichier de composition Docker

Maintenant, écrivons notre fichier Docker Compose, docker-compose.yml , et sauvegardons-le dans src / main / docker :

version: '2' services: app: image: 'docker-spring-boot-postgres:latest' build: context: . container_name: app depends_on: - db environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/compose-postgres - SPRING_DATASOURCE_USERNAME=compose-postgres - SPRING_DATASOURCE_PASSWORD=compose-postgres - SPRING_JPA_HIBERNATE_DDL_AUTO=update db: image: 'postgres:13.1-alpine' container_name: db environment: - POSTGRES_USER=compose-postgres - POSTGRES_PASSWORD=compose-postgres

Le nom de notre application est app. C'est le premier des deux services (lignes 4-15):

  • L'image Spring Boot Docker porte le nom docker-spring-boot-postgres: latest (ligne 5). Docker construit cette image à partir du Dockerfile dans le répertoire actuel (lignes 6-7)
  • Le nom du conteneur est app (ligne 8). Cela dépend du service db (ligne 10). C'est pourquoi il commence après le conteneur db
  • Notre application utilise le conteneur db PostgreSQL comme source de données (ligne 12). Le nom de la base de données, le nom d'utilisateur et le mot de passe sont tous compose-postgres (lignes 12-14)
  • Hibernate créera ou mettra à jour automatiquement toutes les tables de base de données nécessaires (ligne 15)

La base de données PostgreSQL porte le nom db et est le deuxième service (lignes 17-22):

  • Nous utilisons PostgreSQL 13.1 (ligne 18)
  • Le nom du conteneur est db (ligne 19)
  • Le nom d'utilisateur et le mot de passe sont tous deux compose-postgres (lignes 21-22)

5. Exécution avec Docker Compose

Exécutons notre application Spring Boot et PostgreSQL avec Docker Compose :

docker-compose up

Tout d'abord, cela créera l'image Docker pour notre application Spring Boot. Ensuite, il démarrera un conteneur PostgreSQL. Enfin, il lancera notre application image Docker. Cette fois, notre application fonctionne bien:

Starting DemoApplication v0.0.1-SNAPSHOT using Java 11.0.9 on f94e79a2c9fc with PID 1 (/application.jar started by root in /) [...] Finished Spring Data repository scanning in 28 ms. Found 0 JPA repository interfaces. [...] Started DemoApplication in 4.751 seconds (JVM running for 6.512)

Comme nous pouvons le voir, Spring Data n'a trouvé aucune interface de référentiel. C'est exact - nous n'en avons pas encore créé!

Si nous voulons arrêter tous les conteneurs, nous devons d'abord appuyer sur [Ctrl-C]. Ensuite, nous pouvons arrêter Docker Compose:

docker-compose down

6. Création d'une entité client et d'un référentiel

Pour utiliser la base de données PostgreSQL dans notre application, nous allons créer une entité client simple :

@Entity @Table(name = "customer") public class Customer { @Id @GeneratedValue private long id; @Column(name = "first_name", nullable = false) private String firstName; @Column(name = "last_name", nullable = false) private String lastName;

Le client a un attribut id généré et deux attributs obligatoires: firstName et lastName .

Maintenant, nous pouvons écrire l'interface du référentiel pour cette entité :

public interface CustomerRepository extends JpaRepository { }

En étendant simplement JpaRepository , nous héritons des méthodes de création et d'interrogation de notre entité Client .

Enfin, nous utiliserons ces méthodes dans notre application:

@SpringBootApplication public class DemoApplication { @Autowired private CustomerRepository repository; @EventListener(ApplicationReadyEvent.class) public void runAfterStartup() { List allCustomers = this.repository.findAll(); logger.info("Number of customers: " + allCustomers.size()); Customer newCustomer = new Customer(); newCustomer.setFirstName("John"); newCustomer.setLastName("Doe"); logger.info("Saving new customer..."); this.repository.save(newCustomer); allCustomers = this.repository.findAll(); logger.info("Number of customers: " + allCustomers.size()); } }
  • Nous accédons à notre référentiel client via l'injection de dépendances
  • Nous interrogeons le nombre de clients existants avec le référentiel - ce sera zéro
  • Ensuite, nous créons et sauvegardons un client
  • When we then query the existing customers again, we expect to find the one we just created

7. Running with Docker Compose Again

To run the updated Spring Boot application, we need to rebuild it first. Therefore, we execute these commands once more in the project root directory:

./mvnw clean package -DskipTests cp target/docker-spring-boot-postgres-0.0.1-SNAPSHOT.jar src/main/docker

How do we rebuild our Docker image with this updated application JAR file? The best way is to remove the existing Docker image whose name we specified in the docker-compose.yml. This forces Docker to build the image again the next time we start our Docker Compose file:

cd src/main/docker docker-compose down docker rmi docker-spring-boot-postgres:latest docker-compose up

So after stopping our containers, we delete the application Docker image. We then start our Docker Compose file again, which rebuilds the application image.

Here's the application output:

Finished Spring Data repository scanning in 180 ms. Found 1 JPA repository interfaces. [...] Number of customers: 0 Saving new customer... Number of customers: 1

Spring Boot trouve notre référentiel client vide. Par conséquent, nous commençons sans client, puis nous en créons un avec succès.

8. Conclusion

Dans ce court tutoriel, nous avons commencé par créer une application Spring Boot pour PostgreSQL. Ensuite, nous avons écrit un fichier Docker Compose pour exécuter notre conteneur d'application avec un conteneur PostgreSQL.

Enfin, nous avons créé une entité client et un référentiel, ce qui nous a permis de sauvegarder un client dans PostgreSQL.

Comme d'habitude, le code source de ce tutoriel se trouve à l'adresse over sur GitHub.