將 Java 應用程式容器化

已完成

在此單元中,您會容器化 Java 應用程式。

如先前所述,容器會直接在主機作系統、核心和硬體上執行,就像一般系統進程一樣。 容器需要較少的系統資源,因而產生較小的使用量、較少的額外負荷,以及更快的應用程式啟動時間。 這些好處是隨需擴展的絕佳使用範例。

有 Windows 容器和 Linux 容器。 在本課程模組中,您會使用廣泛使用的 Docker 運行時間來建置 Linux 容器映射。 接著,您會將 Linux 容器映射部署到本機電腦的主機作系統。 最後,您會將Linux容器映像部署至 Azure Kubernetes Service。

Docker 概觀

Docker 運行時間可用來建置、提取、執行和推送容器映射,如下圖所示:

顯示 Docker 命令的圖表。

下表描述每個 Docker 命令:

Docker 命令 說明
docker build 建置容器映像,其中包含 Docker 從映像建立執行中容器所需的指示或層。 此命令的結果是影像。
docker pull 容器會從映像初始化,這些映像是從 Azure Container Registry 等登錄提取而來。 此登錄是 Azure Kubernetes Service 從中提取的位置。 此命令的結果是映像的網路提取,這會在 Azure 中發生。 您可以選擇性地在本機提取映像。 建置需要應用程式可能需要之相依性或階層的映像 (例如應用程式伺服器) 時,這個選項很常見。
docker run 映像運行中的實例是一個容器,該命令會執行所有需要的層,以運行並與該運行中的容器應用程式互動。 此命令的結果是在主機作系統上執行的應用程式進程。
docker push Azure Container Registry 會儲存映像,使其快速可用,並關閉網路以進行 Azure 部署和調整。

複製Java應用程式

首先,複製航空公司航班預訂系統的存放庫,並導航至航空公司網頁應用程式項目資料夾。

備註

如果在 CLI 索引標籤中完成 Azure Kubernetes Service 建立,請使用該索引標籤。如果仍在執行中,請開啟新的索引標籤,並流覽至您想要複製航空公司預訂航班預訂系統的位置。

執行以下命令:

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

或者,如果您已安裝 Java 和 Maven,您可以在終端機控制台中執行下列命令,以了解在沒有 Docker 的情況下建置應用程式的體驗。 如果您沒有安裝 Java 和 Maven,可以安全地繼續進行下 一節建構 Docker 檔案。 在該區段中,您會使用 Docker 來提取 JAVA 和 Maven,以代表您執行組建。

mvn clean package

備註

mvn clean package我們使用 命令來說明不使用 Docker 多階段組建的作業挑戰,我們接下來會討論這些挑戰。 同樣地,此步驟是選擇性的。 無論哪種方式,您都可以放心地在不執行 Maven 命令的情況下繼續。

如果程序成功,Maven 已成功建置航空公司保留 Web 應用程式封存航班預訂的系統成品 AirlinesReservationSample-0.0.1-SNAPSHOT.war,如下列輸出所示:

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

假設您是 Java 開發人員,而且您剛建置 AirlinesReservationSample-0.0.1-SNAPSHOT.war。 您的下一個步驟可能是與作業工程師合作,讓此成品部署至內部部署伺服器或虛擬機。 若要讓應用程式順利啟動並執行,伺服器和虛擬機必須可供使用,並設定必要的相依性。 此過程具有挑戰性且耗時,尤其是在需求量增加時,當應用程式遇到更高負載。 使用容器時,這些挑戰會得到緩解。

建構 Dockerfile

現在您已準備好撰寫 Dockerfile。 Dockerfile 是一份文字檔,其中包含使用者將在命令行上執行的所有命令,以組合容器映像。 每個影像都是可快取以提高效率的階層。 層次相互堆疊。

例如,航空公司預訂航班預訂系統必須部署至應用程式伺服器內部並執行。 應用程式伺服器未封裝在 AirlinesReservationSample-0.0.1-SNAPSHOT.war 內。 這是 AirlinesReservationSample-0.0.1-SNAPSHOT.war 執行、接聽和處理 HTTP 要求、管理用戶會話以及加速航班預訂所需的外部相依性。 如果您使用傳統的非容器化部署,作業工程師會在部署 AirlinesReservationSample-0.0.1-SNAPSHOT.war 之前,先在某些實體伺服器或虛擬機上安裝及設定應用程式伺服器。 這些作業工程師也需要確保機器上使用的 JDK (mvn clean package 用來編譯 WAR 的工具) 實際上對應至應用程式伺服器所使用的相同 JRE。 管理這些相依性非常困難且耗時。

使用 Dockerfile,您可以撰寫自動完成此目標所需的指示或階層,方法是藉由步驟中的必要圖層,確保適用於航空公司預約的航班預訂系統具有部署至 Docker 容器執行階段所需的所有相依性。 當您以非規劃間隔使用隨選調整時,此解決方案非常具有吸引力。 每一層都會使用 Docker 快取,其中包含每個指示性里程碑的容器映像檔狀態,優化計算時間和重複利用。 如果圖層未變更,則會使用快取的圖層。 快取層的常見使用案例包括 Java 執行環境、應用程式伺服器,以及航空公司訂位 Web 應用程式的航班訂票系統的其他相依性。 如果先前快取的階層上發生版本變更,將會建立新的快取項目。

下圖描述容器映像的圖層。 執行 Dockerfile 中的命令時,會建立層次。 最上層是航空公司預訂 Web 應用層的讀取/寫入航班預訂系統。 該層建置在先前唯讀層之上。

顯示 Docker 層的圖表。

Docker 具有多階段組建的概念,這項功能可讓您建立較小的容器映像檔,並且具有更好的快取功能和較小的安全性風險,從而可以隨著時間不斷優化和維護 Dockerfile。 例如,您可以將用於編譯和建置應用程式的容器建置階段與執行應用程式的階段分開。 這項功能可讓您只將建置過程中產生的構建工件複製到生產容器映像檔,以減少佔用。 因為容器映像會快取,如果沒有變更,則可以重複使用快取的映射,降低從網路下載的成本和時間。

在生產環境中公開的服務必須謹慎管理,才能獲得安全性。 因此,生產環境會使用並操作安全的容器映像。 此範例會使用 CBL-Mariner Microsoft 所提供的影像。

CBL-Mariner Linux 是輕量型作系統,僅包含雲端環境所需的套件。 您可以透過自定義套件和工具來自定義它,以符合應用程式的需求。 CBL-Mariner 會進行 Azure 驗證測試,且與 Azure 代理程式相容。 Microsoft建置和測試 CBL-Mariner 來提供各種使用案例,範圍從 Azure 服務到支援 IoT 基礎結構。 這是內部建議的Linux發行版,可與Microsoft雲端服務和相關產品搭配使用。

備註

Microsoft 提供與 OpenJDK 搭配的容器映像,包括 UbuntuCBL-Marinerdistrolessdistroless 映像的映像大小為最小,但對其執行 Tomcat 是一項挑戰。 為了達到輕量化設計,distroless 映像移除許多命令和工具,包括 Shell,這表示您無法呼叫 catalina.sh 來啟動 Tomcat。 distroless 映像適用於執行可執行的 JAR,例如搭配 Spring Boot 或 Quarkus 使用的 JAR。

在下列範例中,在建置階段和最終階段中都會使用相同版本的 Microsoft OpenJDK 組建。 此方法可確保您使用服務部署 Tomcat 所使用的相同 JDK 版本來建置原始程式碼,這有助於避免因版本不符而發生非預期的行為。

下圖描述多階段組建,以及根據 Dockerfile 中指定的命令,在每個階段中發生的狀況:

顯示 Docker 多階段組建的圖表。

在階段 0 中,Tomcat 會被下載並解壓縮到 Ubuntu 映像中的一個由環境變數指定的目錄。 變數 TOMCAT_VERSION 會指定要下載的 Tomcat 版本。 如果發行了新版本的 Tomcat,您應該更新版本號碼,因為只有在版本號碼更新時才會獲取新的映像檔。 否則會使用快取的映像。 下載的 Tomcat 被複製到最終階段環境以供使用。

在階段 1 中,Maven 會安裝在 Ubuntu 映射上,而建立的原始程式碼和組態檔會在建置 Maven 專案之前先複製。 每一層都會快取,因此 OS 映像和 Maven 映像層會重複使用快取。 如果組態檔、原始程式碼檔案或 Web 目錄更新,則會重建變更之後的層次。 如果在編譯期間順利完成組建,就會在目標目錄下產生名為AirlinesReservationSample-0.0.1-SNAPSHOT.war的成品。 此成品會複製到最後階段環境以供使用。

在最後階段,Microsoft 所提供的安全映像檔用來從階段 0 和階段 1 分別複製出 Tomcat 和 Java 的建置產物。 名為 app 的使用者擁有專案內使用的所有檔案,而且應用程式也會以 app 使用者身分執行,而不是擁有 root 許可權。 此設定可確保容器映像可以安全地運作,而不需要授與不必要的許可權。 最後,會公開埠號碼 8080,並執行 catalina.sh 腳本以啟動Tomcat。 當您的本機 Docker Desktop 上執行此作業時,您可以透過 URL http://localhost:8080/AirlinesReservationSample存取它。

在專案的根資料夾中, containerize-and-deploy-Java-app-to-Azure/Project/Airlines,使用下列命令來建立名為 Dockerfile 的檔案:

vi Dockerfile

將下列內容新增至您的 Dockerfile,然後儲存並結束。 若要儲存並結束,請按 ESC,輸入 :wq!,然後按 Enter

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

備註

您可以選擇性地在專案的根目錄中使用 Dockerfile_Solution 檔案,其中包含您需要的內容。

Dockerfile 分成三個階段,如下表所述:

  • Tomcat 安裝階段:

    Docker 命令 說明
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat 將基底映像檔設定為在 Ubuntu 上的 Microsoft 組建的 OpenJDK 17,並將此階段命名為 tomcat。 這是安裝 Tomcat 的位置。
    ENV ENV CATALINA_HOME=/usr/local/tomcat 會設定 Tomcat 安裝目錄的環境變數。
    ENV ENV TOMCAT_VERSION=10.1.33 會設定要安裝的 Tomcat 版本。 這應該視需要更新為最新版本。
    RUN 命令 RUN 會更新套件清單、安裝 curl、下載指定的 Tomcat 版本、擷取、將它移至指定的目錄,以及清除不必要的檔案和套件。 這可確保映像保持輕量型。
  • 使用Java 17編譯的建置階段:

    Docker 命令 說明
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS build 將基底映像檔設定為在 Ubuntu 上的 Microsoft 組建的 OpenJDK 17,並將此階段命名為 build。 這個階段用於編譯 Java 應用程式。
    WORKDIR WORKDIR /build 會將容器內的工作目錄設定為 /build,其中會複製和編譯原始程式碼。
    RUN RUN apt-get update && apt-get install -y maven && mvn --version 會安裝 Maven,這是用於 Java 專案的組建自動化工具,並驗證其安裝。
    COPY COPY pom.xml . 會將 Maven 組態檔複製到工作目錄中。 此檔案對於建置專案而言很重要。
    COPY COPY src ./src 將原始碼目錄複製到容器中。 這是 Java 應用程式程式代碼所在的位置。
    COPY COPY web ./web 將 Web 資源目錄複製到容器中。 這包括組建所需的 Web 應用程式資源。
    RUN RUN mvn clean package 會執行 Maven 建置程式,它會編譯 Java 應用程式,並將其封裝成 WAR 檔案。
  • 套件最終階段:

    Docker 命令 說明
    FROM FROM mcr.microsoft.com/openjdk/jdk:17-mariner 會將基礎映像設定為 CBL-Mariner 上的 Microsoft OpenJDK 17 建置,用於應用程式的最終部署。
    ENV ENV CATALINA_HOME=/usr/local/tomcat 會設定 Tomcat 安裝目錄的環境變數,類似於安裝階段。
    ENV ENV PATH=$CATALINA_HOME/bin:$PATH 將 Tomcat bin 目錄新增至系統 PATH,以便輕鬆地執行 Tomcat 命令。
    USER USER app 指定 Tomcat 進程執行所在的使用者,藉由不以根使用者身分執行來增強安全性。
    COPY COPY --chown=app:app --from=tomcat ${CATALINA_HOME} ${CATALINA_HOME}tomcat 階段複製Tomcat安裝,並將擁有權設定為 app 使用者。
    COPY COPY --chown=app:app tomcat-users.xml ${CATALINA_HOME}/conf 將 Tomcat 使用者組態檔複製到容器,並將擁有權設定為 app 使用者。
    COPY COPY --chown=app:app --from=build /build/target/*.war ${CATALINA_HOME}/webapps/AirlinesReservationSample.war 將編譯的 WAR 檔案從 build 階段複製到 Tomcat webapps 目錄,並將擁有權設定為 app 使用者。
    EXPOSE EXPOSE 8080 會公開埠 8080,這是 Tomcat 的預設埠,允許外部存取應用程式。
    CMD CMD ["catalina.sh", "run"] 會指定要在執行容器時啟動 Tomcat 的命令。

如需 Dockerfile 建構的詳細資訊,請參閱 Dockerfile 參考