Java アプリをコンテナー化する
このユニットでは、Java アプリケーションをコンテナー化します。
前述のように、コンテナーは通常のシステム プロセスとしてホスト オペレーティング システム、カーネル、ハードウェアの上で直接実行されます。 コンテナーの必要なシステム リソースが少なくなり、フットプリントが小さくなり、オーバーヘッドが少なくなり、アプリケーションの起動時間が短縮されます。 これらの利点は、オンデマンドでスケーリングするための優れたユース ケースです。
Windows コンテナーと Linux コンテナーがあります。 このモジュールでは、広く使用されている Docker ランタイムを使用して Linux コンテナー イメージを構築します。 次に、Linux コンテナー イメージをローカル コンピューターのホスト オペレーティング システムにデプロイします。 最後に、Linux コンテナー イメージを Azure Kubernetes Service にデプロイします。
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 アプリケーションを複製する
最初に、Flight Booking System for Airline Reservations リポジトリを複製し、Airlines Web アプリケーション プロジェクト フォルダーに移動します。
注
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 は、次の出力に示すように、フライト予約システム for Airline Reservations Web Application Archive artifact 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 は、ユーザーがコマンド ラインで実行してコンテナー イメージをアセンブルするすべてのコマンドを含むテキスト ドキュメントです。 各イメージは、効率のためにキャッシュできるレイヤーです。 レイヤーは互いに重なって構築されます。
たとえば、フライト予約システム for Airline Reservations は、アプリケーション サーバーにデプロイして実行する必要があります。 アプリケーション サーバーは AirlinesReservationSample-0.0.1-SNAPSHOT.war 内にパッケージ化されていません。
AirlinesReservationSample-0.0.1-SNAPSHOT.war を実行し、HTTP 要求をリッスンして処理し、ユーザー セッションを管理し、フライト予約を容易にするために必要な外部依存関係です。 従来のコンテナー化されていないデプロイを使用した場合、運用エンジニアは 、AirlinesReservationSample-0.0.1-SNAPSHOT.war をデプロイする前に、物理サーバーまたは仮想マシンにアプリケーション サーバーをインストールして構成します。 これらの操作エンジニアは、マシンで使用されている JDK (WAR ファイルのコンパイルに使用 mvn clean package
) が、実際にアプリケーション サーバーで使用されているのと同じ JRE に対応していることを確認する必要があります。 これらの依存関係の管理は困難で時間がかかります。
Dockerfile を使用すると、Docker コンテナー ランタイムにデプロイするために必要なすべての依存関係がフライト予約システムに確実に含まれるようにするために必要な手順を重ねて、この目標を自動的に達成するために必要な手順またはレイヤーを記述できます。 このソリューションは、計画外の間隔でオンデマンド スケールを使用する場合に魅力的です。 各レイヤーは Docker キャッシュを使用します。Docker キャッシュには、各説明マイルストーンでのコンテナー イメージの状態が含まれており、コンピューティング時間と再利用が最適化されています。 レイヤーが変更されていない場合は、キャッシュされたレイヤーが使用されます。 キャッシュされたレイヤーの一般的なユース ケースは、Java ランタイム、アプリケーション サーバー、およびフライト予約システム for Airline Reservations Web アプリケーションのその他の依存関係です。 以前にキャッシュされたレイヤーでバージョンが変更された場合、新しいキャッシュされたエントリが作成されます。
次の図は、コンテナー イメージのレイヤーを示しています。 Dockerfile 内のコマンドが実行されると、レイヤーが作成されます。 最上位レイヤーは、航空予約 Web アプリケーション レイヤーの読み取り/書き込みフライト予約システムです。 そのレイヤーは、前の読み取り専用レイヤーの上に構築されています。
Docker にはマルチステージ ビルドという概念があります。これは、キャッシュが向上し、セキュリティフットプリントが小さい小さい小さなコンテナー イメージを作成できる機能であり、時間の経過と共に Dockerfile の最適化とメンテナンスを増やすことができます。 たとえば、アプリケーションをコンパイルおよびビルドするためのコンテナー ビルド ステージと、アプリケーションを実行するためのステージを分離できます。 この機能を使用すると、ビルド中に生成された成果物のみを運用コンテナー イメージにコピーできるため、フットプリントが削減されます。 コンテナー イメージはキャッシュされるため、変更がない場合は、キャッシュされたイメージを再利用できるため、ネットワークからダウンロードするコストと時間が削減されます。
運用環境で公開されるサービスは、セキュリティのために慎重に管理する必要があります。 そのため、運用環境では、セキュリティで保護されたコンテナー イメージを使用して操作します。 この例では、Microsoft が提供する CBL-Mariner
イメージを使用します。
CBL-Mariner Linux は軽量オペレーティング システムであり、クラウド環境に必要なパッケージのみを含みます。 アプリケーションの要件に合わせてカスタム パッケージとツールを使用してカスタマイズできます。 CBL-Mariner は Azure 検証テストを受け、Azure エージェントと互換性があります。 Microsoft は、Azure サービスから IoT インフラストラクチャへの電源供給まで、さまざまなユース ケースに対応する CBL-Mariner を構築およびテストします。 これは、Microsoft クラウド サービスおよび関連製品で使用するために内部で推奨される Linux ディストリビューションです。
注
Microsoft では、 Ubuntu
、 CBL-Mariner
、 distroless
イメージなど、OpenJDK にバンドルされたコンテナー イメージを提供しています。
distroless
イメージのイメージ サイズは最小ですが、Tomcat を実行するのは困難です。 軽量な設計を実現するために、 distroless
イメージはシェルを含む多くのコマンドとツールを削除します。つまり、 catalina.sh を呼び出して Tomcat を起動することはできません。
distroless
イメージは、Spring Boot や Quarkus で使用される実行可能 JAR を実行するのに適しています。
次の例では、ビルド ステージと最終ステージの両方で、同じバージョンの Microsoft Build of OpenJDK が使用されています。 この方法により、サービス デプロイ Tomcat が使用するのと同じバージョンの JDK を使用してソース コードをビルドできます。これにより、バージョンの不一致による予期しない動作を回避できます。
次の図は、Dockerfile で指定されたコマンドに基づいて、マルチステージ ビルドと各ステージで発生している内容を示しています。
ステージ 0 では、Tomcat がダウンロードされ、Ubuntu イメージ上の環境変数で指定されたディレクトリに抽出されます。
TOMCAT_VERSION
変数は、ダウンロードする Tomcat のバージョンを指定します。 Tomcat の新しいバージョンがリリースされた場合は、バージョン番号が変更されたときにのみ新しいイメージがフェッチされるため、バージョン番号を更新する必要があります。 それ以外の場合は、キャッシュされたイメージが使用されます。 ダウンロードした Tomcat は、使用するために最終ステージ環境にコピーされます。
ステージ 1 では、Maven が Ubuntu イメージにインストールされ、Maven プロジェクトをビルドする前に作成されたソース コードと構成ファイルがコピーされます。 各レイヤーはキャッシュされるため、OS イメージと Maven イメージ レイヤーはキャッシュを再利用します。 構成ファイル、ソース コード ファイル、または Web ディレクトリが更新されると、変更以降のレイヤーが再構築されます。 コンパイル中にエラーなしでビルドが正常に完了すると、 AirlinesReservationSample-0.0.1-SNAPSHOT.war という名前のアーティファクトが ターゲット ディレクトリに生成されます。 この成果物は、使用するために最終ステージ環境にコピーされます。
最後のステージでは、Microsoft によって提供されるセキュリティで保護された CBL-Mariner
イメージを使用して、ステージ 0 とステージ 1 から Tomcat と Java のビルド成果物をそれぞれコピーします。
app
という名前のユーザーは、プロジェクト内で使用されるすべてのファイルを所有しており、アプリケーションはroot
特権を持つ代わりにapp
ユーザーとしても実行されます。 このセットアップにより、不要なアクセス許可を付与することなく、コンテナー イメージを安全に操作できるようになります。 最後に、ポート番号 8080 が公開され、tomcat を起動するために catalina.sh スクリプトが実行されます。 ローカルの 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 は、次の表に示す 3 つのステージに分かれています。
Tomcat のインストール ステージ:
Docker コマンド 説明 FROM
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu AS tomcat
は、Ubuntu 上の OpenJDK 17 の Microsoft Build に基本イメージを設定し、このステージに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 上の OpenJDK 17 の Microsoft Build に基本イメージを設定し、このステージにbuild
という名前を付けます。 このステージは、Java アプリケーションのコンパイルに使用されます。WORKDIR
WORKDIR /build
では、コンテナー内の作業ディレクトリが/build
に設定され、ソース コードがコピーされてコンパイルされます。RUN
RUN apt-get update && apt-get install -y maven && mvn --version
は、Java プロジェクトに使用されるビルド自動化ツールである Maven をインストールし、そのインストールを検証します。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 Build of 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
は Tomcat の既定のポートであるポート 8080 を公開し、アプリケーションへの外部アクセスを許可します。CMD
CMD ["catalina.sh", "run"]
は、コンテナーの実行時に Tomcat を起動するコマンドを指定します。
Dockerfile の構築の詳細については、 Dockerfile リファレンスを参照してください。