Een Java-app containeriseren

Voltooid

In deze les gaat u een Java-toepassing in een container maken.

Zoals eerder vermeld, worden containers direct boven op het hostbesturingssysteem, kernel en hardware uitgevoerd als gewone systeemprocessen. Containers vereisen minder systeemresources, wat resulteert in een kleinere footprint, minder overhead en snellere opstarttijden van toepassingen. Deze voordelen zijn uitstekende gebruiksvoorbeelden voor het schalen op aanvraag.

Er zijn Windows-containers en Linux-containers. In deze module gebruikt u de veelgebruikte Docker runtime om een Linux-containerimage te bouwen. Vervolgens implementeert u de Linux-containerinstallatiekopie op het hostbesturingssysteem van uw lokale computer. Ten slotte implementeert u de Linux-containerinstallatiekopieën in Azure Kubernetes Service.

Overzicht van Docker

De Docker-runtime wordt gebruikt voor het bouwen, pullen, uitvoeren en pushen van containerinstallatiekopieën, zoals wordt weergegeven in het volgende diagram:

Diagram met Docker-opdrachten.

In de volgende tabel wordt elke Docker-opdracht beschreven:

Docker-opdracht Beschrijving
docker build Hiermee bouwt u een container-image die bestaat uit de instructies of lagen die nodig zijn voor Docker om een draaiende container uit een image te creëren. Het resultaat van deze opdracht is een afbeelding.
docker pull Containers worden geïnitialiseerd uit afbeeldingen, die worden opgehaald uit registries zoals Azure Container Registry. In dit register haalt Azure Kubernetes Service gegevens op. Het resultaat van deze opdracht is een netwerkdownload van een afbeelding, die plaatsvindt in Azure. U kunt eventueel afbeeldingen plaatselijk ophalen. Deze optie is gebruikelijk bij het bouwen van installatiekopieën die afhankelijkheden of lagen vereisen die uw toepassing mogelijk nodig heeft, zoals een toepassingsserver.
docker run Een uitvoerende instantie van een afbeelding is een container en met behulp van deze opdracht worden alle lagen uitgevoerd die nodig zijn om de container te draaien en te gebruiken. Het resultaat van deze opdracht is een actief toepassingsproces op het hostbesturingssysteem.
docker push In Azure Container Registry worden de afbeeldingen opgeslagen, zodat ze direct beschikbaar en netwerk-dichtbij zijn voor Azure-implementaties en schaalbaarheid.

De Java-toepassing klonen

Clone eerst de repository Flight Booking System for Airline Reservations en navigeer naar de projectmap van de Airlines-webapplicatie.

Notitie

Als het maken van de Azure Kubernetes Service is voltooid op het tabblad CLI, gebruikt u dat tabblad. Als het nog steeds wordt uitgevoerd, opent u een nieuw tabblad en navigeert u naar de locatie waar u liever het Flight Booking System for Airline Reservations kloont.

Voer de volgende opdrachten uit:

git clone https://github.com/Azure-Samples/containerize-and-deploy-Java-app-to-Azure.git
cd containerize-and-deploy-Java-app-to-Azure/Project/Airlines

Als u Java en Maven hebt geïnstalleerd, kunt u desgewenst de volgende opdracht uitvoeren in de terminalconsole om inzicht te krijgen in de ervaring van het bouwen van de toepassing zonder Docker. Als u Java en Maven niet hebt geïnstalleerd, kunt u veilig doorgaan naar de volgende sectie, een Docker-bestand maken. In deze sectie gebruikt u Docker om Java en Maven op te halen om de builds namens u uit te voeren.

mvn clean package

Notitie

We hebben de mvn clean package opdracht gebruikt om de operationele uitdagingen te illustreren voor het niet gebruiken van Docker-builds met meerdere fases, die we hierna behandelen. Nogmaals, deze stap is optioneel. In beide gevallen kunt u veilig doorgaan zonder de Maven-opdracht uit te voeren.

Als het proces succesvol was, heeft Maven met succes het Flight Booking System voor het Airline Reservations Web Application Archive-artifact AirlinesReservationSample-0.0.1-SNAPSHOT.war gebouwd, zoals weergegeven in de volgende uitvoer:

[INFO] Building war: $PROJECT_PATH/containerize-and-deploy-Java-app-to-Azure/Project/Airlines/target/AirlinesReservationSample-0.0.1-SNAPSHOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.776 s
[INFO] Finished at: 2024-11-15T09:33:26+09:00
[INFO] ------------------------------------------------------------------------

Stel dat u een Java-ontwikkelaar bent en u zojuist AirlinesReservationSample-0.0.1-SNAPSHOT.war hebt gebouwd. De volgende stap is waarschijnlijk om samen te werken met de operationele technici om dit artefact te implementeren op een on-premises server of een virtuele machine. De servers en virtuele machines moeten beschikbaar zijn en geconfigureerd met de vereiste afhankelijkheden om de toepassing te starten en uit te voeren. Dit proces is lastig en tijdrovend, vooral wanneer de belasting op uw applicatie toeneemt. Met containers worden deze uitdagingen verholpen.

Een Dockerfile maken

U bent nu klaar om een Dockerfile te maken. Een Dockerfile is een tekstdocument dat alle opdrachten bevat die een gebruiker op de opdrachtregel zou uitvoeren om een containerimage samen te stellen. Elke afbeelding is een laag die voor efficiëntie in de cache kan worden opgeslagen. De lagen bouwen op elkaar af.

Flight Booking System for Airline Reservations moet bijvoorbeeld worden geïmplementeerd en uitgevoerd binnen een toepassingsserver. Een toepassingsserver is niet verpakt in de AirlinesReservationSample-0.0.1-SNAPSHOT.war. Het is een externe afhankelijkheid die nodig is voor de AirlinesReservationSample-0.0.1-SNAPSHOT.war om HTTP-aanvragen uit te voeren, te luisteren naar en te verwerken, gebruikerssessies te beheren en vluchtreserveringen te vergemakkelijken. Als u een traditionele, niet-containerimplementatie hebt gebruikt, installeren en configureren operation engineers een toepassingsserver op een fysieke server of virtuele machine voordat ze de AirlinesReservationSample-0.0.1-SNAPSHOT.war erop implementeren. Deze operationele ingenieurs moeten er ook voor zorgen dat de JDK die op uw computer wordt gebruikt - wat mvn clean package gebruikt om het WAR-bestand te compileren - in feite overeenkomt met dezelfde JRE die door de toepassingsserver wordt gebruikt. Het beheren van deze afhankelijkheden is lastig en tijdrovend.

Met een Dockerfile kunt u de instructies of lagen schrijven die nodig zijn om dit doel automatisch te bereiken door lagen in de stappen te plaatsen die nodig zijn om ervoor te zorgen dat het Flight Booking System voor Luchtvaartmaatschappijen alle afhankelijkheden bevat die nodig zijn om te implementeren in de Docker-containerruntime. Deze oplossing is aantrekkelijk wanneer u werkt met on-demand schaalbaarheid op niet-geplande intervallen. Elke laag maakt gebruik van Docker-cache, die de status van de containerimage bevat op elke instructiemijlpaal, waardoor de rekentijd wordt geoptimaliseerd en hergebruik wordt bevorderd. Als een laag niet wordt gewijzigd, worden lagen in de cache gebruikt. Veelvoorkomende gebruiksvoorbeelden voor lagen in de cache zijn de Java-runtime, toepassingsserver en andere afhankelijkheden voor de webtoepassing Flight Booking System for Airline Reservations. Als en wanneer een versie wordt gewijzigd op een eerder in de cache geplaatste laag, wordt er een nieuwe vermelding in de cache gemaakt.

In het onderstaande diagram worden de lagen van een containerimage weergegeven. Wanneer de opdrachten in het Dockerfile worden uitgevoerd, worden de lagen gemaakt. De bovenste laag is het read/write Flight Booking System voor de webtoepassingslaag Airline Reservations. Deze laag is gebouwd op basis van de vorige alleen-lezen lagen.

Diagram met de Docker-lagen.

Docker heeft het concept van builds met meerdere fasen, een functie waarmee u een kleinere containerinstallatiekopieën kunt maken met betere caching en een kleinere beveiligingsvoetafdruk, waardoor de Dockerfile in de loop van de tijd beter kan worden geoptimaliseerd en onderhouden. U kunt bijvoorbeeld de buildfase van de container scheiden voor het compileren en bouwen van de toepassing van de fase voor het uitvoeren van de toepassing. Met deze functie kunt u alleen de artefacten kopiëren die tijdens de build zijn gegenereerd naar de productiecontainerafbeelding, wat de footprint vermindert. Omdat containerafbeeldingen in de cache worden opgeslagen, kunnen ze opnieuw worden gebruikt als er geen wijzigingen zijn, wat de kosten en tijd voor het downloaden van het netwerk vermindert.

Services die in de productieomgeving worden weergegeven, moeten zorgvuldig worden beheerd voor beveiliging. Daarom gebruikt en voert de productieomgeving een beveiligde containerimage uit. In het voorbeeld wordt de CBL-Mariner afbeelding van Microsoft gebruikt.

CBL-Mariner Linux is een lichtgewicht besturingssysteem, dat alleen de pakketten bevat die nodig zijn voor een cloudomgeving. U kunt deze aanpassen via aangepaste pakketten en hulpprogramma's om aan de vereisten van uw toepassing te voldoen. CBL-Mariner Azure-validatietests ondergaan en compatibel is met Azure-agents. Microsoft bouwt en test CBL-Mariner om verschillende gebruiksscenario's mogelijk te maken, variërend van Azure-services tot het aandrijven van ioT-infrastructuur. Het is de intern aanbevolen Linux-distributie voor gebruik met Microsoft-cloudservices en gerelateerde producten.

Notitie

Microsoft biedt containerinstallatiekopieën die zijn gebundeld met OpenJDK, inclusief Ubuntu, CBL-Marineren distroless installatiekopieën. De distroless image heeft het kleinste formaat, maar het is uitdagend om Tomcat erop te draaien. Om een lichtgewicht ontwerp te bereiken, verwijdert de distroless image veel opdrachten en hulpprogramma's, waaronder de shell, wat betekent dat u catalina.sh niet kunt aanroepen om Tomcat te starten. De distroless installatiekopie is geschikt voor het uitvoeren van uitvoerbare JAR's, zoals die worden gebruikt met Spring Boot of Quarkus.

In het volgende voorbeeld wordt dezelfde versie van Microsoft Build van OpenJDK gebruikt in zowel de buildfase als de laatste fase. Deze aanpak zorgt ervoor dat u de broncode bouwt met dezelfde versie van de JDK die door de service-implementatie van Tomcat wordt gebruikt, waardoor onverwacht gedrag wordt voorkomen als gevolg van niet-overeenkomende versies.

In de volgende afbeelding ziet u de build met meerdere fasen en wat er gebeurt in elke fase op basis van de opdrachten die zijn opgegeven in het Dockerfile:

Diagram van de Docker-build met meerdere fases.

In fase 0 wordt Tomcat gedownload en geëxtraheerd in een map die is opgegeven door een omgevingsvariabele op een Ubuntu-installatiekopie. De TOMCAT_VERSION variabele geeft de versie van Tomcat op die moet worden gedownload. Als er een nieuwe versie van Tomcat wordt uitgebracht, moet u het versienummer bijwerken, aangezien een nieuwe image alleen wordt opgehaald wanneer het versienummer wordt gewijzigd. Anders wordt de afbeelding in de cache gebruikt. De gedownloade versie van Tomcat wordt gekopieerd naar de definitieve omgeving voor gebruik.

In fase 1 wordt Maven geïnstalleerd op een Ubuntu-installatiekopie en worden de gemaakte broncode en configuratiebestanden gekopieerd voordat het Maven-project wordt gebouwd. Elke laag wordt in de cache opgeslagen, zodat de besturingssysteem- en Maven-imagelagen de cache opnieuw gebruiken. Als configuratiebestanden, broncodebestanden of de webmap worden bijgewerkt, worden de lagen vanaf de wijzigingen opnieuw opgebouwd. Als de build is voltooid zonder fouten tijdens het compileren, wordt een artefact met de naam AirlinesReservationSample-0.0.1-SNAPSHOT.war gegenereerd onder de doelmap . Dit artefact wordt gekopieerd naar de eindfaseomgeving voor gebruik.

In de laatste fase wordt de beveiligde CBL-Mariner installatiekopie van Microsoft gebruikt om de Tomcat- en Java-buildartefacten te kopiëren uit respectievelijk fase 0 en fase 1. Een gebruiker met de naam app is eigenaar van alle bestanden die in het project worden gebruikt en de toepassing wordt ook uitgevoerd als de app gebruiker in plaats van root bevoegdheden. Deze installatie zorgt ervoor dat de containerafbeelding veilig kan worden uitgevoerd zonder onnodige machtigingen te verlenen. Ten slotte wordt poortnummer 8080 weergegeven en wordt het catalina.sh script uitgevoerd om Tomcat te starten. Wanneer dit wordt uitgevoerd op uw lokale Docker Desktop, kunt u deze openen via de URL http://localhost:8080/AirlinesReservationSample.

Gebruik in de hoofdmap van uw project containerize-and-deploy-Java-app-to-Azure/Project/Airlines de volgende opdracht om een bestand met de naam Dockerfile te maken:

vi Dockerfile

Voeg de volgende inhoud toe aan uw Dockerfile en sla deze op en sluit deze af. Als u wilt opslaan en afsluiten, drukt u op Esc, typt u :wq!en drukt u vervolgens op Enter.

############################################
# Tomcat Intall stage
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat

ENV CATALINA_HOME=/usr/local/tomcat

# Configure Tomcat Version (Be sure to use the latest version)
ENV TOMCAT_VERSION=10.1.33

# Install Tomcat and required packages
RUN apt-get update ; \
    apt-get install -y curl ; \
    curl -O https://downloads.apache.org/tomcat/tomcat-10/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz ; \
    tar xzf apache-tomcat-${TOMCAT_VERSION}.tar.gz ; \
    mv apache-tomcat-${TOMCAT_VERSION} ${CATALINA_HOME} ; \
    rm apache-tomcat-${TOMCAT_VERSION}.tar.gz && \
    apt-get remove --purge -y curl && \
    apt-get autoremove -y && \
    apt-get clean

############################################
# Build stage (Compiles with Java 17)
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS build

WORKDIR /build

# Install Maven
RUN apt-get update && apt-get install -y maven && mvn --version

# Copy source code
COPY pom.xml .
COPY src ./src
COPY web ./web

# Build the project
RUN mvn clean package

############################################
# Package final stage
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-mariner

# Configure the location of the Tomcat installation
ENV CATALINA_HOME=/usr/local/tomcat
# Configure the path to the Tomcat binaries
ENV PATH=$CATALINA_HOME/bin:$PATH

# This is the user that runs the Tomcat process
USER app

# Copy the Tomcat installation from the Tomcat stage
COPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME}
# Copy the Tomcat configuration files
COPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/conf
# Copy the compiled WAR file from the build stage
COPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.war

# Expose the default Tomcat port
EXPOSE 8080
# Start Tomcat
CMD ["catalina.sh", "run"]

Notitie

U kunt desgewenst het Dockerfile_Solution-bestand in de hoofdmap van uw project gebruiken, dat de inhoud bevat die u nodig hebt.

Het Dockerfile is onderverdeeld in drie fasen, die worden beschreven in de volgende tabellen:

  • De Installatiefase van Tomcat:

    Docker-opdracht Beschrijving
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat stelt de basisinstallatiekopie in op Microsoft Build van OpenJDK 17 op Ubuntu en noemt deze fase tomcat. Hier is Tomcat geïnstalleerd.
    ENV ENV CATALINA_HOME=/usr/local/tomcat stelt een omgevingsvariabele in voor de Tomcat-installatiemap.
    ENV ENV TOMCAT_VERSION=10.1.33 hiermee stelt u de versie van Tomcat in die moet worden geïnstalleerd. Dit moet indien nodig worden bijgewerkt naar de nieuwste versie.
    RUN De RUN opdracht werkt de pakketlijst bij, installeert curl, downloadt de opgegeven versie van Tomcat, extraheert deze, verplaatst deze naar de opgegeven map en schoont onnodige bestanden en pakketten op. Dit zorgt ervoor dat de afbeelding licht blijft.
  • De buildfase, die wordt gecompileerd met Java 17:

    Docker-opdracht Beschrijving
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS build stelt de basisinstallatiekopie in op Microsoft Build van OpenJDK 17 op Ubuntu en noemt deze fase build. Deze fase wordt gebruikt voor het compileren van de Java-toepassing.
    WORKDIR WORKDIR /build stelt de werkmap in de container /buildin op , waar de broncode wordt gekopieerd en gecompileerd.
    RUN RUN apt-get update && apt-get install -y maven && mvn --version installeert Maven, een hulpprogramma voor buildautomatisering dat wordt gebruikt voor Java-projecten en controleert de installatie.
    COPY COPY pom.xml . kopieert het Maven-configuratiebestand naar de werkmap. Dit bestand is essentieel voor het bouwen van het project.
    COPY COPY src ./src kopieert de broncodemap naar de container. Hier bevindt zich de Java-toepassingscode.
    COPY COPY web ./web kopieert de map met webresources naar de container. Dit omvat resources voor webtoepassingen die nodig zijn voor de build.
    RUN RUN mvn clean package voert het Maven-buildproces uit, waarmee de Java-toepassing wordt gecompileerd en verpakt in een WAR-bestand.
  • De laatste fase van het pakket:

    Docker-opdracht Beschrijving
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-mariner stelt de basisafbeelding in op Microsoft Build van OpenJDK 17 op CBL-Mariner, die wordt gebruikt voor de uiteindelijke implementatie van de applicatie.
    ENV ENV CATALINA_HOME=/usr/local/tomcat stelt de omgevingsvariabele voor de Tomcat-installatiemap in, vergelijkbaar met de installatiefase.
    ENV ENV PATH=$CATALINA_HOME/bin:$PATH voegt de map Tomcat bin toe aan het systeem PATH, zodat Tomcat-opdrachten eenvoudig kunnen worden uitgevoerd.
    USER USER app geeft de gebruiker op waaronder het Tomcat-proces wordt uitgevoerd, waardoor de beveiliging wordt verbeterd door niet als hoofdgebruiker te worden uitgevoerd.
    COPY COPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME} kopieert de Tomcat-installatie vanuit de tomcat fase, waarbij het eigendom wordt ingesteld op de app gebruiker.
    COPY COPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/conf kopieert het tomcat-gebruikersconfiguratiebestand naar de container, waarbij het eigendom wordt ingesteld op de app gebruiker.
    COPY COPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.war kopieert het gecompileerde WAR-bestand van de build fase naar de map Tomcat-web-apps , waarbij het eigendom wordt ingesteld op de app gebruiker.
    EXPOSE EXPOSE 8080 maakt poort 8080 beschikbaar, de standaardpoort voor Tomcat, waardoor externe toegang tot de toepassing mogelijk is.
    CMD CMD ["catalina.sh", "run"] hiermee geeft u de opdracht om Tomcat te starten wanneer de container wordt uitgevoerd.

Zie de Dockerfile-referentie voor meer informatie over dockerfile-constructie.