Container sind heute ein unverzichtbares Werkzeug für die Softwareentwicklung. Das Ausführen von Anwendungen in jeder Umgebung wird einfach, wenn Sie Container nutzen.
Die beliebteste Technologie zum Ausführen von Containern ist Docker, das auf jedem Betriebssystem ausgeführt werden kann.
In diesem Blogbeitrag erfahren Sie, wie Sie Docker für die 3 wichtigsten Anwendungsfälle verwenden. Sie werden lernen, wie man:
- eine Datenbank lokal mit Docker ausführen,
- automatische Tests mit einer dockerisierten Datenbank ausführen
- Führen Sie Ihre Anwendung lokal und in der Produktion mit Docker aus.
Sie verwenden eine Java Spring Boot-Anwendung, aber alle Erkenntnisse gelten für jede andere Programmiersprache Ihrer Wahl.
Um alle Beispiele auszuführen, müssen Sie:
- Installieren Sie Docker
- Installieren Sie Java
Führen Sie isolierte Anwendungen mit Docker aus
Docker nimmt sich wiederholende, alltägliche Konfigurationsaufgaben ab und wird während des gesamten Entwicklungslebenszyklus für eine schnelle, einfache und portable Anwendungsentwicklung verwendet – Desktop und Cloud. (Quelle:https://www.docker.com/use-cases/)
Der Kern der Supermacht von Docker besteht darin, sogenannte Cgroups zu nutzen, um leichtgewichtige, isolierte, tragbare und leistungsstarke Umgebungen zu erstellen, die Sie in Sekundenschnelle starten können.
Sehen wir uns an, wie Sie Docker nutzen können, um produktiver zu sein.
Datenbankcontainer
Mit Docker können Sie viele Arten von Datenbanken in Sekundenschnelle starten. Es ist einfach und belastet Ihr lokales System nicht mit anderen Anforderungen, die Sie zum Ausführen der Datenbank benötigen. Alles wird mit dem Docker-Container geliefert.
Wenn Sie hub.docker.com durchsuchen, finden Sie gebrauchsfertige Container für viele Datenbanken.
Mit dem docker run
Befehl können Sie einen MySQL-Docker-Container starten.
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
Dieser Befehl verwendet erweiterte Funktionen zum Ausführen eines Docker-Containers:
-v "$PWD/data"
bildet Ihr lokales Verzeichnis./data
ab zum Docker-Container, mit dem Sie den Docker-Container starten können, ohne Ihre Daten zu verlieren,-p 3306:3306
bildet den Containerport3306
ab zu unserem Computer, damit andere Anwendungen ihn verwenden können,-e MYSQL_DATABASE=my-database
setzt eine Umgebungsvariable, um eine neue Datenbank namensmy-database
zu erstellen automatisch,-e MYSQL_ROOT_PASSWORD=admin-password
setzt eine Umgebungsvariable, um das Admin-Passwort festzulegen,--rm
entfernt den Container, wenn er gestoppt wird.
Diese Umgebungsvariablen und mehr sind auf der Seite des Docker-Images dokumentiert.
Verwendung von Datenbankcontainern für die Entwicklung
Sie verwenden einen beliebten Tech-Stack, um eine Webanwendung auf der Grundlage von Java und Spring Boot zu erstellen. Um sich auf die Docker-Teile zu konzentrieren, können Sie eine einfache Demo-Anwendung aus dem offiziellen Accessing JPA Data With Rest Guide klonen.
# Download the sample application
git clone https://github.com/spring-guides/gs-accessing-data-rest.git
# Open the final application folder
cd complete
Die Anwendung wird mit einer In-Memory-Datenbank geliefert, die für die Produktion nicht wertvoll ist, da mehrere Dienste nicht auf eine einzelne Datenbank zugreifen und diese mutieren können. Eine MySQL-Datenbank ist besser geeignet, um Ihre Anwendung auf viel mehr Lese- und Schreibvorgänge zu skalieren.
Fügen Sie daher den MySQL-Treiber zu Ihrer pom.xml
hinzu :
<!-- 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>
Jetzt müssen Sie die Konfiguration hinzufügen, um eine Verbindung zu Ihrer Datenbank herzustellen, indem Sie eine Konfigurationsdatei src/main/resources/application.properties
hinzufügen .
# 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
Sie können nun die Anwendung starten und vorhandene Endpunkte aufrufen:
# 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
Sie haben Ihre rudimentäre Anwendung, die Daten in Ihre Datenbank schreibt und liest, erfolgreich verwendet. Durch die Verwendung der MySQL-Docker-Datenbank erhalten Sie in Sekundenschnelle eine robuste Datenbank, die Sie von jeder Anwendung aus verwenden können.
Verwendung von Datenbankcontainern für Integrationstests
Die Anwendung verfügt bereits über Tests, die eine laufende Datenbank erwarten. Da Sie jedoch Ihre In-Memory-Datenbank durch eine echte MySQL-Datenbank ersetzt haben, werden Tests nicht erfolgreich ausgeführt, wenn Sie Ihre Datenbank stoppen.
# 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 ...
Um Container, die Tests ausführen, schnell zu starten und zu stoppen, gibt es ein praktisches Tool namens testcontainers. Dort finden Sie Bibliotheken für viele Programmiersprachen, einschließlich Java.
Zuerst müssen Sie einige Abhängigkeiten zu Ihrer pom.xml
hinzufügen :
<!-- 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>
Sie müssen die Tests aktualisieren, um die Testcontainer zu verwenden, die die Datenbank bei jedem Testlauf starten. Fügen Sie dem Test eine Anmerkung und ein Feld hinzu, um ihn zu verwenden:
//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);
}
Bei jeder Testausführung wird die Datenbank für Sie gestartet, sodass Sie beim Ausführen von Tests eine tatsächliche Datenbank verwenden können. Die gesamte Verkabelung, Einrichtung, Inbetriebnahme und Reinigung werden für Sie erledigt.
Dockerisieren Sie Ihre Anwendung
Das Dockerisieren Ihrer Anwendung mit einfachen Docker-Tools ist möglich, wird jedoch nicht empfohlen.
Sie können Ihre Anwendung erstellen, einen Basiscontainer verwenden, der Java enthält, und Ihre Anwendung kopieren und ausführen. Aber es gibt viele Fallstricke, und das gilt für jede Sprache und jedes Framework. Suchen Sie also immer nach Tools, die Ihnen das Leben erleichtern.
In diesem Beispiel verwenden Sie Jib- und Distributionslose Container, um auf einfache Weise einen Docker-Container zu erstellen. Wenn Sie beides in Kombination verwenden, erhalten Sie einen minimalen, sicheren und reproduzierbaren Container, der lokal und in der Produktion auf die gleiche Weise funktioniert.
Um Jib zu verwenden, müssen Sie es als Maven-Plugin hinzufügen, indem Sie es zu Ihrer pom.xml
hinzufügen :
<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>
Sie können jetzt das Image erstellen und die Anwendung ausführen:
# 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)
Die Anwendung wird mit Netzwerkmodus-Host --net=host
gestartet , was es einfach macht, sich einfach mit der Datenbank zu verbinden, die Sie gestartet haben. Alternativ können Sie ein docker network
erstellen und beide im selben Netzwerk starten.
Sie können Ihren Container per Push in eine Containerregistrierung übertragen und von jedem Container-Orchestrierungstool darauf verweisen, um Ihre Anwendung in der Produktion auszuführen.