


Erstellen eines Docker-Images der Spring Boot-Anwendung mithilfe von Buildpacks
Einführung
Sie haben eine Spring Boot-Anwendung erstellt. Es funktioniert hervorragend auf Ihrem lokalen Computer und jetzt müssen Sie die Anwendung woanders bereitstellen. Auf einigen Plattformen können Sie die JAR-Datei direkt übermitteln und sie wird bereitgestellt. An manchen Orten können Sie eine virtuelle Maschine starten, dort den Quellcode herunterladen, ihn erstellen und ausführen. Meistens müssen Sie die Anwendung jedoch mithilfe von Containern bereitstellen. Meistens wird Docker verwendet, um das Image in einem Container zu erstellen und auszuführen. Wenn Sie die JAR-Datei auf einige Plattformen hochladen, wird die Anwendung außerdem in einem Container unter der Haube ausgeführt.
In diesem Blog werden wir drei verschiedene Möglichkeiten sehen, ein Docker-Image für die jeweilige Spring Boot-Anwendung zu erstellen. Fangen wir an:
Grundlegendes Container-Image
Der naive und unzureichende Weg, das Docker-Image für jede Anwendung zu erstellen, besteht darin, eine einfache Docker-Datei zu verwenden, die die JAR-Datei in das Image kopiert und sie mit dem Befehl java -jar ausführt.
Erstellen Sie eine Docker-Datei
Hier ist die Docker-Datei, die Sie im Stammverzeichnis des Projekts ablegen können:
FROM eclipse-temurin:21-jre-ubi9-minimal ARG JAR_FILE COPY ${JAR_FILE} application.jar ENTRYPOINT ["java", "-jar", "/application.jar"]
Wir haben ein Argument JAR_FILE angegeben, das den Speicherort der zu verwendenden JAR-Datei angibt.
Docker-Image erstellen
Nachdem die obige Docker-Datei erstellt wurde, werden die folgenden Schritte verwendet, um das Docker-Image zu erstellen:
-
Erstellen Sie die JAR-Datei für das Spring Boot-Projekt:
./gradlew bootJar # For Gradle build system
ODER
./mvnw spring-boot:build-jar # For Maven build system
-
Verwenden Sie die Docker-Datei, um das Docker-Image mit der neuesten JAR-Datei zu erstellen. Ersetzen Sie im folgenden Befehl {IMAGE_NAME} durch den erforderlichen Bildnamen und {JAR_FILE} durch den Pfad zur generierten JAR-Datei. Der Bildname enthält auch ein Tag, etwa – mycompany/product-service:0.0.1-SNAPSHOT:
docker build --build-arg JAR_FILE={JAR_FILE} --tag {IMAGE_NAME} .
-
Überprüfen Sie mit dem folgenden Befehl, ob das Docker-Image erstellt wurde. Sie sollten das Bild mit dem im obigen Befehl angegebenen Namen sehen können:
docker images
Effizientes Container-Image mit Layered Jar
Obwohl es möglich und einfach ist, ein Spring Boot-Uber-Jar als Docker-Image zu packen (wie in der vorherigen Methode erwähnt), hat das Kopieren und Ausführen des Fat-Jars im Docker-Image viele Nachteile. Zum Beispiel
- Es entsteht ein gewisser Mehraufwand, wenn Uber Jar ausgeführt wird, ohne es zu entpacken.
- Es ist nicht optimal, den Code der Anwendung und alle ihre Abhängigkeiten in einer einzigen Ebene unterzubringen.
Da wir unseren Code häufiger kompilieren als die Spring Boot-Version aktualisieren, ist es besser, die Dinge etwas stärker zu trennen. Wenn wir diese JAR-Dateien (die selten geändert werden) in der Ebene vor der Anwendungsebene ablegen, muss Docker oft nur die unterste Ebene ändern und kann den Rest aus seinem Cache auswählen.
Aktivieren Sie Layered Jar
Um ein mehrschichtiges Docker-Image zu erstellen, müssen wir zuerst ein mehrschichtiges JAR erstellen. Heutzutage ist es in Gradle und Maven standardmäßig aktiviert. Sie können das mehrschichtige JAR-Verhalten mit der folgenden Einstellung aktivieren oder deaktivieren:
// build.gradle tasks.named("bootJar") { layered { enabled = false } }
// build.gradle.kts tasks.named<BootJar>("bootJar") { layered { enabled.set(false) } }
<!-- pom.xml --> <project> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layers> <enabled>true</enabled> </layers> </configuration> </plugin> </plugins> </build> </project>
Sie können sogar anpassen, wie die Ebenen erstellt werden. Informationen zur Gradle- oder Maven-Konfiguration finden Sie in der Dokumentation.
Erstellen Sie eine Docker-Datei
Unten finden Sie die Docker-Datei, mit der Sie die Vorteile des mehrschichtigen JAR nutzen und ein mehrschichtiges Docker-Image der Spring Boot-Anwendung erstellen können.
# Perform the extraction in a separate builder container FROM eclipse-temurin:21-jre-ubi9-minimal AS builder WORKDIR /builder # This points to the built jar file in the target folder # Adjust this to 'build/libs/*.jar' if you're using Gradle ARG JAR_FILE=target/*.jar # Copy the jar file to the working directory and rename it to application.jar COPY ${JAR_FILE} application.jar # Extract the jar file using an efficient layout RUN java -Djarmode=tools -jar application.jar extract --layers --destination extracted # This is the runtime container FROM eclipse-temurin:21-jre-ubi9-minimal WORKDIR /application # Copy the extracted jar contents from the builder container into the working directory in the runtime container # Every copy step creates a new docker layer # This allows docker to only pull the changes it really needs COPY --from=builder /builder/extracted/dependencies/ ./ COPY --from=builder /builder/extracted/spring-boot-loader/ ./ COPY --from=builder /builder/extracted/snapshot-dependencies/ ./ COPY --from=builder /builder/extracted/application/ ./ # Start the application jar - this is not the uber jar used by the builder # This jar only contains application code and references to the extracted jar files # This layout is efficient to start up and CDS friendly ENTRYPOINT ["java", "-jar", "application.jar"]
Docker-Image erstellen
Die Schritte zum Erstellen des mehrschichtigen Docker-Images sind dieselben wie zum Erstellen eines einfachen Docker-Images. Bitte schauen Sie dort nach.
Cloud Native Buildpacks
Was wäre, wenn ich Ihnen sage, dass Sie ein Docker-Image erstellen können, ohne eine Docker-Datei zu erstellen? Mit Cloud Native Buildpacks können wir Docker-Images direkt aus dem Gralde- oder Maven-Plugin erstellen. Einige Plattformen (wie Heroku oder Cloud Foundry) verwenden Buildpacks, um bereitgestellte JAR-Dateien in ausführbare Bilder zu konvertieren.
Spring Boot bietet Buildpack-Unterstützung direkt für Maven und Gradle. Wir müssen keine zusätzlichen Plugins einbinden. Führen Sie einfach den folgenden Befehl aus:
./gradlew bootBuildImage # For gradle build system
ODER
./mvnw spring-boot:build-image # For maven build system
Der obige Befehl generiert ein Bild mit dem Standardnamen {PROJECT_NAME}:${PROJECT_VERSION}. Wenn Sie den Namen des generierten Bildes konfigurieren möchten, können Sie die folgenden Schritte ausführen:
Konfigurieren Sie den Bildnamen für das Gradle-Build-System
Wir können die bootBuildImage-Aufgabe so konfigurieren, dass sie den Namen des Bildes festlegt:
// For build.gradle.kts val imagePrefix = "javarush" val dockerImageName = "docker-example" tasks.named<BootBuildImage>("bootBuildImage") { imageName.set("${imagePrefix}/${dockerImageName}:${version}") }
// For build.gradle def imagePrefix = "javarush" def dockerImageName = "docker-example" tasks.named("bootBuildImage") { imageName = "${imagePrefix}/${dockerImageName}:${version}" }
Konfigurieren Sie den Image-Namen für das Maven-Build-System
Wir können das Spring-Boot-Maven-Plugin so konfigurieren, dass es einen anderen Bildnamen verwendet, etwa so:
<properties> <imagePrefix>javarush</imagePrefix> </properties> ... <project> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <image> <name>${imagePrefix}/${project.artifactId}:${project.version}</name> </image> </configuration> </plugin> </plugins> </build> </project>
Konfigurieren Sie den Bildnamen, während Sie den Befehl ausführen
Wir können sogar den Namen des Bildes definieren, während wir den Befehl zum Erstellen des Bildes ausführen.
./gradlew bootBuildImage --imageName=javarush/docker-example:1.0.0 # For grade build system ./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=javarush/docker-example:1.0.0 # For maven build system
You can see the documentation to further configure Gradle or Maven plugin.
This is my go-to method to create a Docker image for any Spring Boot application.
Running Docker Container
Once you create a docker image, you need to make sure that it works as expected. After you make sure that the image is created, you can directly run it using the docker run command. For example,
docker run -p "8080:8080" {IMAGE_NAME}
But, this is not how images are used in production applications. Docker Compose is used to run and manage multiple docker images.
Conclusion
In this blog, we have seen how to build Docker images for Spring Boot applications using different methods. Being able to build docker images for your apps is a must skill to know because the image is what gets delivered. Thanks for reading the article till the end. I appreciate it. I will meet you in the next one. As always, all feedback and suggestions are welcome.
Das obige ist der detaillierte Inhalt vonErstellen eines Docker-Images der Spring Boot-Anwendung mithilfe von Buildpacks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undress AI Tool
Ausziehbilder kostenlos

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Java verwendet Wrapper-Klassen, da grundlegende Datentypen nicht direkt an objektorientierten Operationen teilnehmen können und Objektformen häufig in den tatsächlichen Bedürfnissen erforderlich sind. 1. Sammelklassen können nur Objekte speichern, z. B. Listen verwenden automatische Boxen, um numerische Werte zu speichern. 2. Generika unterstützen keine Grundtypen, und Verpackungsklassen müssen als Typparameter verwendet werden. 3.. Verpackungsklassen können Nullwerte darstellen, um nicht festgelegte oder fehlende Daten zu unterscheiden. 4. Verpackungsklassen bieten praktische Methoden wie String -Conversion, um die Analyse und Verarbeitung von Daten zu erleichtern. In Szenarien, in denen diese Eigenschaften benötigt werden, sind Verpackungsklassen unverzichtbar.

Der Unterschied zwischen HashMap und Hashtable spiegelt sich hauptsächlich in der Gewindesicherheit, der Nullwertunterstützung und der Leistung wider. 1. In Bezug auf die Gewindesicherheit ist Hashtable Thread-Safe, und seine Methoden sind hauptsächlich Synchronmethoden, während HashMap keine Synchronisationsverarbeitung durchführt, die nicht mit Thread-Safe ist. 2. In Bezug auf die Nullwertunterstützung ermöglicht HashMap einen Nullschlüssel und mehrere Nullwerte, während Hashtable keine Nullschlüssel oder -Werte zulässt, sonst wird eine Nullpointerexception geworfen. 3. In Bezug auf die Leistung ist HashMap effizienter, da kein Synchronisationsmechanismus vorhanden ist und Hashtable für jeden Vorgang eine niedrige Verriegelungsleistung aufweist. Es wird empfohlen, stattdessen eine Concurrenthashmap zu verwenden.

StaticMethodsinInterfaces -reisEtroducucuedInjava8toalloytilityFunctionSwitHinTheInterfaceItEp.beejava8, solche Funktionen, dieseparatehelperklassen, führendemTodisorganizedCode.Now, StaticMetheSprovidreefits: 1) theeneNableable -theenableaby

Der JIT -Compiler optimiert den Code durch vier Methoden: Methode Inline, Hotspot -Erkennung und -vergleich, Typespekulation und Devirtualisation sowie die Eliminierung des redundanten Betriebs. 1. Methode Inline reduziert den Anrufaufwand und fügt häufig kleine Methoden direkt in den Anruf ein. 2. Erkennung und Hochfrequenzcodeausführung und zentral optimieren, um Ressourcen zu sparen. 3. Typ Spekulation sammelt Informationen zum Laufzeittyp, um Devirtualisation -Anrufe zu erzielen und die Effizienz zu verbessern. 4. Redundante Operationen beseitigen nutzlose Berechnungen und Inspektionen basierend auf den Betriebsdaten, wodurch die Leistung verbessert wird.

Instanzinitialisierungsblöcke werden in Java verwendet, um die Initialisierungslogik beim Erstellen von Objekten auszuführen, die vor dem Konstruktor ausgeführt werden. Es ist für Szenarien geeignet, in denen mehrere Konstruktoren Initialisierungscode, komplexe Feldinitialisierung oder anonyme Szenarien der Klasseninitialisierung teilen. Im Gegensatz zu statischen Initialisierungsblöcken wird es jedes Mal ausgeführt, wenn es instanziiert wird, während statische Initialisierungsblöcke nur einmal ausgeführt werden, wenn die Klasse geladen wird.

InvaVa, theFinalKeywordPreventsAvariable von ValueFromBeingumedAfterasssignment, ButitsBehaviordiffersForprimitive und ANSPRIMITIVEVARIABLE, FinalMakesthevalueconstant, AsinfinalIntmax_speed = 100; WhirerastsignmentcausaSesSaSesSaSesSaSaSesSaSesSaSaSesSaSaSesSaSesSesirror

Es gibt zwei Arten von Konvertierung: implizit und explizit. 1. Die implizite Umwandlung erfolgt automatisch, wie z. B. das Konvertieren in INT in Doppel; 2. Explizite Konvertierung erfordert einen manuellen Betrieb, z. B. die Verwendung (int) MyDouble. Ein Fall, in dem die Typ -Konvertierung erforderlich ist, umfasst die Verarbeitung von Benutzereingaben, mathematische Operationen oder das Übergeben verschiedener Werte zwischen Funktionen. Probleme, die beachtet werden müssen, sind: Umdrehung von Gleitpunktzahlen in Ganzzahlen wird der fraktionale Teil abschneiden, große Typen in kleine Typen zu einem Datenverlust führen, und einige Sprachen ermöglichen keine direkte Konvertierung bestimmter Typen. Ein ordnungsgemäßes Verständnis der Regeln der Sprachkonvertierung hilft, Fehler zu vermeiden.

Der Werksmodus wird verwendet, um die Logik der Objekterstellung zusammenzufassen, wodurch der Code flexibler, einfach zu pflegen und locker gekoppelt ist. Die Kernantwort lautet: Durch zentrales Verwalten von Logik der Objekterstellung, das Ausblenden von Implementierungsdetails und die Unterstützung der Erstellung mehrerer verwandter Objekte. Die spezifische Beschreibung lautet wie folgt: Der Fabrikmodus gibt Objekterstellung an eine spezielle Fabrikklasse oder -methode zur Verarbeitung und vermeidet die Verwendung von NewClass () direkt; Es ist für Szenarien geeignet, in denen mehrere Arten von verwandten Objekten erstellt werden, die Erstellungslogik sich ändern und Implementierungsdetails versteckt werden müssen. Zum Beispiel werden im Zahlungsabwickler Stripe, PayPal und andere Instanzen durch Fabriken erstellt. Die Implementierung umfasst das von der Fabrikklasse zurückgegebene Objekt basierend auf Eingabeparametern, und alle Objekte erkennen eine gemeinsame Schnittstelle. Gemeinsame Varianten umfassen einfache Fabriken, Fabrikmethoden und abstrakte Fabriken, die für unterschiedliche Komplexitäten geeignet sind.
