Docker-images maken met Spring Boot

1. Inleiding

Naarmate meer organisaties overstappen op containers en virtuele servers, wordt Docker een steeds belangrijker onderdeel van de workflows voor softwareontwikkeling. Daartoe is een van de geweldige nieuwe functies in Spring Boot 2.3 de mogelijkheid om eenvoudig een Docker-image voor Spring Boot-applicaties te maken.

In deze zelfstudie bekijken we hoe u Docker-afbeeldingen kunt maken voor een Spring Boot-toepassing.

2. Traditionele Docker-builds

De traditionele manier om Docker-images te bouwen met Spring Boot is om een ​​Dockerfile te gebruiken. Hieronder een eenvoudig voorbeeld:

FROM openjdk: 8-jdk-alpine EXPOSE 8080 ARG JAR_FILE = target / demo-app-1.0.0.jar VOEG $ {JAR_FILE} app.jar ENTRYPOINT ["java", "- jar", "/ app.jar"]

We zouden dan de docker build opdracht om een ​​Docker-image te maken. Dit werkt prima voor de meeste toepassingen, maar er zijn een aantal nadelen.

Ten eerste gebruiken we de vetpot gemaakt door Spring Boot. Dit kan de opstarttijd beïnvloeden, vooral in een containeromgeving. We kunnen opstarttijd besparen door in plaats daarvan de geëxplodeerde inhoud van het jar-bestand toe te voegen.

Ten tweede zijn Docker-images in lagen gebouwd. De aard van Spring Boot fat jars zorgt ervoor dat alle applicatiecode en bibliotheken van derden in een enkele laag worden geplaatst. Dit betekent dat zelfs wanneer slechts een enkele regel code verandert, de hele laag opnieuw moet worden opgebouwd.

Door de pot te exploderen voordat deze wordt gebouwd, krijgen applicatiecode en bibliotheken van derden elk hun eigen laag. Hierdoor kunnen we profiteren van het cachemechanisme van Docker. Als nu een regel code wordt gewijzigd, hoeft alleen die corresponderende laag opnieuw te worden opgebouwd.

Laten we met dit in gedachten eens kijken hoe Spring Boot het proces van het maken van Docker-images heeft verbeterd.

3. Buildpacks

Buildpacks zijn een tool die raamwerk- en toepassingsafhankelijkheden biedt.

Gegeven een Spring Boot-fat jar, zou een buildpack bijvoorbeeld de Java-runtime voor ons leveren. Hierdoor kunnen we het Docker-bestand overslaan en automatisch een verstandige Docker-afbeelding krijgen.

Spring Boot bevat zowel Maven- als Gradle-ondersteuning voor buildpacks. Als we bijvoorbeeld bouwen met Maven, voeren we de volgende opdracht uit:

./mvnw spring-boot: build-image

Laten we eens kijken naar enkele van de relevante uitvoer om te zien wat er gebeurt:

[INFO] Building jar: target / demo-0.0.1-SNAPSHOT.jar ... [INFO] Building image 'docker.io/library/demo:0.0.1-SNAPSHOT' ... [INFO]> Builder image trekken 'gcr.io/paketo-buildpacks/builder:base-platform-api-0.3' 100% ... [INFO] [creator] ===> DETECTIE [INFO] [creator] 5 van 15 deelnemende buildpacks [INFO] [ creator] paketo-buildpacks / bellsoft-liberica 2.8.1 [INFO] [creator] paketo-buildpacks / executable-jar 1.2.8 [INFO] [creator] paketo-buildpacks / apache-tomcat 1.3.1 [INFO] [creator] paketo-buildpacks / dist-zip 1.3.6 [INFO] [creator] paketo-buildpacks / spring-boot 1.9.1 ... [INFO] Succesvol gemaakte image 'docker.io/library/demo:0.0.1-SNAPSHOT' [INFO] Totale tijd: 44.796 s

De eerste regel laat zien dat we onze standaard vetpot hebben gebouwd, net als elk typisch mavenpakket.

De volgende regel begint met het bouwen van de Docker-installatiekopie. Meteen daarna zien we dat de build de Packeto-builder binnenhaalt.

Packeto is een implementatie van cloud-native buildpacks. Het doet het werk van het analyseren van ons project en het bepalen van de vereiste kaders en bibliotheken. In ons geval bepaalt het dat we een Spring Boot-project hebben en voegt het de vereiste buildpacks toe.

Ten slotte zien we de gegenereerde Docker-afbeelding en de totale build-tijd. Merk op hoe de eerste keer dat we bouwen, we behoorlijk wat tijd besteden aan het downloaden van buildpacks en het maken van verschillende lagen.

Een van de geweldige functies van buildpacks is dat de Docker-afbeelding uit meerdere lagen bestaat. Dus als we alleen onze applicatiecode wijzigen, zullen volgende builds veel sneller zijn:

... [INFO] [creator] Hergebruik laag 'paketo-buildpacks / executable-jar: class-path' [INFO] [creator] Hergebruik laag 'paketo-buildpacks / spring-boot: web-applicatie-type' ... [INFO] Succesvol gemaakte afbeelding 'docker.io/library/demo:0.0.1-SNAPSHOT' ... [INFO] Totale tijd: 10.591 s

4. Gelaagde potten

In sommige gevallen geven we er misschien de voorkeur aan om geen buildpacks te gebruiken - misschien is onze infrastructuur al gekoppeld aan een andere tool, of hebben we al aangepaste Dockerfiles die we willen hergebruiken.

Om deze redenen ondersteunt Spring Boot ook het bouwen van Docker-images met gelaagde potten. Laten we, om te begrijpen hoe het werkt, eens kijken naar een typische Spring Boot-indeling voor vetpotten:

org / springframework / boot / loader / ... BOOT-INF / classes / ... lib / ...

De vetpot bestaat uit 3 hoofdgebieden:

  • Bootstrap-klassen die nodig zijn om de Spring-applicatie te starten
  • Toepassingscode
  • Bibliotheken van derden

Bij gelaagde potten ziet de structuur er hetzelfde uit, maar we krijgen een nieuwe layers.idx bestand dat elke map in de fat jar toewijst aan een laag:

- "afhankelijkheden": - "BOOT-INF / lib /" - "spring-boot-loader": - "org /" - "snapshot-afhankelijkheden": - "applicatie": - "BOOT-INF / classes /" - "BOOT-INF / classpath.idx" - "BOOT-INF / layers.idx" - "META-INF /"

Out-of-the-box, Spring Boot biedt vier lagen:

  • afhankelijkheden: typische afhankelijkheden van derden
  • snapshot-afhankelijkheden: afhankelijkheden van momentopnamen van derden
  • middelen: statische bronnen
  • toepassing: applicatiecode en bronnen

Het doel is om applicatiecode en bibliotheken van derden in lagen te plaatsen die aangeven hoe vaak ze veranderen.

Applicatiecode is bijvoorbeeld waarschijnlijk wat het vaakst verandert, dus het krijgt zijn eigen laag. Verder kan elke laag op zichzelf evolueren en alleen wanneer een laag is gewijzigd, wordt deze opnieuw opgebouwd voor de Docker-afbeelding.

Nu we de nieuwe gelaagde jar-structuur begrijpen, gaan we kijken hoe we deze kunnen gebruiken om Docker-afbeeldingen te maken.

4.1. Gelaagde potten maken

Eerst moeten we ons project opzetten om een ​​gelaagde pot te maken. Met Maven betekent dit het toevoegen van een nieuwe configuratie aan de Spring Boot-plug-in-sectie van onze POM:

 org.springframework.boot spring-boot-maven-plugin waar 

Met deze configuratie is de Maven pakket commando (samen met een van zijn afhankelijke commando's) zal een nieuwe gelaagde jar genereren met behulp van de vier standaardlagen die eerder zijn genoemd.

4.2. Lagen bekijken en extraheren

Vervolgens moeten we de lagen uit de pot halen, zodat de Docker-afbeelding de juiste lagen heeft.

Om de lagen van een gelaagde pot te onderzoeken, kunnen we de volgende opdracht uitvoeren:

java -Djarmode = layertools -jar demo-0.0.1.jar lijst

Om ze vervolgens te extraheren, zouden we uitvoeren:

java -Djarmode = layertools -jar demo-0.0.1.jar extract

4.3. De Docker-afbeelding maken

De eenvoudigste manier om deze lagen in een Docker-afbeelding op te nemen, is door een Dockerfile te gebruiken:

FROM adoptopenjdk: 11-jre-hotspot als builder ARG JAR_FILE = target / *. Jar COPY $ {JAR_FILE} application.jar RUN java -Djarmode = layertools -jar application.jar extract FROM adoptopenjdk: 11-jre-hotspot COPY --from = builder afhankelijkheden / ./ COPY --from = builder snapshot-afhankelijkheden / ./ COPY --from = builder spring-boot-loader / ./ COPY --from = builder applicatie / ./ ENTRYPOINT ["java", "org .springframework.boot.loader.JarLauncher "]

Dit Dockerfile extraheert de lagen uit onze vetpot en kopieert vervolgens elke laag naar de Docker-afbeelding. Elk KOPIËREN richtlijn resulteert in een nieuwe laag in de uiteindelijke Docker-afbeelding.

Als we dit Dockerfile bouwen, kunnen we zien dat elke laag uit de gelaagde pot als een eigen laag wordt toegevoegd aan de Docker-afbeelding:

... Stap 6/10: COPY --from = builder afhankelijkheden / ./ ---> 2c631b8f9993 Stap 7/10: COPY --from = builder snapshot-afhankelijkheden / ./ ---> 26e8ceb86b7d Stap 8/10: COPY --from = builder spring-boot-loader / ./ ---> 6dd9eaddad7f Stap 9/10: COPY --from = builder applicatie / ./ ---> dc80cc00a655 ...

5. Conclusie

In deze tutorial hebben we verschillende manieren gezien om Docker-images te bouwen met Spring Boot. Met behulp van buildpacks kunnen we geschikte Docker-images krijgen zonder standaardplaat of aangepaste configuraties. Of, met wat meer moeite, kunnen we gelaagde potten gebruiken om een ​​meer op maat gemaakte Docker-afbeelding te krijgen.

Alle voorbeelden in deze tutorial zijn te vinden op GitHub.

Bekijk de tutorial over jib voor meer informatie over het gebruik van Java en Docker.