Les conteneurs sont un outil essentiel pour le développement de logiciels aujourd'hui. L'exécution d'applications dans n'importe quel environnement devient facile lorsque vous exploitez des conteneurs.
La technologie la plus populaire pour exécuter des conteneurs est Docker, qui s'exécute sur n'importe quel système d'exploitation.
Dans cet article de blog, vous apprendrez à utiliser Docker pour les 3 cas d'utilisation les plus essentiels. Vous apprendrez à :
- exécuter une base de données localement à l'aide de Docker,
- exécuter des tests automatisés à l'aide d'une base de données dockerisée,
- exécutez votre application localement et en production à l'aide de Docker.
Vous utiliserez une application Java Spring Boot, mais tous les apprentissages s'appliquent à tous les autres langages de programmation de votre choix.
Pour exécuter tous les exemples, vous devez :
- Installer Docker
- Installer Java
Exécuter des applications isolées à l'aide de Docker
Docker supprime les tâches de configuration répétitives et banales et est utilisé tout au long du cycle de vie du développement pour un développement d'applications rapide, facile et portable - sur ordinateur et dans le cloud. (Source :https://www.docker.com/use-cases/)
Le cœur de la superpuissance de Docker est d'exploiter ce que l'on appelle les cgroups pour créer des environnements légers, isolés, portables et performants, que vous pouvez démarrer en quelques secondes.
Voyons comment vous pouvez utiliser Docker pour être plus productif.
Conteneurs de base de données
Avec Docker, vous pouvez démarrer de nombreux types de bases de données en quelques secondes. C'est facile et cela ne pollue pas votre système local avec d'autres exigences dont vous avez besoin pour exécuter la base de données. Tout est livré avec le conteneur Docker.
En recherchant hub.docker.com, vous pouvez trouver des conteneurs prêts à l'emploi pour de nombreuses bases de données.
Utilisation de l'docker run
commande, vous pouvez démarrer un conteneur MySQL Docker.
docker run --rm -v "$PWD/data":/var/lib/mysql --name mysql -e MYSQL_ROOT_PASSWORD=admin-password -e MYSQL_DATABASE=my-database -p 3306:3306 mysql:8.0.28-debian
Cette commande utilise des fonctionnalités avancées d'exécution d'un conteneur Docker :
-v "$PWD/data"
mappe votre répertoire local./data
au conteneur Docker, ce qui vous permet de démarrer le conteneur Docker sans perdre vos données,-p 3306:3306
mappe le port conteneur3306
à notre machine afin que d'autres applications puissent l'utiliser,-e MYSQL_DATABASE=my-database
définit une variable d'environnement pour créer une nouvelle base de données appeléemy-database
automatiquement,-e MYSQL_ROOT_PASSWORD=admin-password
définit une variable d'environnement pour définir le mot de passe administrateur,--rm
supprime le conteneur à l'arrêt.
Ces variables d'environnement et bien d'autres sont documentées sur la page de l'image Docker.
Comment utiliser les conteneurs de base de données pour le développement
Vous utiliserez une pile technologique populaire pour créer une application Web basée sur Java et Spring Boot. Pour vous concentrer sur les parties Docker, vous pouvez cloner une application de démonstration simple à partir du guide officiel d'accès aux données JPA avec Rest.
# Download the sample application
git clone https://github.com/spring-guides/gs-accessing-data-rest.git
# Open the final application folder
cd complete
L'application est livrée avec une base de données en mémoire, qui n'est pas utile pour la production car elle ne permet pas à plusieurs services d'accéder et de muter une seule base de données. Une base de données MySQL est plus adaptée pour faire évoluer votre application vers de nombreuses autres lectures et écritures.
Par conséquent, ajoutez le pilote MySQL à votre pom.xml
:
<!-- Disable in memory database -->
<!--
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
-->
<!-- MySQL driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
Maintenant, vous devez ajouter la configuration pour vous connecter à votre base de données en ajoutant un fichier de configuration src/main/resources/application.properties
.
# Database configuration
spring.datasource.url=jdbc:mysql://localhost:3306/my-database
spring.datasource.username=root
spring.datasource.password=admin-password
# Create table and database automatically
spring.jpa.hibernate.ddl-auto=update
Vous pouvez maintenant démarrer l'application et appeler les points de terminaison existants :
# Get all people
curl http://localhost:8080/people
# Add a person
curl -i -H "Content-Type:application/json" -d '{"firstName": "Frodo", "lastName": "Baggins"}' http://localhost:8080/people
# Get all people again, which now returns the created person
curl http://localhost:8080/people
Vous avez utilisé avec succès votre application rudimentaire, qui écrit et lit des données dans votre base de données. L'utilisation de la base de données MySQL Docker vous donne une base de données robuste en quelques secondes, et vous pouvez l'utiliser à partir de n'importe quelle application.
Comment utiliser les conteneurs de base de données pour les tests d'intégration
L'application a déjà des tests qui attendent une base de données en cours d'exécution. Mais, comme vous avez remplacé votre base de données en mémoire par une véritable base de données MySQL, les tests ne fonctionneront pas correctement si vous arrêtez votre base de données.
# Stop database
docker rm -f mysql
# Run tests
./mvnw clean test
... skipped output ...
[ERROR] Tests run: 7, Failures: 0, Errors: 7, Skipped: 0
... skipped output ...
Pour démarrer et arrêter rapidement les conteneurs en cours d'exécution de tests, il existe un outil pratique appelé testcontainers. Vous y trouverez des bibliothèques pour de nombreux langages de programmation, y compris Java.
Tout d'abord, vous devez ajouter des dépendances à votre pom.xml
:
<!-- testcontainer -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.16.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.16.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.16.3</version>
<scope>test</scope>
</dependency>
Vous devez mettre à jour les tests pour utiliser les testcontainers, qui démarrent la base de données à chaque exécution de test. Ajoutez une annotation et un champ au test pour en faire usage :
//added imports
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@SpringBootTest
@AutoConfigureMockMvc
@Testcontainers // Annotation to enable testcontainers
public class AccessingDataRestApplicationTests {
// Field to access the started database
@Container
private static MySQLContainer database = new MySQLContainer<>("mysql:5.7.34");
//Set database configuration using the started database
@DynamicPropertySource
static void databaseProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", database::getJdbcUrl);
registry.add("spring.datasource.username", database::getUsername);
registry.add("spring.datasource.password", database::getPassword);
}
Pour chaque exécution de test, la base de données est démarrée pour vous, ce qui vous permet d'utiliser une base de données réelle lorsque vous exécutez des tests. Tout le câblage, la configuration, le démarrage et le nettoyage sont faits pour vous.
Dockeriser votre application
Dockeriser votre application à l'aide d'outils Docker simples est possible mais non recommandé.
Vous pouvez créer votre application, utiliser un conteneur de base contenant Java et copier et exécuter votre application. Mais il y a beaucoup d'écueils, et c'est le cas pour tous les langages et frameworks. Cherchez donc toujours des outils qui vous facilitent la vie.
Dans cet exemple, vous utiliserez des conteneurs Jib et distroless pour créer facilement un conteneur Docker. L'utilisation des deux en combinaison vous donne un conteneur minimal, sécurisé et reproductible, qui fonctionne de la même manière localement et en production.
Pour utiliser Jib, vous devez l'ajouter en tant que plugin maven en l'ajoutant à votre pom.xml
:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Jib plugin -->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<from>
<image>gcr.io/distroless/java17:nonroot</image>
</from>
<to>
<image>my-docker-image</image>
</to>
</configuration>
</plugin>
</plugins>
</build>
Vous pouvez maintenant créer l'image et exécuter l'application :
# build the docker container
./mvnw compile jib:dockerBuild
# find your build image
docker images
# start the database
docker run --rm -v "$PWD/data":/var/lib/mysql --name mysql -e MYSQL_ROOT_PASSWORD=admin-password -e MYSQL_DATABASE=my-database -p 3306:3306 mysql:8.0.28-debian
# start the docker container which contains your application
docker run --net=host my-docker-image
… skipped output…
2022-04-15 17:43:51.509 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-15 17:43:51.521 INFO 1 --- [ main] c.e.a.AccessingDataRestApplication : Started AccessingDataRestApplication in 6.146 seconds (JVM running for 6.568)
L'application est démarrée avec l'hôte en mode réseau --net=host
, ce qui facilite la connexion à la base de données que vous avez démarrée. Alternativement, vous pouvez créer un docker network
et démarrez les deux sur le même réseau.
Vous pouvez pousser votre conteneur vers un registre de conteneurs et le référencer à partir de n'importe quel outil d'orchestration de conteneurs pour exécuter votre application en production.