Containerisera en Java-app
I den här lektionen ska du containerisera ett Java-program.
Som tidigare nämnts körs containrar direkt ovanpå värdoperativsystemet, kerneln och maskinvaran som vanliga systemprocesser. Containrar kräver färre systemresurser, vilket resulterar i ett mindre fotavtryck, mindre omkostnader och snabbare starttider för program. Dessa fördelar är bra användningsfall för skalning på begäran.
Det finns Windows-containrar och Linux-containrar. I den här modulen använder du den ofta använda Docker-körningen för att skapa en Linux-containeravbildning. Sedan distribuerar du Linux-containeravbildningen till värdoperativsystemet på den lokala datorn. Slutligen distribuerar du Linux-containeravbildningen till Azure Kubernetes Service.
Docker-översikt
Docker-körningen används för att skapa, hämta, köra och skicka containeravbildningar enligt följande diagram:
I följande tabell beskrivs varje Docker-kommando:
| Docker-kommando | Beskrivning |
|---|---|
docker build |
Skapar en containeravbildning som består av de instruktioner eller lager som behövs för att Docker ska kunna skapa en container som körs från en avbildning. Resultatet av det här kommandot är en avbildning. |
docker pull |
Laddar ned en image från ett registry till imagearkivet för den Docker-daemon som valts av klienten. Befintliga bildlager kan återanvändas. I den här modulen använder din lokala Docker-miljö images från containerregister under utvecklingen. Senare hämtar AKS-noder programbilden från Azure Container Registry för distribution. |
docker run |
Skapar och startar en ny container från en image. Containern kör sin konfigurerade startprocess, med förbehåll för åsidosättningar på kommandoraden. Bildlager tillhandahåller containerns filsystem. Dockerfile-buildinstruktioner körs inte igen när containern startar. |
docker push |
Azure Container Registry lagrar avbildningarna så att de är lättillgängliga och nätverksnära för Azure-distributioner och skalning. |
Klona Java-programmet
Först, klona lagringsplatsen Flight Booking System for Airline Reservations och navigera till projektmappen för Airlines webbapplikation.
Notera
Om skapandet av Azure Kubernetes Service är klar på CLI-fliken använder du den fliken. Om den fortfarande körs öppnar du en ny flik och navigerar till den plats där du föredrar att klona Bokningssystemet för flygreservationer.
Kör följande kommandon:
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
Om du har Installerat Java och Maven kan du köra följande kommando i terminalkonsolen för att få en uppfattning om upplevelsen av att skapa programmet utan Docker. Om du inte har Java och Maven installerade kan du gå vidare till nästa avsnitt, Skapa en Docker-fil. I det avsnittet använder du Docker för att hämta Java och Maven för att köra byggen åt dig.
mvn clean package
Notera
Vi använde mvn clean package kommandot för att illustrera de operativa utmaningarna med att inte använda Docker-flerstegsversioner, som vi tar upp härnäst. Återigen är det här steget valfritt. Hur som helst kan du fortsätta utan att köra Maven-kommandot på ett säkert sätt.
Om processen lyckades har Maven framgångsrikt byggt webbapplikationsarkivartefakten för flygbokningssystemet för flygbolagsreservationer AirlinesReservationSample-0.0.1-SNAPSHOT.war, vilket illustreras av följande historiska utdata. Tidsstämpeln och varaktigheten för bygget kan skilja sig åt:
[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] ------------------------------------------------------------------------
Anta att du är Java-utvecklare och att du precis har skapat AirlinesReservationSample-0.0.1-SNAPSHOT.war. Nästa steg är förmodligen att arbeta med driftstekniker för att få den här artefakten distribuerad till antingen en intern server eller en virtuell maskin. För att programmet ska starta och köras korrekt måste servrarna och de virtuella datorerna vara tillgängliga och konfigurerade med nödvändiga beroenden. Den här processen är utmanande och tidskrävande, särskilt på begäran när ökad belastning drabbar ditt program. Med containrar lindras dessa utmaningar.
Skapa en Dockerfile
Nu är du redo att skapa en Dockerfile. En Dockerfile är ett textdokument som innehåller alla kommandon som en användare skulle köra på kommandoraden för att montera en containeravbildning. En containeravbildning kan innehålla flera skrivskyddade filsystemlager. Docker kan återanvända cachelagrade byggresultat för oförändrade steg. Lagren bygger på varandra.
Flight Booking System for Airline Reservations måste till exempel distribueras till och köras på en programserver. En programserver är inte paketerad i AirlinesReservationSample-0.0.1-SNAPSHOT.war. Det är ett externt beroende som krävs för att AirlinesReservationSample-0.0.1-SNAPSHOT.war ska kunna köra, lyssna efter och bearbeta HTTP-begäranden, hantera användarsessioner och underlätta flygbokningar. Om du använde en traditionell, icke-containerbaserad distribution skulle åtgärdstekniker installera och konfigurera en programserver på en fysisk server eller virtuell dator innan de distribuerar AirlinesReservationSample-0.0.1-SNAPSHOT.war till den. Dessa åtgärdstekniker skulle också behöva se till att JDK:et som används på datorn – vilket är det som mvn clean package används för att kompilera WAR-filen – i själva verket motsvarar samma JRE som används av programservern. Det är svårt och tidskrävande att hantera dessa beroenden.
Med en Dockerfile kan du skriva de instruktioner eller lager som behövs för att automatiskt uppnå detta mål genom att lägga in de steg som behövs för att säkerställa att Bokningssystem för flygreservationer har alla beroenden som behövs för att implementera till Docker-kontainermiljön. Den här lösningen är övertygande när du arbetar med skalning på begäran med oplanerade intervall. Varje lager använder Docker-cache, som innehåller containeravbildningens tillstånd vid varje instruktionsmilstolpe, vilket optimerar beräkningstiden och återanvändningen. Om ett lager inte ändras används cachelagrade lager. Vanliga användningsfall för cachelagrade lager är Java-körningen, programservern och andra beroenden för webbappen Flight Booking System for Airline Reservations. Om och när en version ändras på ett tidigare cachelagrat lager skapas en ny cachelagrad post.
En containeravbildning innehåller skrivskyddade filsystemlager. I det här exemplet kopierar Dockerfile Tomcat och Flight Booking System WAR-filen till avbildningen vid byggtiden. Docker lägger till ett separat skrivbart lager när Docker skapar en container från avbildningen. Det skrivbara lagret för varje container registrerar sina egna filsystemändringar utan att ändra avbildningsskikten.
Notera
För filer som lagras i containerns skrivbara lager påverkar tillägg, ändringar och borttagningar containern i stället för den ursprungliga imagen. Att ändra filer som kommer från ett bildlager använder copy-on-write-beteende.
Docker har begreppet flerstegsversioner, en funktion som gör att du kan skapa en mindre containeravbildning med bättre cachelagring och ett mindre säkerhetsavtryck, vilket möjliggör ökad optimering och underhåll av Dockerfile över tid. Du kan till exempel separera containerbyggfasen för att kompilera och skapa programmet från fasen för att köra programmet. Med den här funktionen kan du endast kopiera de artefakter som genererades under kompileringen till produktionscontaineravbildningen, vilket minskar dess fotavtryck. Eftersom containeravbildningar cachelagras kan cachelagrade avbildningar återanvändas om inga ändringar görs, vilket minskar kostnaden och tiden för nedladdning från nätverket.
Tjänster som exponeras i produktionsmiljön måste hanteras noggrant för säkerheten. Därför använder och driftsätter produktionsmiljön en säker containerbild. I exemplet används en Azure Linux-avbildning som tillhandahålls av Microsoft.
Det sista steget använder Microsoft Build för OpenJDK 17 på Azure Linux 3.0. Taggen 17-azurelinux anger uttryckligen namnet på denna bas. Den äldre 17-mariner taggen är fortfarande ett kompatibilitetsalias som speglar Azure Linux-avbildningen. Den bör inte förväxlas med tillbakadragna 17-mariner-cm1 och 17-mariner-cm2 avbildningar. Mer information finns i Microsoft Build för OpenJDK container images.
Notera
Microsoft tillhandahåller containeravbildningar som paketeras med OpenJDK, inklusive Ubuntu, Azure Linux och distroless avbildningar. Bilden distroless har den minsta bildstorleken, men det är svårt att köra Tomcat på den. För att uppnå en enkel design tar avbildningen distroless bort många kommandon och verktyg, inklusive gränssnittet, vilket innebär att du inte kan anropa catalina.sh för att starta Tomcat. Bilden distroless är lämplig för körning av körbara JAR:er, till exempel de som används med Spring Boot eller Quarkus.
I följande exempel används samma version av Microsoft Build för OpenJDK i både byggfasen och den sista fasen. Den här metoden säkerställer att du skapar källkoden med samma version av JDK:et som tomcat för tjänstdistribution använder, vilket hjälper till att undvika oväntat beteende på grund av versionsmatchningar.
Följande bild visar flerstegsversionen och vad som händer i varje steg baserat på de kommandon som anges i Dockerfile:
I steg 0 laddas Tomcat ned från ett versionsspecifikt Apache-arkiv, verifieras med en SHA-512-kontrollsumma och extraheras till en katalog som anges av en miljövariabel på en Ubuntu-avbildning. Variabeln TOMCAT_VERSION anger utgåvan och byggargumentet TOMCAT_SHA512 anger dess förväntade kontrollsumma. Uppdatera båda värdena tillsammans när du väljer en nyare version som stöds. Docker kan återanvända det cachelagrade installationsskiktet medan dess instruktioner och indata är oförändrade. Tomcat-installationen kopieras till miljön i det sista steget för användning.
I steg 1 installeras Maven på en Ubuntu-avbildning och den skapade källkoden och konfigurationsfilerna kopieras över innan Maven-projektet skapas. Varje lager cachelagras, så OS-avbildnings- och Maven-avbildningslagerna återanvänder cachen. Om konfigurationsfiler, källkodsfiler eller webbkatalogen uppdateras återskapas lagren från ändringarna och framåt. Om bygget slutförs utan fel under kompileringen genereras en artefakt med namnet AirlinesReservationSample-0.0.1-SNAPSHOT.war under målkatalogen . Den här artefakten kopieras till den sista fasmiljön för användning.
I det sista steget kopieras Tomcat och Java-byggartefakter från steg 0 respektive steg 1 till en Microsoft Build för OpenJDK 17-avbildning på Azure Linux 3.0. En användare med namnet app äger alla filer som används i projektet, och programmet körs också som app användare i stället för att ha root behörigheter. Den här konfigurationen säkerställer att containeravbildningen kan köras på ett säkert sätt utan att onödiga behörigheter beviljas. Slutligen exponeras portnummer 8080 och skriptet catalina.sh körs för att starta Tomcat. När detta körs på ditt lokala Docker Desktop kan du komma åt det via URL:en http://localhost:8080/AirlinesReservationSample.
I containerize-and-deploy-Java-app-to-Azure/Project/Airlines använder du en installerad textredigerare för att skapa en fil med namnet Dockerfile. Lägg till följande innehåll och spara filen:
Important
Innan du skapar en avbildning som du ska exponera offentligt kontrollerar du den aktuella Tomcat 10.1.x-versionen som stöds på nedladdningssidan för Apache Tomcat och granskar säkerhetsmeddelandena. Uppdatera TOMCAT_VERSION och TOMCAT_SHA512 tillsammans med hjälp av Apaches publicerade versionsinformation. En artefakt som är tillgänglig i Apache-arkivet innebär inte att dess version är aktuell eller rekommenderad.
############################################
# 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"]
Notera
Använd Dockerfile som visas i den här lektionen för den här övningen. Applikationen måste kopieras till webapps/AirlinesReservationSample.war så att URL:erna i följande enheter använder kontexten /AirlinesReservationSample/. Ett annat WAR-filnamn ändrar standardkontexten för Tomcats applikationskontext.
Dockerfile är indelad i tre steg, som beskrivs i följande tabeller:
Installationsfasen för Tomcat:
Docker-kommando Beskrivning FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcatanger basavbildningen till Microsoft Build för OpenJDK 17 på Ubuntu och namnger den här fasentomcat. Det är här Tomcat installeras.ENVENV CATALINA_HOME=/usr/local/tomcatanger en miljövariabel för Tomcat-installationskatalogen.ENVENV TOMCAT_VERSION=10.1.61anger Tomcat-versionen som är låst för det här exemplet. Granska versioner som stöds och uppdatera den tillsammans medTOMCAT_SHA512vid behov.ARGARG TOMCAT_SHA512tillhandahåller Apaches publicerade SHA-512-kontrollsumma för det valda arkivet som ett byggargument.RUNInstallerar curloch CA-certifikat och använder sedancurl -fSLför att ladda ned det versionsspecifika Apache-arkivet.-fgör att begäran misslyckas vid HTTP-fel;-Lföljer omdirigeringar. Arkivet verifieras medsha512sum -c -före extrahering tillCATALINA_HOMEmed--strip-components=1. Kedjan&&stoppas vid fel i stället för att maskera fel under rensningen. Slutligen tar den bort arkivet och onödiga paket och rensar paketcachen.Build-fasen, som kompileras med Java 17:
Docker-kommando Beskrivning FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS buildanger basavbildningen till Microsoft Build för OpenJDK 17 på Ubuntu och namnger den här fasenbuild. Det här steget används för att kompilera Java-programmet.WORKDIRWORKDIR /buildanger arbetskatalogen i containern till/build, där källkoden kopieras och kompileras.RUNRUN apt-get update && apt-get install -y maven && mvn --versioninstallerar Maven, ett verktyg för byggautomatisering som används för Java-projekt, och verifierar installationen.COPYCOPY pom.xml .kopierar Maven-konfigurationsfilen till arbetskatalogen. Den här filen är viktig för att skapa projektet.COPYCOPY src ./srckopierar källkodskatalogen till containern. Det är här Java-programkoden finns.COPYCOPY web ./webkopierar webbresurskatalogen till containern. Detta omfattar de webbprogramresurser som behövs för bygget.RUNRUN mvn clean packagekör Maven-byggprocessen, som kompilerar Java-programmet och paketerar det i en WAR-fil.Paketets slutfas:
Docker-kommando Beskrivning FROMFROM mcr.microsoft.com/openjdk/jdk:17-azurelinuxanger att basavbildningen är Microsoft Build för OpenJDK 17 på Azure Linux 3.0, som används för den slutliga distributionen av programmet.ENVENV CATALINA_HOME=/usr/local/tomcatanger miljövariabeln för Tomcat-installationskatalogen, ungefär som installationssteget.ENVENV PATH=$CATALINA_HOME/bin:$PATHlägger till tomcat-bin-katalogen i systemetPATH, vilket gör att Tomcat-kommandon enkelt kan köras.USERUSER appanger den användare under vilken Tomcat-processen körs, vilket förbättrar säkerheten genom att inte köras som rotanvändare.COPYCOPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME}kopierar Tomcat-installationen fråntomcatfasen och anger ägarskapet tillappanvändaren.COPYCOPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/confkopierar Tomcat-användarkonfigurationsfilen till containern och ställer in ägarskapet påappanvändaren.COPYCOPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.warkopierar den kompilerade WAR-filen frånbuildfasen till tomcat-webbappskatalogen och anger ägarskapet tillappanvändaren.EXPOSEEXPOSE 8080dokumenterar att programmet förväntas lyssna på TCP-port 8080. Den exponerar ingen värdport. Nästa enhet exponerar porten med alternativet-p 8080:8080pådocker run.CMDCMD ["catalina.sh", "run"]anger kommandot för att starta Tomcat när containern körs.
Mer information om Dockerfile-konstruktion finns i Dockerfile-referensen.