Konteneryzowanie aplikacji Java

Ukończone

W tej lekcji konteneryzujesz aplikację Java.

Jak wspomniano wcześniej, kontenery działają bezpośrednio na systemie operacyjnym hosta, jądrze i sprzęcie jako zwykłe procesy systemowe. Kontenery wymagają mniejszej liczby zasobów systemowych, co skutkuje mniejszym zużyciem, mniejszym obciążeniem i krótszym czasem uruchamiania aplikacji. Te korzyści będą doskonałymi przykładami zastosowań skalowania na żądanie.

Istnieją kontenery systemu Windows i kontenery systemu Linux. W tym module używasz powszechnie używanego środowiska uruchomieniowego platformy Docker do kompilowania obrazu kontenera systemu Linux. Następnie wdrożysz obraz kontenera systemu Linux w systemie operacyjnym hosta komputera lokalnego. Na koniec wdrożysz obraz kontenera systemu Linux w usłudze Azure Kubernetes Service.

Omówienie platformy Docker

Środowisko uruchomieniowe platformy Docker służy do kompilowania, ściągania, uruchamiania i wypychania obrazów kontenerów, jak pokazano na poniższym diagramie:

Diagram przedstawiający polecenia budowania, ściągania, wysyłania i uruchamiania platformy Docker łączące klienta, host Docker i rejestr.

W poniższej tabeli opisano każde polecenie platformy Docker:

Polecenie Docker Opis
docker build Tworzy obraz kontenera, który składa się z instrukcji lub warstw potrzebnych do uruchomienia kontenera na podstawie tego obrazu. Wynikiem tego polecenia jest obraz.
docker pull Pobiera obraz z rejestru do magazynu obrazów demona platformy Docker wybranego przez klienta. Istniejące warstwy obrazów można ponownie użyć. W tym module lokalne środowisko platformy Docker używa obrazów z rejestrów podczas programowania; później węzły usługi AKS ściągają obraz aplikacji z Azure Container Registry na potrzeby wdrożenia.
docker run Tworzy i uruchamia nowy kontener na podstawie obrazu. Kontener uruchamia skonfigurowany proces uruchamiania, z możliwością nadpisania z poziomu wiersza polecenia. Warstwy obrazów zapewniają system plików kontenera; Instrukcje kompilacji pliku Dockerfile nie są ponownie wykonywane po uruchomieniu kontenera.
docker push Usługa Azure Container Registry przechowuje obrazy, aby były łatwo dostępne i blisko sieci dla wdrożeń i skalowania platformy Azure.

Klonowanie aplikacji Java

Najpierw sklonuj repozytorium Flight Booking System for Airline Reservations i przejdź do folderu projektu aplikacji internetowej Airlines.

Notatka

Jeśli tworzenie usługi Azure Kubernetes Service zostało zakończone w zakładce terminala, użyj tej zakładki. Jeśli nadal trwa, otwórz nową zakładkę i przejdź do lokalizacji, w której wolisz sklonować system rezerwacji lotów dla linii lotniczych.

Uruchom następujące polecenia:

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

Opcjonalnie, jeśli masz zainstalowane środowisko Java i Maven, możesz uruchomić następujące polecenie w konsoli terminalu, aby zrozumieć środowisko kompilowania aplikacji bez platformy Docker. Jeśli nie masz zainstalowanego środowiska Java i narzędzia Maven, możesz bezpiecznie przejść do następnej sekcji : Konstruowanie pliku platformy Docker. W tej sekcji użyjesz platformy Docker, aby ściągnąć środowisko Java i narzędzie Maven w celu wykonania kompilacji w Twoim imieniu.

mvn clean package

Notatka

Użyliśmy polecenia mvn clean package do zilustrowania wyzwań operacyjnych związanych z nienależytym użyciem wielostopniowych kompilacji w Dockerze, co omówimy w dalszej części. Ponownie ten krok jest opcjonalny. Tak czy inaczej, można bezpiecznie kontynuować bez wykonywania polecenia Maven.

Jeśli proces zakończył się pomyślnie, narzędzie Maven pomyślnie zbudowało artefakt Web Application Archive aplikacji Flight Booking System for Airline Reservations AirlinesReservationSample-0.0.1-SNAPSHOT.war, jak pokazano na poniższych danych wyjściowych. Sygnatura czasowa kompilacji i czas trwania mogą się różnić:

[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] ------------------------------------------------------------------------

Wyobraź sobie, że jesteś deweloperem Java i właśnie zbudowałeś AirlinesReservationSample-0.0.1-SNAPSHOT.war. Następnym krokiem jest prawdopodobnie współpraca z inżynierami operacji w celu wdrożenia tego artefaktu na serwerze lokalnym lub maszynie wirtualnej. Aby aplikacja mogła zostać uruchomiona i działać pomyślnie, serwery i maszyny wirtualne muszą być dostępne i skonfigurowane z wymaganymi zależnościami. Ten proces jest trudny i czasochłonny, zwłaszcza w sytuacjach, gdy zwiększa się obciążenie aplikacji. W przypadku kontenerów te wyzwania są złagodzone.

Utwórz plik Dockerfile

Teraz możesz utworzyć plik Dockerfile. Plik Dockerfile to dokument tekstowy zawierający wszystkie polecenia wykonywane przez użytkownika w wierszu polecenia w celu utworzenia obrazu kontenera. Obraz kontenera może zawierać wiele warstw systemu plików tylko do odczytu. Platforma Docker może ponownie używać buforowanych wyników kompilacji dla niezmienionych kroków. Warstwy układają się jedna na drugiej.

Na przykład system rezerwacji lotów dla rezerwacji linii lotniczych musi zostać wdrożony i uruchomiony na serwerze aplikacji. Serwer aplikacji nie jest zawarty w AirlinesReservationSample-0.0.1-SNAPSHOT.war. Jest to zależność zewnętrzna wymagana dla AirlinesReservationSample-0.0.1-SNAPSHOT.war do uruchamiania, nasłuchiwania i przetwarzania żądań HTTP, zarządzania sesjami użytkowników i ułatwienia rezerwacji lotów. Jeśli użyto tradycyjnego, niekontenerowego wdrożenia, inżynierowie operacji zainstalują i skonfigurują serwer aplikacji na pewnym serwerze fizycznym lub maszynie wirtualnej przed wdrożeniem w nim pliku AirlinesReservationSample-0.0.1-SNAPSHOT.war . Inżynierowie operacji musieliby również upewnić się, że zestaw JDK używany na maszynie — który jest używany mvn clean package do kompilowania pliku WAR — w rzeczywistości odpowiada temu samemu środowisku JRE używanemu przez serwer aplikacji. Zarządzanie tymi zależnościami jest trudne i czasochłonne.

Za pomocą pliku Dockerfile można napisać instrukcje lub warstwy potrzebne do automatycznego osiągnięcia tego celu, nakładając warstwy w krokach niezbędnych do zapewnienia, że system rezerwacji lotów ma wszystkie zależności wymagane do wdrożenia w środowisku uruchomieniowym Docker. To rozwiązanie jest przekonujące, gdy pracujesz ze skalowaniem na żądanie w nieplanowanych odstępach czasu. Każda warstwa używa pamięci podręcznej Docker, która zawiera stan obrazu kontenera na każdym etapie instruktażowym, co optymalizuje czas przetwarzania i ponowne wykorzystanie. Jeśli warstwa nie zmienia się, używane są buforowane warstwy. Typowe przypadki użycia buforowanych warstw to środowisko uruchomieniowe Java, serwer aplikacji i inne zależności dla aplikacji internetowej Flight Booking System for Airline Reservations. Jeśli i kiedy wersja zmieni się na wcześniej buforowanej warstwie, zostanie utworzony nowy buforowany wpis.

Obraz kontenera zawiera warstwy systemu plików tylko do odczytu. W tym przykładzie plik Dockerfile kopiuje Tomcat oraz plik WAR systemu Flight Booking System do obrazu w czasie kompilacji. Platforma Docker dodaje oddzielną warstwę zapisywalną podczas tworzenia kontenera na podstawie obrazu. Każda zapisywalna warstwa kontenera rejestruje własne zmiany systemu plików bez modyfikowania warstw obrazu.

Notatka

W przypadku plików przechowywanych w zapisywalnej warstwie kontenera dodania, modyfikacje i usunięcia mają wpływ na ten kontener, a nie oryginalny obraz. Zmiana plików pochodzących z warstwy obrazu wykorzystuje mechanizm copy-on-write.

Platforma Docker ma koncepcję kompilacji wieloeeżowych, czyli funkcji, która umożliwia tworzenie mniejszego obrazu kontenera z lepszym buforowaniem i mniejszym zużyciem zabezpieczeń, co pozwala zwiększyć optymalizację i konserwację pliku Dockerfile w czasie. Na przykład można oddzielić etap kompilacji kontenera na potrzeby kompilowania i kompilowania aplikacji z etapu uruchamiania aplikacji. Ta funkcja umożliwia kopiowanie tylko artefaktów wygenerowanych podczas kompilacji do obrazu kontenera produkcyjnego, co zmniejsza jego rozmiar. Ponieważ obrazy kontenerów są buforowane, jeśli nie ma żadnych zmian, obrazy buforowane mogą być ponownie używane, co zmniejsza koszt i czas pobierania z sieci.

Usługi uwidocznione w środowisku produkcyjnym muszą być starannie zarządzane pod kątem zabezpieczeń. W związku z tym środowisko produkcyjne używa i zarządza bezpiecznym obrazem kontenera. W przykładzie użyto obrazu systemu Azure Linux dostarczonego przez Microsoft.

Ostatni etap używa Microsoft Build of OpenJDK 17 w systemie Azure Linux 3.0. Tag 17-azurelinux jawnie nadaje tej bazie nazwę. Starszy 17-mariner tag pozostaje aliasem zgodności, który odzwierciedla obraz Azure Linux. Nie należy go mylić z wycofanymi 17-mariner-cm1 obrazami i 17-mariner-cm2 obrazami. Aby uzyskać więcej informacji, zobacz obrazy kontenerów Microsoft Build of OpenJDK.

Notatka

Microsoft udostępnia obrazy kontenerów z dołączonym pakietem OpenJDK, w tym obrazy Ubuntu, Azure Linux i distroless. Obraz distroless ma najmniejszy rozmiar obrazu, ale uruchomienie serwera Tomcat na nim jest trudne. Aby uzyskać lekki projekt, distroless obraz usuwa wiele poleceń i narzędzi, w tym powłokę, co oznacza, że nie można wywołać catalina.sh, aby uruchomić Tomcat. Obraz distroless jest odpowiedni do uruchamiania wykonywalnych plików JAR, takich jak te używane z Spring Boot lub Quarkus.

W poniższym przykładzie ta sama wersja zestawu Microsoft Build openJDK jest używana zarówno na etapie kompilacji, jak i na ostatnim etapie. Takie podejście zapewnia utworzenie kodu źródłowego z tą samą wersją zestawu JDK używanego przez wdrożenie usługi Tomcat, co pomaga uniknąć nieoczekiwanego zachowania z powodu niezgodności wersji.

Na poniższej ilustracji przedstawiono kompilację wieloetapową i elementy występujące na każdym etapie na podstawie poleceń określonych w pliku Dockerfile:

Diagram przedstawiający instrukcje dotyczące pliku Dockerfile tworzenia warstw obrazów na etapach instalacji serwera Tomcat, kompilacji kodu i etapu uruchomieniowego.

Na etapie 0 serwer Tomcat jest pobierany z archiwum Apache specyficznego dla wersji, zweryfikowany przy użyciu sumy kontrolnej SHA-512 i wyodrębniony do katalogu określonego przez zmienną środowiskową na obrazie systemu Ubuntu. Zmienna TOMCAT_VERSION określa wydanie, a TOMCAT_SHA512 argument kompilacji określa oczekiwaną sumę kontrolną. Zaktualizuj obie wartości razem podczas wybierania nowszej obsługiwanej wersji. Platforma Docker może ponownie używać buforowanej warstwy instalacji, jeśli jej instrukcje i dane wejściowe są niezmienione. Instalacja serwera Tomcat jest kopiowana do środowiska końcowego etapu w celu użycia.

Na etapie 1 narzędzie Maven jest instalowane na obrazie systemu Ubuntu, a utworzone pliki źródłowe i pliki konfiguracji są kopiowane przed utworzeniem projektu Maven. Każda warstwa jest buforowana, więc warstwy obrazu systemu operacyjnego i obrazu Maven wykorzystują pamięć podręczną ponownie. Jeśli pliki konfiguracji, pliki kodu źródłowego lub katalog internetowy zostaną zaktualizowane, warstwy z poziomu zmian zostaną ponownie skompilowane. Jeśli kompilacja zakończy się pomyślnie bez błędów podczas kompilacji, w katalogu docelowym zostanie wygenerowany artefakt o nazwie AirlinesReservationSample-0.0.1-SNAPSHOT.war. Ten artefakt jest kopiowany do środowiska końcowego etapu, aby być używanym.

Na ostatnim etapie artefakty kompilacji tomcat i Java z etapu 0 i etapu 1 są kopiowane odpowiednio do obrazu Microsoft Build of OpenJDK 17 w systemie Azure Linux 3.0. Użytkownik app jest właścicielem wszystkich plików używanych w projekcie, a aplikacja jest również uruchamiana jako użytkownik app zamiast posiadać uprawnienia root. Ta konfiguracja gwarantuje, że obraz kontenera może być bezpiecznie użytkowany bez udzielania niepotrzebnych uprawnień. Na koniec numer portu 8080 jest uwidoczniony, a skrypt catalina.sh jest wykonywany w celu uruchomienia serwera Tomcat. Po uruchomieniu tego polecenia na lokalnym pulpicie platformy Docker możesz uzyskać do niego dostęp za pośrednictwem adresu URL http://localhost:8080/AirlinesReservationSample.

W containerize-and-deploy-Java-app-to-Azure/Project/Airlinesprogramie użyj zainstalowanego edytora tekstów, aby utworzyć plik o nazwie Dockerfile. Dodaj następującą zawartość i zapisz plik:

Important

Przed utworzeniem obrazu, który zostanie udostępniony publicznie, sprawdź bieżącą obsługiwaną wersję serwera Tomcat 10.1.x na stronie pobierania apache Tomcat i przejrzyj powiadomienia o zabezpieczeniach. Aktualizuj TOMCAT_VERSION i TOMCAT_SHA512 razem przy użyciu opublikowanych informacji o wersji oprogramowania Apache. Artefakt pozostały dostępny w archiwum Apache nie oznacza, że jego wersja jest bieżąca lub zalecana.

############################################
# 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"]

Notatka

W tym ćwiczeniu użyj pliku Dockerfile pokazanego w tej lekcji. Aplikację należy skopiować do webapps/AirlinesReservationSample.war, aby adresy URL w poniższych jednostkach używały kontekstu /AirlinesReservationSample/. Inna nazwa pliku WAR zmienia domyślny kontekst aplikacji Tomcat.

Plik Dockerfile jest podzielony na trzy etapy, które są opisane w następujących tabelach:

  • Etap instalacji serwera Tomcat:

    Polecenie Docker Opis
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat Ustawia obraz podstawowy na Microsoft Build of OpenJDK 17 w systemie Ubuntu i nazywa ten etap tomcat. W tym miejscu jest instalowany serwer Tomcat.
    ENV ENV CATALINA_HOME=/usr/local/tomcat Ustawia zmienną środowiskową dla katalogu instalacyjnego serwera Tomcat.
    ENV ENV TOMCAT_VERSION=10.1.61 Ustawia wydanie serwera Tomcat przypięte na potrzeby tego przykładu. Przejrzyj obsługiwane wersje i zaktualizuj je wraz z TOMCAT_SHA512 w razie potrzeby.
    ARG ARG TOMCAT_SHA512 Dostarcza opublikowaną przez Apache sumę kontrolną SHA-512 dla wybranego archiwum jako argument kompilacji.
    RUN Instaluje curl i certyfikaty urzędu certyfikacji, a następnie używa curl -fSL do pobierania archiwum Apache specyficznego dla wersji. -f sprawia, że błędy HTTP kończą się niepowodzeniem; -L podąża za przekierowaniami. Archiwum jest weryfikowane sha512sum -c - przed wyodrębnianiem do CATALINA_HOME za pomocą polecenia --strip-components=1. Łańcuch && zatrzymuje się w przypadku błędu zamiast maskowania błędów podczas czyszczenia. Na koniec usuwa archiwum i niepotrzebne pakiety i czyści pamięć podręczną pakietu.
  • Etap kompilacji, który kompiluje się z językiem Java 17:

    Polecenie Docker Opis
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS build Ustawia obraz podstawowy na Microsoft Build of OpenJDK 17 w systemie Ubuntu i nazywa ten etap build. Ten etap służy do kompilowania aplikacji Java.
    WORKDIR WORKDIR /build Ustawia katalog roboczy wewnątrz kontenera na /build, gdzie kod źródłowy jest kopiowany i kompilowany.
    RUN RUN apt-get update && apt-get install -y maven && mvn --version instaluje narzędzie Maven, narzędzie automatyzacji kompilacji używane na potrzeby projektów Java i weryfikuje jego instalację.
    COPY COPY pom.xml . kopiuje plik konfiguracji programu Maven do katalogu roboczego. Ten plik jest niezbędny do kompilowania projektu.
    COPY COPY src ./src Kopiuje katalog kodu źródłowego do kontenera. W tym miejscu znajduje się kod aplikacji Java.
    COPY COPY web ./web kopiuje katalog zasobów internetowych do kontenera. Obejmuje to zasoby aplikacji internetowej potrzebne do kompilacji.
    RUN RUN mvn clean package Wykonuje proces kompilacji narzędzia Maven, który kompiluje aplikację Java i pakuje ją do pliku WAR.
  • Końcowy etap pakietu:

    Polecenie Docker Opis
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-azurelinuxUstawia obraz podstawowy na Microsoft Build of OpenJDK 17 w systemie Azure Linux 3.0, który jest używany do końcowego wdrożenia aplikacji.
    ENV ENV CATALINA_HOME=/usr/local/tomcat Ustawia zmienną środowiskową dla katalogu instalacyjnego serwera Tomcat, podobnie jak w przypadku etapu instalacji.
    ENV ENV PATH=$CATALINA_HOME/bin:$PATH Dodaje katalog bin tomcat do systemu PATH, co umożliwia łatwe uruchamianie poleceń serwera Tomcat.
    USER USER app Określa użytkownika, w którym jest uruchamiany proces Tomcat, zwiększając bezpieczeństwo, nie uruchamiając go jako użytkownik główny.
    COPY COPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME} kopiuje instalację Tomcata z etapu tomcat, ustawiając jej własność na użytkownika app.
    COPY COPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/conf Kopiuje plik konfiguracji użytkownika serwera Tomcat do kontenera, ustawiając własność użytkownikowi app .
    COPY COPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.war Kopiuje skompilowany plik WAR z etapu build do katalogu Tomcat webapps, ustawiając własność na użytkownika app.
    EXPOSE EXPOSE 8080 dokumentuje, że aplikacja ma nasłuchiwać na porcie TCP 8080. Nie publikuje portu hosta. Następna jednostka publikuje port z opcją -p 8080:8080 na docker run.
    CMD CMD ["catalina.sh", "run"] Określa polecenie uruchamiania serwera Tomcat po uruchomieniu kontenera.

Aby uzyskać więcej informacji na temat konstrukcji pliku Dockerfile, zobacz dokumentację pliku Dockerfile.