Wie kann man ein Maven-Projekt andocken? und wie viele Möglichkeiten, dies zu erreichen?

87

Ich bin neu in Docker und weiß nicht, wie man ein Java-Projekt mit maven ausführt, obwohl ich viele Dokumente gelesen und viele Methoden ausprobiert habe.

  1. Soll ich das Image mit erstellen Dockerfile?
  2. Wie lauten die Befehle, wenn das Maven-Projekt auf dem Host ausgeführt werden soll Dockerfile?
Yashon Lin
quelle

Antworten:

122

Arbeitsbeispiel.

Dies ist kein Spring Boot-Tutorial. Dies ist die aktualisierte Antwort auf eine Frage zum Ausführen eines Maven-Builds in einem Docker-Container.

Frage ursprünglich vor 4 Jahren gepostet.

1. Generieren Sie eine Anwendung

Verwenden Sie den Federinitialisierer, um eine Demo-App zu erstellen

https://start.spring.io/

Geben Sie hier die Bildbeschreibung ein

Extrahieren Sie das Zip-Archiv lokal

2. Erstellen Sie eine Docker-Datei

#
# Build stage
#
FROM maven:3.6.0-jdk-11-slim AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package

#
# Package stage
#
FROM openjdk:11-jre-slim
COPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/usr/local/lib/demo.jar"]

Hinweis

  • In diesem Beispiel wird ein mehrstufiger Build verwendet . In der ersten Phase wird der Code erstellt. Die zweite Stufe enthält nur das erstellte Glas und eine JRE, um es auszuführen (beachten Sie, wie das Glas zwischen den Stufen kopiert wird).

3. Erstellen Sie das Image

docker build -t demo .

4. Führen Sie das Image aus

$ docker run --rm -it demo:latest

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2019-02-22 17:18:57.835  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication v0.0.1-SNAPSHOT on f4e67677c9a9 with PID 1 (/usr/local/bin/demo.jar started by root in /)
2019-02-22 17:18:57.837  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2019-02-22 17:18:58.294  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.711 seconds (JVM running for 1.035)

Sonstiges

Lesen Sie in der Docker-Hub-Dokumentation, wie der Maven-Build für die Verwendung eines lokalen Repositorys zum Zwischenspeichern von Jars optimiert werden kann.

Update (07.02.2019)

Diese Frage ist jetzt 4 Jahre alt und in dieser Zeit kann man mit Recht sagen, dass die Erstellung von Anwendungen mit Docker erhebliche Änderungen erfahren hat.

Option 1: Mehrstufiger Aufbau

Mit diesem neuen Stil können Sie leichtere Bilder erstellen, die Ihre Build-Tools und Ihren Quellcode nicht enthalten.

In diesem Beispiel wird erneut das offizielle Maven- Basis-Image verwendet, um die erste Phase des Builds mit einer gewünschten Version von Maven auszuführen. Der zweite Teil der Datei definiert, wie das erstellte Glas zum endgültigen Ausgabebild zusammengesetzt wird.

FROM maven:3.5-jdk-8 AS build  
COPY src /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java  
COPY --from=build /usr/src/app/target/helloworld-1.0.0-SNAPSHOT.jar /usr/app/helloworld-1.0.0-SNAPSHOT.jar  
EXPOSE 8080  
ENTRYPOINT ["java","-jar","/usr/app/helloworld-1.0.0-SNAPSHOT.jar"]  

Hinweis:

  • Ich verwende das verzweifelte Basis-Image von Google , das gerade genug Laufzeit für eine Java-App bieten soll.

Option 2: Ausleger

Ich habe diesen Ansatz nicht verwendet, aber er scheint eine Untersuchung wert zu sein, da Sie damit Bilder erstellen können, ohne böse Dinge wie Dockerfiles erstellen zu müssen :-)

https://github.com/GoogleContainerTools/jib

Das Projekt verfügt über ein Maven-Plugin, das die Verpackung Ihres Codes direkt in Ihren Maven-Workflow integriert.


Ursprüngliche Antwort (der Vollständigkeit halber enthalten, aber vor Ewigkeiten geschrieben)

Versuchen Sie es mit den neuen offiziellen Bildern, es gibt eines für Maven

https://registry.hub.docker.com/_/maven/

Das Image kann verwendet werden, um Maven zur Erstellungszeit auszuführen, um eine kompilierte Anwendung zu erstellen, oder um, wie in den folgenden Beispielen, einen Maven-Build in einem Container auszuführen.

Beispiel 1 - Maven läuft in einem Container

Der folgende Befehl führt Ihren Maven-Build in einem Container aus:

docker run -it --rm \
       -v "$(pwd)":/opt/maven \
       -w /opt/maven \
       maven:3.2-jdk-7 \
       mvn clean install

Anmerkungen:

  • Das Schöne an diesem Ansatz ist, dass die gesamte Software im Container installiert ist und ausgeführt wird. Benötigen Sie nur Docker auf dem Host-Computer.
  • Siehe Dockerfile für diese Version

Beispiel 2 - Verwenden Sie Nexus zum Zwischenspeichern von Dateien

Führen Sie den Nexus-Container aus

docker run -d -p 8081:8081 --name nexus sonatype/nexus

Erstellen Sie eine "settings.xml" -Datei:

<settings>
  <mirrors>
    <mirror>
      <id>nexus</id>
      <mirrorOf>*</mirrorOf>
      <url>http://nexus:8081/content/groups/public/</url>
    </mirror>
  </mirrors>
</settings>

Führen Sie nun die Maven-Verknüpfung mit dem Nexus-Container aus, damit Abhängigkeiten zwischengespeichert werden

docker run -it --rm \
       -v "$(pwd)":/opt/maven \
       -w /opt/maven \
       --link nexus:nexus \
       maven:3.2-jdk-7 \
       mvn -s settings.xml clean install

Anmerkungen:

  • Ein Vorteil der Ausführung von Nexus im Hintergrund besteht darin, dass andere Repositorys von Drittanbietern über die Administrator-URL transparent für die Maven-Builds verwaltet werden können, die in lokalen Containern ausgeführt werden.
Mark O'Connor
quelle
Kann dies verwendet werden, um die Maven-Zentrale für einen Gradle-Build zu ersetzen? Wie in support.sonatype.com/entries/… angegeben, habe ich mavenCentral()in meinen Gradle-Abhängigkeiten durch ersetzt maven {url "http://nexus:8081..."und bekomme jetzt nur noch Auflösungsprobleme.
Mohamnag
@mohamnag Richtig, die obige Maven-Einstellungsdatei macht genau das und leitet alle Maven Central-Anforderungen an das lokale Nexus-Repository um. Sie müssen umreißen, welche Art von Auflösungsproblemen Sie haben. Könnte alles sein ... Haben Sie beispielsweise den Docker-Link eingerichtet, damit der "Nexus" -Host ordnungsgemäß aufgelöst wird?
Mark O'Connor
Ich stellte fest, dass alles in Ordnung war, aber der Nexus brauchte entweder Zeit, um den Index zu erstellen, oder etwas anderes verursachte die Probleme. Ich habe auch versucht, eine Indexaktualisierung auszulösen, daher bin ich mir nicht sicher, in welchem ​​Fall das Problem behoben wurde. Vielen Dank jedoch.
Mohamnag
Nexus 3 ist jetzt auch als Docker-Container verfügbar. Verwenden Sie "Sonatyp / Nexus3"
Thorbjørn Ravn Andersen
1
@avandeursen Sie haben Recht, dass der Parameter --link veraltet ist (Antwort über 3 Jahre alt). Die korrektere Lösung (meiner Meinung nach) besteht jedoch darin, ein Docker-Netzwerk zu erstellen und beide Container darauf auszuführen. Auf diese Weise können Sie die native DNS-Funktion in Docker nutzen und weiterhin namentlich auf den Nexus-Container verweisen. Wird das Beispiel später aktualisieren
Mark O'Connor
47

Es kann viele Möglichkeiten geben. Aber ich habe zwei Möglichkeiten implementiert

Das gegebene Beispiel ist ein Maven-Projekt.

1. Verwenden von Dockerfile im Maven-Projekt

Verwenden Sie die folgende Dateistruktur:

Demo
└── src
|    ├── main
|    │   ├── java
|    │       └── org
|    │           └── demo
|    │               └── Application.java
||    └── test
|
├──── Dockerfile
├──── pom.xml

Und aktualisieren Sie die Docker-Datei wie folgt:

FROM java:8
EXPOSE 8080
ADD /target/demo.jar demo.jar
ENTRYPOINT ["java","-jar","demo.jar"]

Navigieren Sie zum Projektordner und geben Sie den folgenden Befehl ein, mit dem Sie ein Image erstellen und dieses Image ausführen können:

$ mvn clean
$ mvn install
$ docker build -f Dockerfile -t springdemo .
$ docker run -p 8080:8080 -t springdemo

Holen Sie sich Videos bei Spring Boot mit Docker

2. Verwenden von Maven-Plugins

Fügen Sie das angegebene Maven-Plugin hinzu pom.xml

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.5</version>
        <configuration>
            <imageName>springdocker</imageName>
            <baseImage>java</baseImage>
            <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
            <resources>
                <resource>
                    <targetPath>/</targetPath>
                    <directory>${project.build.directory}</directory>
                    <include>${project.build.finalName}.jar</include>
                </resource>
            </resources>
        </configuration>
    </plugin>

Navigieren Sie zum Projektordner und geben Sie den folgenden Befehl ein. Sie können ein Image erstellen und dieses Image ausführen:

$ mvn clean package docker:build
$ docker images
$ docker run -p 8080:8080 -t <image name>

Im ersten Beispiel erstellen wir Dockerfile und stellen das Basis-Image bereit und fügen jar an. Danach führen wir den Docker-Befehl aus, um ein Image mit einem bestimmten Namen zu erstellen, und führen dann das Image aus.

Während im zweiten Beispiel verwenden wir Maven Plugin in die wir bieten baseImageund imageNameso brauchen wir nicht zu schaffen Dockerfile hier .. nach Maven - Projekt Verpackung werden wir die Docker Bild erhalten , und wir müssen nur das Bild laufen ..

Riddhi Gohil
quelle
Anstatt den Einstiegspunkt zu ändern, um den Artefaktnamen anzugeben, können Sie einen Ansatz wie den folgenden verwenden: alooma.com/blog/building-dockers - Verwenden Sie das Maven-Dependency-Plugin, um einen allgemeinen Namen zu verwenden. Es ist nicht erforderlich, ein versioniertes Glas in den Docker-Container zu legen, da der Container selbst versioniert ist.
Kboom
14

Als Faustregel sollten Sie mit Maven eine fette JAR erstellen (eine JAR, die sowohl Ihren Code als auch alle Abhängigkeiten enthält).

Dann können Sie eine Docker-Datei schreiben , die Ihren Anforderungen entspricht (wenn Sie eine fette JAR erstellen können, benötigen Sie nur ein Basis-Betriebssystem wie CentOS und die JVM).

Dies ist, was ich für eine Scala-App (die Java-basiert ist) verwende.

FROM centos:centos7

# Prerequisites.

RUN yum -y update
RUN yum -y install wget tar

# Oracle Java 7

WORKDIR /opt

RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u71-b14/server-jre-7u71-linux-x64.tar.gz
RUN tar xzf server-jre-7u71-linux-x64.tar.gz
RUN rm -rf server-jre-7u71-linux-x64.tar.gz
RUN alternatives --install /usr/bin/java java /opt/jdk1.7.0_71/bin/java 1

# App

USER daemon

# This copies to local fat jar inside the image
ADD /local/path/to/packaged/app/appname.jar /app/appname.jar

# What to run when the container starts
ENTRYPOINT [ "java", "-jar", "/app/appname.jar" ]

# Ports used by the app
EXPOSE 5000

Dadurch wird mit Java7 ein CentOS-basiertes Image erstellt. Beim Start wird Ihre App-JAR ausgeführt.

Die Bereitstellung erfolgt am besten über die Docker-Registrierung. Sie ähnelt einem Github für Docker-Images.

Sie können ein Bild wie folgt erstellen:

# current dir must contain the Dockerfile
docker build -t username/projectname:tagname .

Sie können dann ein Bild folgendermaßen verschieben:

docker push username/projectname # this pushes all tags

Sobald sich das Image in der Docker-Registrierung befindet, können Sie es von überall auf der Welt abrufen und ausführen.

Weitere Informationen finden Sie im Docker-Benutzerhandbuch .

Beachten Sie Folgendes :

Sie können Ihr Repository auch in ein Image ziehen und das JAR als Teil der Containerausführung erstellen. Dies ist jedoch kein guter Ansatz, da sich der Code ändern kann und Sie möglicherweise ohne vorherige Ankündigung eine andere Version der App verwenden.

Das Bauen eines fetten Glases behebt dieses Problem.

Matteo Pacini
quelle
HI, ich habe Ihr Beispiel in meiner Docker-Datei verwendet, um das Fettglas im Bild zu kopieren, aber der Build schlägt fehl, weil das Fettglas unter dem lokalen Pfad nicht gefunden werden kann. Ist es so etwas wie target / app.jar?
user_mda
Hallo, gibt es eine Möglichkeit, das Artefakt zur Laufzeit von nexus herunterzuladen? Um das herunterzuladende Artefakt mithilfe von Eigenschaften und nicht anhand eines tatsächlichen Links zum Glas selbst anzugeben? In der Docker-Datei: RUN wget -O {project.build.finalname}.jar Aber ich möchte das obige Glas von Nexus herunterladen.
Pramod Setlur
1
Das Einfügen eines FAT JAR in das Code-Repo ist für mich langsam. Gibt es eine Möglichkeit, Maven zum Erstellen des Images zu verwenden?
WoLfPwNeR
1
Fette Gläser haben auch einige Probleme, insbesondere mit signierten Gläsern.
Thorbjørn Ravn Andersen
1
Als Faustregel gilt, dass Pakete, die auf dem Manifest oder anderen Datendateien in ihren Gläsern basieren, wahrscheinlich fehlschlagen, da es keine sichere Möglichkeit gibt, diese Daten zusammenzuführen. Manifestdateien mit übereinstimmenden Pfaden innerhalb eines JAR-Konflikts und entweder erstem oder letztem Gewinn (ich kann mich nicht erinnern, welcher). Das einzige Mal, dass Sie die Verwendung eines fetten Glases in Betracht ziehen sollten, ist, wenn Sie nur sehr wenige Abhängigkeiten haben und sehr gut wissen, dass ihre Gläser keine widersprüchlichen Manifestdaten enthalten. Andernfalls sollten Sie die Gläser sicher verwenden, da sie für die Verwendung (dh separat) vorgesehen sind.
PiersyP
3

Hier ist mein Beitrag.
Ich werde nicht versuchen, alle Tools / Bibliotheken / Plugins aufzulisten, die vorhanden sind, um Docker mit Maven zu nutzen. Einige Antworten haben es bereits getan.
Stattdessen werde ich mich auf die Anwendungstypologie und den Dockerfile-Weg konzentrieren.
Dockerfileist wirklich ein einfaches und wichtiges Konzept von Docker (alle bekannten / öffentlichen Bilder hängen davon ab) und ich denke, dass der Versuch, das Verstehen und Verwenden von Dockerfiles zu vermeiden, nicht unbedingt der bessere Weg ist, in die Docker-Welt einzutreten.

Das Andocken einer Anwendung hängt von der Anwendung selbst und dem zu erreichenden Ziel ab

1) Für Anwendungen, die wir auf einem installierten / eigenständigen Java-Server ausführen möchten (Tomcat, JBoss usw.)

Der Weg ist schwieriger und das ist nicht das ideale Ziel, da dies die Komplexität erhöht (wir müssen den Server verwalten / warten) und weniger skalierbar und weniger schnell als eingebettete Server in Bezug auf das Erstellen / Bereitstellen / Aufheben der Bereitstellung ist.
Bei älteren Anwendungen kann dies jedoch als erster Schritt betrachtet werden.
Im Allgemeinen besteht die Idee hier darin, ein Docker-Image für den Server zu definieren und ein Image pro zu implementierender Anwendung zu definieren.
Die Docker-Images für die Anwendungen erzeugen das erwartete WAR / EAR, diese werden jedoch nicht als Container ausgeführt, und das Image für die Serveranwendung stellt die von diesen Images erzeugten Komponenten als bereitgestellte Anwendungen bereit.
Für große Anwendungen (Millionen von Codezeilen) mit vielen Legacy-Inhalten und so schwer zu migrieren, um auf eine eingebettete Full-Spring-Boot-Lösung zu migrieren, ist das wirklich eine schöne Verbesserung.
Ich werde diesen Ansatz nicht näher erläutern, da dies für kleinere Anwendungsfälle von Docker gilt, aber ich wollte die Gesamtidee dieses Ansatzes erläutern, da ich denke, dass es für Entwickler, die sich diesen komplexen Fällen stellen, gut ist zu wissen, dass einige Türen geöffnet sind Docker integrieren.

2) Für Anwendungen, die den Server selbst einbetten / booten (Spring Boot mit eingebettetem Server: Tomcat, Netty, Jetty ...)

Das ist das ideale Ziel mit Docker . Ich habe Spring Boot spezifiziert, weil dies ein wirklich schönes Framework ist, das auch ein sehr hohes Maß an Wartbarkeit aufweist, aber theoretisch könnten wir jeden anderen Java-Weg verwenden, um dies zu erreichen.
Im Allgemeinen besteht die Idee hier darin, ein Docker-Image pro bereitzustellender Anwendung zu definieren.
Die Docker-Images für die Anwendungen erzeugen eine JAR oder eine Reihe von JAR- / Klassen- / Konfigurationsdateien. Diese starten eine JVM mit der Anwendung (Java-Befehl), wenn wir aus diesen Images einen Container erstellen und starten.
Für neue Anwendungen oder Anwendungen, die für die Migration nicht zu komplex sind, muss dieser Weg gegenüber eigenständigen Servern bevorzugt werden, da dies der Standardweg und der effizienteste Weg zur Verwendung von Containern ist.
Ich werde diesen Ansatz detailliert beschreiben.

Andocken einer Maven-Anwendung

1) Ohne Spring Boot

Die Idee ist, mit Maven ein Fat Jar zu erstellen (das Maven Assembly Plugin und das Maven Shade Plugin helfen dabei), das sowohl die kompilierten Klassen der Anwendung als auch die erforderlichen Maven-Abhängigkeiten enthält.
Dann können wir zwei Fälle identifizieren:

  • Wenn es sich bei der Anwendung um eine Desktop- oder autonome Anwendung handelt (die nicht auf einem Server bereitgestellt werden muss): Wir können wie CMD/ENTRYPOINTin Dockerfileder Java-Ausführung der Anwendung Folgendes angeben :java -cp .:/fooPath/* -jar myJar

  • Wenn es sich bei der Anwendung um eine Serveranwendung handelt, z. B. Tomcat, ist die Idee dieselbe: ein dickes Glas der Anwendung abzurufen und eine JVM in der Anwendung auszuführen CMD/ENTRYPOINT. Aber hier mit einem wichtigen Unterschied: Wir müssen einige logische und spezifische Bibliotheken ( org.apache.tomcat.embedBibliotheken und einige andere) einbeziehen, die den eingebetteten Server starten, wenn die Hauptanwendung gestartet wird.
    Wir haben einen umfassenden Leitfaden auf der Heroku-Website .
    Für den ersten Fall (autonome Anwendung) ist dies eine einfache und effiziente Möglichkeit, Docker zu verwenden.
    Für den zweiten Fall (Serveranwendung) funktioniert dies, ist aber nicht eindeutig, kann fehleranfällig sein und ist kein sehr erweiterbares Modell, da Sie Ihre Anwendung nicht in den Rahmen eines ausgereiften Frameworks wie Spring Boot stellen, das viele Funktionen ausführt von diesen Dingen für Sie und bietet auch ein hohes Maß an Erweiterung.
    Dies hat jedoch einen Vorteil: Sie haben ein hohes Maß an Freiheit, da Sie die eingebettete Tomcat-API direkt verwenden.

2) Mit Spring Boot

Endlich geht es los.
Das ist einfach, effizient und sehr gut dokumentiert.
Es gibt wirklich mehrere Ansätze, um eine Maven / Spring Boot-Anwendung auf Docker auszuführen.
Alle aufzudecken wäre lang und vielleicht langweilig.
Die beste Wahl hängt von Ihren Anforderungen ab.
Wie auch immer, die Build-Strategie in Bezug auf Docker-Ebenen sieht gleich aus.
Wir möchten einen mehrstufigen Build verwenden: einen, der sich für die Abhängigkeitsauflösung auf Maven und für den Build stützt, und einen anderen, der sich beim Starten der Anwendung auf JDK oder JRE stützt.

Bauphase (Maven-Bild):

  • pom Kopie zum Bild
  • Downloads von Abhängigkeiten und Plugins.
    Über das, mvn dependency:resolve-pluginsangekettet an mvn dependency:resolveden Job kann zu tun , aber nicht immer.
    Warum ? Da diese Plugins und die packageAusführung zum Packen des Fat Jars möglicherweise von unterschiedlichen Artefakten / Plugins und sogar von demselben Artefakt / Plugin abhängen, wird möglicherweise immer noch eine andere Version verwendet. Ein sicherer Ansatz, der möglicherweise langsamer ist, besteht darin, Abhängigkeiten aufzulösen, indem genau der mvnBefehl ausgeführt wird, der zum Packen der Anwendung verwendet wird (wodurch genau die benötigten Abhängigkeiten abgerufen werden), aber die Quellkompilierung übersprungen und der Zielordner gelöscht wird, um die Verarbeitung zu beschleunigen und zu beschleunigen Verhindern Sie eine unerwünschte Schichtwechselerkennung für diesen Schritt.
  • Quellcode-Kopie auf das Bild
  • Packen Sie die Anwendung

Phase ausführen (JDK- oder JRE-Image):

  • Kopieren Sie das Glas aus der vorherigen Phase

Hier zwei Beispiele.

a) Ein einfacher Weg ohne Cache für heruntergeladene Maven-Abhängigkeiten

Dockerfile:

########Maven build stage########
FROM maven:3.6-jdk-11 as maven_build
WORKDIR /app

#copy pom
COPY pom.xml .

#resolve maven dependencies
RUN mvn clean package -Dmaven.test.skip -Dmaven.main.skip -Dspring-boot.repackage.skip && rm -r target/

#copy source
COPY src ./src

# build the app (no dependency download here)
RUN mvn clean package  -Dmaven.test.skip

# split the built app into multiple layers to improve layer rebuild
RUN mkdir -p target/docker-packaging && cd target/docker-packaging && jar -xf ../my-app*.jar

########JRE run stage########
FROM openjdk:11.0-jre
WORKDIR /app

#copy built app layer by layer
ARG DOCKER_PACKAGING_DIR=/app/target/docker-packaging
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/lib /app/lib
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/classes /app/classes
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/META-INF /app/META-INF

#run the app
CMD java -cp .:classes:lib/* \
         -Djava.security.egd=file:/dev/./urandom \
         foo.bar.MySpringBootApplication

Nachteil dieser Lösung? Alle Änderungen in der Datei pom.xml bedeuten, dass die gesamte Ebene, die die Maven-Abhängigkeiten herunterlädt und speichert, neu erstellt wird. Dies ist im Allgemeinen für Anwendungen mit vielen Abhängigkeiten nicht akzeptabel (und Spring Boot zieht viele Abhängigkeiten), insgesamt, wenn Sie während der Image-Erstellung keinen Maven-Repository-Manager verwenden.

b) Ein effizienterer Weg mit Cache für heruntergeladene Maven-Abhängigkeiten

Der Ansatz ist hier der gleiche, jedoch werden Downloads von Maven-Abhängigkeiten im Docker-Builder-Cache zwischengespeichert.
Die Cache-Operation basiert auf dem Buildkit (experimentelle API von Docker).
Um das Buildkit zu aktivieren, muss die env-Variable DOCKER_BUILDKIT = 1 festgelegt werden (Sie können dies tun, wo Sie möchten: .bashrc, Befehlszeile, Docker-Daemon-JSON-Datei ...).

Dockerfile:

# syntax=docker/dockerfile:experimental

########Maven build stage########
FROM maven:3.6-jdk-11 as maven_build
WORKDIR /app

#copy pom
COPY pom.xml .

#copy source
COPY src ./src

# build the app (no dependency download here)
RUN --mount=type=cache,target=/root/.m2  mvn clean package -Dmaven.test.skip

# split the built app into multiple layers to improve layer rebuild
RUN mkdir -p target/docker-packaging && cd target/docker-packaging && jar -xf ../my-app*.jar

########JRE run stage########
FROM openjdk:11.0-jre
WORKDIR /app

#copy built app layer by layer
ARG DOCKER_PACKAGING_DIR=/app/target/docker-packaging
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/lib /app/lib
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/BOOT-INF/classes /app/classes
COPY --from=maven_build ${DOCKER_PACKAGING_DIR}/META-INF /app/META-INF

#run the app
CMD java -cp .:classes:lib/* \
         -Djava.security.egd=file:/dev/./urandom \
         foo.bar.MySpringBootApplication
davidxxx
quelle