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 |
Containrar initieras från avbildningar som hämtas från register som Azure Container Registry. Det är i det här registret som Azure Kubernetes Service hämtar från. Resultatet av det här kommandot är att en avbildning hämtas över nätverket, vilket sker i Azure. Du kan också hämta bilder lokalt. Det här alternativet är vanligt när du skapar avbildningar som kräver beroenden eller lager som programmet kan behöva, till exempel en programserver. |
docker run |
En instans av en avbildning som körs är en container och det här kommandot kör alla lager som behövs för att köra och interagera med det containerprogram som körs. Resultatet av det här kommandot är en programprocess som körs på värdoperativsystemet. |
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 så har Maven framgångsrikt skapat flygbokningssystemet för webbapplikationsarkivet för flygreservationer, artefakten AirlinesReservationSample-0.0.1-SNAPSHOT.war, enligt följande utdata:
[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. Varje bild är ett lager som kan cachelagras för effektivitet. 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.
Följande diagram visar skikten i en containeravbildning. När kommandona i Dockerfile körs skapas lagren. Det översta lagret är det läs-/skrivbara flightbokningssystemet för webbapplagret Flygreservationer. Det lagret bygger på de tidigare skrivskyddade lagren.
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 avbildningen CBL-Mariner som tillhandahålls av Microsoft.
CBL-Mariner Linux är ett enkelt operativsystem som endast innehåller de paket som behövs för en molnmiljö. Du kan anpassa den via anpassade paket och verktyg för att passa kraven för ditt program. CBL-Mariner genomgår Azure-valideringstester och är kompatibel med Azure-agenter. Microsoft bygger och testar CBL-Mariner för att driva olika användningsfall, allt från Azure-tjänster till att driva IoT-infrastruktur. Det är den internt rekommenderade Linux-distributionen för användning med Microsofts molntjänster och relaterade produkter.
Notera
Microsoft tillhandahåller containeravbildningar som paketeras med OpenJDK, inklusive Ubuntu, CBL-Marineroch 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 of 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 och extraheras till en katalog som anges av en miljövariabel på en Ubuntu-avbildning. Variabeln TOMCAT_VERSION anger vilken version av Tomcat som ska laddas ned. Om en ny version av Tomcat släpps bör du uppdatera versionsnumret eftersom en ny avbildning endast hämtas när versionsnumret ändras. Annars används den cachelagrade avbildningen. Tomcat som laddats ned kopieras till den sista fasmiljön 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 används den säkra CBL-Mariner avbildningen från Microsoft för att kopiera Tomcat- respektive Java-kompileringsartefakterna från steg 0 respektive steg 1. 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 rotmappen för projektet, containerize-and-deploy-Java-app-to-Azure/Project/Airlines, använder du följande kommando för att skapa en fil med namnet Dockerfile:
vi Dockerfile
Lägg till följande innehåll i Dockerfile och spara och avsluta sedan. Om du vill spara och avsluta trycker du på ESC, skriver :wq!och trycker sedan på Retur.
############################################
# 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"]
Notera
Du kan valfritt använda Dockerfile_Solution-filen i projektets rot, som innehåller det innehåll du behöver.
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 of 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.33anger vilken version av Tomcat som ska installeras. Detta bör uppdateras till den senaste versionen efter behov.RUNKommandot RUNuppdaterar paketlistan, installerarcurl, laddar ned den angivna versionen av Tomcat, extraherar den, flyttar den till den angivna katalogen och rensar onödiga filer och paket. Detta säkerställer att bilden förblir lätt.Build-fasen, som kompileras med Java 17:
Docker-kommando Beskrivning FROMFROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS buildanger basavbildningen till Microsoft Build of 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-marineranger basavbildningen till Microsoft Build of OpenJDK 17 påCBL-Mariner, 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 8080exponerar port 8080, standardporten för Tomcat, vilket ger extern åtkomst till programmet.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.