Een Java-app containeriseren
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:
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 |
Hiermee downloadt u een image uit een registry in de image store van de Docker-daemon die door de client is geselecteerd. Bestaande afbeeldingslagen kunnen opnieuw worden gebruikt. In deze module maakt uw lokale Docker-omgeving gebruik van images uit registries tijdens de ontwikkeling; later halen AKS-knooppunten de image van de toepassing op uit Azure Container Registry voor implementatie. |
docker run |
Hiermee maakt en start u een nieuwe container op basis van een image. De container voert het geconfigureerde opstartproces uit, behoudens opdrachtregeloverschrijvingen. Imagelagen bieden het bestandssysteem van de container; build-instructies voor Dockerfile worden niet opnieuw uitgevoerd wanneer de container wordt gestart. |
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 is geslaagd, heeft Maven het Flight Booking System for Airline Reservations Web Application Archive artifact AirlinesReservationSample-0.0.1-SNAPSHOT.war gebouwd, zoals geïllustreerd door de volgende historische uitvoer. De tijdstempel en duur van uw build kunnen verschillen:
[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. Een containerimage kan meerdere alleen-lezen bestandssysteemlagen bevatten. Docker kan buildresultaten in de cache opnieuw gebruiken voor ongewijzigde stappen. 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.
Een containerimage bevat alleen-lezen bestandssysteemlagen. In dit voorbeeld kopieert het Dockerfile Tomcat en het WAR-bestand Flight Booking System naar de image tijdens de build. Docker voegt een afzonderlijke schrijfbare laag toe wanneer er een container van de image wordt gemaakt. De beschrijfbare laag van elke container registreert zijn eigen bestandssysteemwijzigingen zonder de imagelagen te wijzigen.
Notitie
Voor bestanden die zijn opgeslagen in de beschrijfbare laag van de container, zijn toevoegingen, wijzigingen en verwijderingen van invloed op die container in plaats van de oorspronkelijke image. Als u bestanden wijzigt die afkomstig zijn van een afbeeldingslaag, wordt gebruikgemaakt van copy-on-write-gedrag.
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 een Azure Linux-image van Microsoft gebruikt.
In de laatste fase wordt Microsoft Build van OpenJDK 17 gebruikt op Azure Linux 3.0. De 17-azurelinux tag geeft deze basis expliciet een naam. De oudere 17-mariner tag blijft een compatibiliteitsalias die de Azure Linux-image weerspiegelt. Deze moet niet worden verward met de buiten gebruik gestelde 17-mariner-cm1- en 17-mariner-cm2-images. Zie Microsoft Build van OpenJDK containerimages voor meer informatie.
Notitie
Microsoft biedt containerimages gebundeld met OpenJDK, waaronder Ubuntu, Azure Linux en distroless images. 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:
In fase 0 wordt Tomcat gedownload uit een versiespecifiek Apache-archief, geverifieerd met een SHA-512-controlesom en geëxtraheerd in een map die is opgegeven door een omgevingsvariabele op een Ubuntu-installatiekopie. De TOMCAT_VERSION variabele geeft de release aan en het TOMCAT_SHA512 buildargument geeft de verwachte checksum op. Werk beide waarden bij elkaar bij wanneer u een nieuwere ondersteunde release selecteert. Docker kan de installatielaag in de cache opnieuw gebruiken, terwijl de instructies en invoer ongewijzigd blijven. De Tomcat-installatie wordt gekopieerd naar de laatste faseomgeving 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 worden de Tomcat- en Java buildartefacten uit respectievelijk fase 0 en fase 1 gekopieerd naar een Microsoft Build van OpenJDK 17-installatiekopie op Azure Linux 3.0. 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 containerize-and-deploy-Java-app-to-Azure/Project/Airlines een geïnstalleerde teksteditor om een bestand met de naam Dockerfile te maken. Voeg de volgende inhoud toe en sla het bestand op:
Important
Voordat u een containerimage maakt die u openbaar beschikbaar stelt, controleert u de huidige ondersteunde Tomcat 10.1.x-release op de downloadpagina van Apache Tomcat en bekijkt u de beveiligingswaarschuwingen. Werk TOMCAT_VERSION en TOMCAT_SHA512 samen bij met de gepubliceerde releasegegevens van Apache. Een artefact dat nog beschikbaar is in het Apache-archief , betekent niet dat de versie actueel of aanbevolen is.
############################################
# Tomcat Intall stage
############################################
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat
ENV CATALINA_HOME=/usr/local/tomcat
# Configure the reviewed Tomcat version and checksum
ENV TOMCAT_VERSION=10.1.61
ARG TOMCAT_SHA512=35120a2b1182bac3d55438fbec0dc581d03b0f1c16ce692a930f3bb6a1097cf896b94b389152257071a87cb2928ac8c15f1bad08387c14acc7c17dbc1bb598fb
# Install Tomcat and required packages
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates && \
curl -fSL \
"https://archive.apache.org/dist/tomcat/tomcat-10/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz" \
-o /tmp/tomcat.tar.gz && \
echo "${TOMCAT_SHA512} /tmp/tomcat.tar.gz" | sha512sum -c - && \
mkdir -p "${CATALINA_HOME}" && \
tar -xzf /tmp/tomcat.tar.gz --strip-components=1 -C "${CATALINA_HOME}" && \
rm /tmp/tomcat.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-azurelinux
# 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
Gebruik het Dockerfile dat in deze les wordt weergegeven voor deze oefening. De toepassing moet naar webapps/AirlinesReservationSample.war worden gekopieerd zodat de URL's in de volgende eenheden de /AirlinesReservationSample/-context gebruiken. Een andere WAR-bestandsnaam wijzigt de standaard-Tomcat-toepassingscontext.
Het Dockerfile is onderverdeeld in drie fasen, die worden beschreven in de volgende tabellen:
De Installatiefase van Tomcat:
Docker-opdracht Beschrijving FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcatstelt de basisinstallatiekopie in op Microsoft Build van OpenJDK 17 op Ubuntu en noemt deze fasetomcat. Hier is Tomcat geïnstalleerd.ENVENV CATALINA_HOME=/usr/local/tomcatstelt een omgevingsvariabele in voor de Tomcat-installatiemap.ENVENV TOMCAT_VERSION=10.1.61hiermee stelt u de Tomcat-release voor dit voorbeeld vast. Bekijk ondersteunde releases en werk deze samen metTOMCAT_SHA512indien nodig bij.ARGARG TOMCAT_SHA512levert de gepubliceerde SHA-512-controlesom van Apache voor het geselecteerde archief als een buildargument.RUNInstalleert curlen CA-certificaten en gebruiktcurl -fSLvervolgens om het versiespecifieke Apache-archief te downloaden.-flaat HTTP-fouten falen;-Lvolgt omleidingen. Het archief wordt geverifieerd metsha512sum -c -voordat het wordt uitgepakt inCATALINA_HOMEmet--strip-components=1. De&&keten stopt bij fouten in plaats van fouten te maskeren tijdens het opschonen. Ten slotte worden het archief en overbodige pakketten verwijderd en wordt de pakketcache opgeschoond.De buildfase, die wordt gecompileerd met Java 17:
Docker-opdracht Beschrijving FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS buildstelt de basisinstallatiekopie in op Microsoft Build van OpenJDK 17 op Ubuntu en noemt deze fasebuild. Deze fase wordt gebruikt voor het compileren van de Java-toepassing.WORKDIRWORKDIR /buildstelt de werkmap in de container/buildin op , waar de broncode wordt gekopieerd en gecompileerd.RUNRUN apt-get update && apt-get install -y maven && mvn --versioninstalleert Maven, een hulpprogramma voor buildautomatisering dat wordt gebruikt voor Java-projecten en controleert de installatie.COPYCOPY pom.xml .kopieert het Maven-configuratiebestand naar de werkmap. Dit bestand is essentieel voor het bouwen van het project.COPYCOPY src ./srckopieert de broncodemap naar de container. Hier bevindt zich de Java-toepassingscode.COPYCOPY web ./webkopieert de map met webresources naar de container. Dit omvat resources voor webtoepassingen die nodig zijn voor de build.RUNRUN mvn clean packagevoert 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 FROMFROM mcr.microsoft.com/openjdk/jdk:17-azurelinuxstelt de basisimage in op Microsoft Build van OpenJDK 17 op Azure Linux 3.0, die wordt gebruikt voor de uiteindelijke implementatie van de toepassing.ENVENV CATALINA_HOME=/usr/local/tomcatstelt de omgevingsvariabele voor de Tomcat-installatiemap in, vergelijkbaar met de installatiefase.ENVENV PATH=$CATALINA_HOME/bin:$PATHvoegt de map Tomcat bin toe aan het systeemPATH, zodat Tomcat-opdrachten eenvoudig kunnen worden uitgevoerd.USERUSER appgeeft de gebruiker op waaronder het Tomcat-proces wordt uitgevoerd, waardoor de beveiliging wordt verbeterd door niet als hoofdgebruiker te worden uitgevoerd.COPYCOPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME}kopieert de Tomcat-installatie vanuit detomcatfase, waarbij het eigendom wordt ingesteld op deappgebruiker.COPYCOPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/confkopieert het tomcat-gebruikersconfiguratiebestand naar de container, waarbij het eigendom wordt ingesteld op deappgebruiker.COPYCOPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.warkopieert het gecompileerde WAR-bestand van debuildfase naar de map Tomcat-web-apps , waarbij het eigendom wordt ingesteld op deappgebruiker.EXPOSEEXPOSE 8080documenteert dat de toepassing naar verwachting luistert op TCP-poort 8080. Er wordt geen hostpoort gepubliceerd. In de volgende eenheid wordt de poort gepubliceerd met de-p 8080:8080optie opdocker run.CMDCMD ["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.