Containerisera en Java-app

Slutförd

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 i princip bara en annan systemprocess. Containrar kräver färre systemresurser, vilket resulterar i ett mindre fotavtryck, mindre omkostnader och snabbare starttider för program. Det här ä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.

Översikt över Docker

Docker-körningen används för att skapa, hämta, köra och skicka containeravbildningar. Följande bild visar dessa användningsfall följt av en beskrivning av varje användningsfall/Docker-kommando.

Diagram showing Docker commands.

Docker-kommando beskrivning
docker build Skapar en containeravbildning. i princip de instruktioner/lager som behövs för att Docker i slutändan 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, och det är här Azure Kubernetes Service kommer att hämtas från. Resultatet av det här kommandot är en nätverkshämtning av en avbildning som kommer att ske i Azure. Observera att du kan hämta bilder lokalt. Detta är vanligt när du skapar avbildningar som kräver beroenden/lager som ditt program 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 klonar du lagringsplatsen Flight Booking System for Airline Reservations och cd till projektmappen Airlines webbprogram.

Kommentar

Om Skapandet av Azure Kubernetes Service har slutförts på din CLI-flik använder du den fliken. Om den fortfarande körs öppnar du en ny flik och cd till den plats där du föredrar att klona Flight Booking System for Airline Reservations.

Kör följande kommando i CLI:

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

Kör följande kommando i CLI:

cd containerize-and-deploy-Java-app-to-Azure/Project/Airlines

Kommentar

Om du har Installerat Java och Maven kan du köra följande kommandon i CLI för att få en uppfattning om hur du skapar programmet utan Docker. Om du inte har Java och Maven installerade kan du på ett säkert sätt 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 versionerna åt dig.

Om du har Maven och en JDK(8) eller högre installerad kan du köra följande kommando i CLI:

mvn clean install

Kommentar

Vi har använt mvn clean install kommandot för att illustrera de operativa utmaningarna med att inte använda Docker-flerstegsversioner, som vi kommer att ta upp härnäst. Återigen är det här steget valfritt. Hur som helst kan du på ett säkert sätt gå vidare utan att köra Maven-kommandot.

Maven bör ha skapat Flight Booking System for Airline Reservations Web Application Archive artefakt FlightBookingSystemSample-0.0.-SNAPSHOT.war, som i följande utdata:

[INFO] Building war: /mnt/c/Users/chtrembl/dev/git/containerize-and-deploy-Java-app-to-Azure/Project/FlightBookingSystemSample/target/FlightBookingSystemSample-0.0.1-SNAPSHOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  17.698 s
[INFO] Finished at: 2021-09-28T15:18:07-04:00
[INFO] ------------------------------------------------------------------------

Anta att du är Java-utvecklare och att du just har skapat den här FlightBookingSystemSample-0.0.1-SNAPSHOT.war. Nästa steg är förmodligen att arbeta med åtgärdstekniker för att få artefakten distribuerad till antingen en lokal server eller en virtuell dator. För att programmet ska starta och köras korrekt måste servrarna och de virtuella datorerna vara tillgängliga och konfigurerade med de nödvändiga beroendena. Detta ä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 kan köra på kommandoraden för att montera en containeravbildning, som var och en är lager (som kan cachelagras för effektivitet) som bygger ovanpå 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 FlightBookingSystemSample-0.0.1-SNAPSHOT.war. Det är ett externt beroende som krävs för FlightBookingSystemSample-0.0.1-SNAPSHOT.war att köra, lyssna efter och bearbeta HTTP-begäranden, hantera användarsessioner och underlätta flygbokningar. Om detta var en traditionell, icke-containerbaserad distribution skulle åtgärdstekniker installera och konfigurera en programserver på någon fysisk server och/eller virtuell dator innan de FlightBookingSystemSample-0.0.1-SNAPSHOT.war distribuerar till den. Dessa åtgärdstekniker skulle också behöva se till att JDK:et som används på datorn (det som mvn clean install användes för att kompilera .war) 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 (lager) som behövs för att utföra detta automatiskt genom att lägga i de steg som behövs för att säkerställa att Flight Booking System for Airline Reservations har alla beroenden som krävs för att distribuera till Docker-containerkörningen. Detta är mycket övertygande när du börjar tänka på skalning på begäran med oplanerade intervall. Det är värt att notera att varje lager utnyttjar Docker-cachen, 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 saker som Java-körning, programserver och/eller andra beroenden för webbprogrammet 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 bild visar lager i en containeravbildning. Du kommer att märka att det översta lagret är det skrivskyddade flygbokningssystemet för webbprogramlagret Flygreservationer, som bygger på de tidigare skrivskyddade lagren, som alla är resultatet av kommandona i Dockerfile.

Diagram showing the Docker layers.

Docker har också 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. Till exempel instruktioner som du kan använda för att utföra både en kompilering av programmet (FlightBookingSystemSample-0.0.1-SNAPSHOT.war) och en version av själva containeravbildningen, vilket lämnar resterna av kompileringen FlightBookingSystemSample-0.0.1-SNAPSHOT.war bakom, vilket resulterar i ett mindre fotavtryck. På lång sikt ger detta utdelning när du börjar tänka på dessa bilder som reser runt i nätverket. Med flerstegsversioner använder du flera FROM-instruktioner i Din Dockerfile. Varje FROM-instruktion kan använda en annan bas, och var och en av dessa instruktioner börjar med en ren skiffer, vilket tar bort onödiga filer i cachelagringsskiktet som normalt kan cachelagras.

Det är absolut nödvändigt att se till att programmet skapas av samma JDK som motsvarar samma JRE som ska isoleras i containeravbildningen vid körning. I följande exempel har du en build-fas som använder en specifik version av Maven och en specifik version av JDK:t för att kompilera FlightBookingSystemSample-0.0.1-SNAPSHOT.war. Det här steget säkerställer att alla Docker-körningar som kör den här fasen får den förväntade genererade bytekoden som Dockerfile-författaren har angett (annars måste åtgärdstekniker korsreferensera sin Java- och programserverkörning med utvecklarens). Paketsteget använder sedan en specifik version av Tomcat och JRE som motsvarar JDK:et i byggfasen. Återigen görs detta för att säkerställa att alla beroenden (Java Development Kit JDK, Java Runtime Environment JRE, programserver) kontrolleras och isoleras för att säkerställa det förväntade beteendet på alla datorer som avbildningen ska köras på.

Det är också värt att notera att med den här flerstegsversionen finns det tekniskt sett inget behov av att Maven och Java installeras på systemet. Docker hämtar dem för användning med både att skapa programmet och programkörningen, vilket undviker eventuella versionskonflikter och oväntat beteende. såvida du inte kompilerar kod och skapar artefakter utanför Docker.

Följande bild visar flerstegsversionen och vad som händer i varje steg baserat på de kommandon som anges i Dockerfile. I steg 0 kompileras webbappen Flight Booking System for Airline Reservations och FlightBookingSystemSample-0.0.1-SNAPSHOT.war genereras. Det här steget möjliggör konsekvens för Maven- och Java-versioner som används för att kompilera det här programmet. När har FlightBookingSystemSample-0.0.1-SNAPSHOT.war skapats är det det enda lagret som behövs för steg 1 (Körningssteg) och alla tidigare lager kan tas bort. Docker använder sedan det här FlightBookingSystemSample-0.0.1-SNAPSHOT.war lagret från steg 0 för att konstruera de återstående lagren som behövs för körning. I det här fallet konfigurerar du programservern och startar programmet.

Diagram showing the Docker multistage build.

Skapa en fil med namnet Dockerfile i roten i projektet, containerize-and-deploy-Java-app-to-Azure/Project/Airlines:

vi Dockerfile

Lägg till följande innehåll i Dockerfile och spara och avsluta sedan genom att trycka på ESC och sedan skriva :wq! och trycka på Retur:

#
# Build stage
#
FROM maven:3.6.0-jdk-11-slim AS build
WORKDIR /build
COPY pom.xml .
COPY src ./src
COPY web ./web
RUN mvn clean package

#
# Package stage
#
FROM tomcat:8.5.72-jre11-openjdk-slim
COPY tomcat-users.xml /usr/local/tomcat/conf
COPY --from=build /build/target/*.war /usr/local/tomcat/webapps/FlightBookingSystemSample.war
EXPOSE 8080
CMD ["catalina.sh", "run"]

Kommentar

Alternativt innehåller Dockerfile_Solution i projektets rot det innehåll som behövs.

Den här Dockerfile Build-fasen har sex instruktioner:

Docker-kommando beskrivning
FROM FROM maven kommer att vara basskiktet från vilket detta FlightBookingSystemSample-0.0.1-SNAPSHOT.war skapas, en specifik version av Maven och en specifik version av JDK för att säkerställa att samma kompilering av bytekod sker på alla datorer som kör den här versionen.
WORKDIR WORKDIR används för att definiera arbetskatalogen för en container vid en viss tidpunkt. i det här fallet, där kompilerade artefakter kommer att finnas.
COPY COPY lägger till filer från Docker-klientens aktuella katalog. När du konfigurerar de filer som krävs för att Maven ska kompilera krävs pom.xml av Docker-kontexten.
COPY Konfigurerar de filer som behövs för att Maven ska kompileras. Docker-kontexten behöver mappen src som innehåller webbappen Flight Booking System for Airline Reservations.
COPY Konfigurerar de filer som behövs för att Maven ska kompileras. Webbkontexten för Docket behöver mappen som innehåller webbappen Flight Booking System for Airline Reservations beroenden.
KÖR Instruktionen RUN mvn clean package används för att köra alla kommandon ovanpå den aktuella avbildningen. I det här fallet används RUN för att köra Maven-versionen, som kompilerar FlightBookingSystemSample-0.0.1-SNAPSHOT.war.

Det här Docker-filpaketet har fem instruktioner:

Docker-kommando beskrivning
FROM FROM tomcat kommer att vara basskiktet som detta ovanpå vilket containeravbildning kommer att skapas. Containeravbildningen Flight Booking System for Airline Reservations är en avbildning som bygger på tomcat-avbildningen. Docker-körningen försöker hitta tomcat-avbildningen lokalt. Om den inte har den här versionen hämtas en från registret. Om du inspekterar tomcat-avbildningen som refereras här skulle du upptäcka att den har skapats med många andra lager, vilket gör den återanvändbar som en paketerad programservercontaineravbildning som världen kan använda när de distribuerar sitt Java-program. Vi valde och testade tomcat:8.5.72-jre11-openjdk-slim i modulens syfte. Observera att alla tidigare lager från den första build-fasen är borta när Docker känner igen den här andra FROM-instruktionen.
COPY COPY tomcat-users.xml kopierar tomcat-users.xml-filen som hanterar flight booking system for Airline Reservations-användare (hanteras inom källkontrollen med Tomcat-identitet, vanligtvis i ett externt identitetshanteringssystem) till tomcat-containeravbildningen så att den finns i containeravbildningen varje gång en containeravbildning skapas.
ADD ADD target/*.war /usr/local/tomcat/webapps/FlightBookingSystemSample.war kopierar den maven som kompilerats FlightBookingSystemSample-0.0.1-SNAPSHOT.war till mappen tomcat images webapps för att säkerställa att när Tomcat initieras kommer den att hitta den FlightBookingSystemSample-0.0.1-SNAPSHOT.war som ska installeras på programservern.
EXPOSE EXPOSE 8080 krävs eftersom Tomcat har konfigurerats för att lyssna på trafik på port 8080. Detta säkerställer att Docker-processen lyssnar på den här porten.
CMD CMD-instruktionen anger ett kommando som ska köras när containern körs. I det här fallet CMD ["catalina.sh", "run"] instruerar du Docker att initiera Tomcat-programservern.

Kommentar

Utan en versionstagg på FROM tomcat raden tillämpas den senaste versionen. I allmänhet vill du använda en versionstagg (kom ihåg att cachelagring tillämpas, så om lagren ändras konsekvent får du bandbredd, svarstid, beräkningstid och/eller biverkningar av otestade versioner/lager). För den här modulens skull har vi valt specifika Maven-, Tomcat- och Java JRE/JDK-taggar som testas för att fungera med FlightBookingSystemSample-0.0.1-SNAPSHOT.war vid körning.

Mer information om Dockerfile-konstruktion finns i Dockerfile-referens