Tomcat アプリケーションを Azure App Service 上の Tomcat に 移行する

このガイドでは、既存の Tomcat アプリケーションを移行し、Tomcat 9.0 を使用して Azure App Service で実行する場合に知っておくべきことについて説明します。

移行前

移行を確実に成功させるには、開始する前に、次のセクションで説明する評価とインベントリの手順を完了します。

以下の移行前の要件のいずれかを満たすことができない場合は、次の関連する移行ガイドを参照してください。

サポートされているプラットフォームに切り替える

App Service では、特定のバージョンの Java で特定のバージョンの Tomcat が提供されます。 互換性を確保するために、残りの手順を続行する前に、現在の環境でサポートされているいずれかのバージョンの Tomcat および Java にアプリケーションを移行してください。 結果として得られた構成は、十分にテストしてください。 このようなテストでは、Linux ディストリビューションの安定した最新リリースを使用します。

注意

現在のサーバーがサポートされていない JDK (Oracle JDK や IBM OpenJ9 など) で実行されている場合、この検証が特に重要です。

現在の Java バージョンを取得するには、実稼働サーバーにサインインし、次のコマンドを実行します。

java -version

Azure App Service では、Java 8 のバイナリは Eclipse Temurin から提供されています。 Java 11、17、および今後のすべての LTS リリースの Java では、App Service は Microsoft Build of OpenJDK を提供します。 これらのバイナリは、次のサイトで無料でダウンロードできます。

現在の Tomcat バージョンを取得するには、実稼働サーバーにサインインし、次のコマンドを実行します。

${CATALINA_HOME}/bin/version.sh

Azure App Service によって使用されている現在のバージョンを取得するには、Azure App Service で使用するバージョンに応じて、Tomcat 9 をダウンロードします。

外部リソースをインベントリする

データ ソース、JMS メッセージ ブローカー、およびその他の外部リソースは、JNDI (Java Naming and Directory Interface) を介して挿入されます。 こうしたリソースの一部では、移行または再構成が必要な場合があります。

アプリケーション内

META-INF/context.xml ファイルを調べます。 <Context> 要素内の <Resource> 要素を探します。

アプリケーション サーバー上

$CATALINA_BASE/conf/context.xml および $CATALINA_BASE/conf/server.xml ファイルと、$CATALINA_BASE/conf/[engine-name]/[host-name] ディレクトリにある .xmlファイルを調べます。

context.xmlファイルでは、JNDI リソースは、最上位の <Context> 要素内の <Resource> 要素で記述されます。

server.xml ファイルでは、JNDI リソースは <GlobalNamingResources> 要素内の <Resource> 要素で記述されます。

データソース

データソースは、type 属性が javax.sql.DataSource に設定されている JNDI リソースです。 データソースごとに、次の情報を文書にまとめます。

  • データソース名
  • 接続プールの構成
  • JDBC ドライバーの JAR ファイルの場所

詳細については、Tomcat のドキュメントの「JNDI Datasource How-To」を参照してください。

その他のすべての外部リソース

このガイドでは、考えられるすべての外部依存関係を記載することはできません。 アプリケーションの外部依存関係がすべて満たされるよう確認するのは、担当チームの責任です。

シークレットをインベントリする

パスワードとセキュリティで保護された文字列

すべてのシークレット文字列とパスワードについて、運用サーバー上のすべてのプロパティと構成ファイルを確認します。 $CATALINA_BASE/conf にある server.xmlcontext.xml を必ず確認してください。 また、アプリケーション内にパスワードや資格情報を含むファイルが存在する場合もあります。 これらには、META-INF/context.xmlや、Spring Boot アプリケーションの場合は application.properties または application.yml ファイルなどがあります。

証明書をインベントリする

パブリック SSL エンドポイント、またはバックエンド データベースやその他のシステムとの通信に使用されるすべての証明書を文書化します。 次のコマンドを実行して、運用サーバー上のすべての証明書を表示できます。

keytool -list -v -keystore <path to keystore>

ファイル システムが使用されているかどうかとその使用方法を判断する

アプリケーション サーバーでファイル システムを使用する場合は、再構成や、まれにアーキテクチャの変更が必要になります。 次のシナリオの一部または全部を確認できます。

読み取り専用の静的コンテンツ

現在、アプリケーションで静的コンテンツを提供している場合は、そのための別の場所が必要になります。 静的コンテンツを Azure Blob Storage に移動し、グローバルな高速ダウンロードのために Azure CDN を追加することを検討できます。 詳細については、「Azure Storage での静的 Web サイト ホスティング」と「クイック スタート:Azure ストレージ アカウントと Azure CDN との統合」を参照してください。

動的に公開される静的コンテンツ

アプリケーションによってアップロードまたは生成されるが、作成後に変更できない静的コンテンツをアプリケーションで許可する場合は、前述のように Azure Blob Storage と Azure CDN を使用し、Azure Function でアップロードと CDN の更新を処理します。 「Azure Functions を使用した静的コンテンツのアップロードと CDN の事前読み込み」で、ご利用いただけるサンプルの実装を提供しています。

動的または内部のコンテンツ

アプリケーションで頻繁に書き込みおよび読み取りされるファイル (一時データ ファイルなど) や、アプリケーションでのみ表示できる静的ファイルの場合、Azure Storage を App Service ファイル システムにマウントできます。 詳細については、「Linux 上の App Service 内の Azure Storage からコンテンツを提供する」を参照してください。

ID セッションの永続化メカニズム

使用されているセッション永続化マネージャーを特定するには、アプリケーション内の context.xml ファイルおよび Tomcat の構成を調べます。 <Manager> 要素を探して、className 属性の値を確認します。

Tomcat の組み込みの PersistentManager の実装 (StandardManagerFileStore など) は、App Service のような分散型のスケーリングされたプラットフォームで使用するように設計されていません。 App Service では、複数のインスタンス間で負荷が分散され、任意の時点で任意のインスタンスが透過的に再起動される可能性があるため、変更可能な状態をファイル システムに保持することは推奨されません。

セッションの永続化が必要な場合は、代替の PersistentManager の実装を使用する必要があります。これは、Redis Cache を使用して VMware Tanzu Session Manager などの外部データ ストアへの書き込みを行います。 詳細については、「Tomcat を使用してセッション キャッシュとして Redis を使用する」を参照してください。

実稼働サーバーで実行されているすべての外部プロセスとデーモンを特定する

デーモンの監視など、アプリケーション サーバーの外部で実行されているプロセスがある場合は、それらを削除するか、別の場所に移行する必要があります。

特殊なケース

運用環境のシナリオによっては、追加の変更が必要な場合や、追加の制限が課される場合があります。 そのようなシナリオはめったに発生しませんが、それらがアプリケーションに適用されないこと、または正しく解決されることを確認することが重要です。

スケジュールされたジョブにアプリケーションが依存しているかどうかを判断する

スケジュールされたジョブ (Quartz Scheduler タスクや cron ジョブなど) は、App Service では使用できません。 App Service では、スケジュールされたタスクを含むアプリケーションの内部でのデプロイが妨げられることはありません。 ただし、アプリケーションをスケールアウトすると、同じスケジュールされたジョブが、スケジュールされた期間に複数回実行されることがあります。 このような場合、意図しない結果になることがあります。

アプリケーション サーバーの内部または外部で、すべてのスケジュールされたジョブをインベントリします。

アプリケーションに OS 固有のコードが含まれているかどうかを判断する

アプリケーションにホスト OS に依存するコードが含まれている場合は、それをリファクタリングしてそれらの依存関係を削除する必要があります。 たとえば、ファイル システムのパスで / または \ を使用している場合、File.Separator または Paths.get に置き換えることが必要になる可能性があります。

Tomcat クラスタリングが使用されているかどうかを判断する

Tomcat クラスタリング は Azure App Service ではサポートされていません。 代わりに、Tomcat 固有の機能を使用せずに Azure App Service によってスケーリングと負荷分散を構成して管理できます。 セッション状態を別の場所に保持して、レプリカの間で使用できるようにすることができます。 詳細については、「ID セッションの永続化メカニズム」を参照してください。

アプリケーションでクラスタリングが使用されているかどうかを判断するには、server.xml ファイルの <Host> または <Engine> 要素内で <Cluster> 要素を探します。

非 HTTP コネクタが使用されているかどうかを判断する

App Service では、1 つの HTTP コネクタのみがサポートされます。 アプリケーションで AJP コネクタなどの追加のコネクタが必要な場合は、App Service を使用しないでください。

アプリケーションによって使用されている HTTP コネクタを特定するには、Tomcat 構成の server.xml ファイル内で <Connector> 要素を探します。

MemoryRealm が使用されているかどうかを判断する

MemoryRealm には、永続化された XML ファイルが必要です。 Azure AppService では、このファイルを /home ディレクトリかそのいずれかのサブディレクトリ、またはマウントされたストレージにアップロードする必要があります。 その後、pathName パラメーターを適宜変更する必要があります。

MemoryRealm が現在使用されているかどうかを確認するには、server.xml および context.xml ファイルを調べ、className 属性が org.apache.catalina.realm.MemoryRealm に設定されている <Realm> 要素を検索します。

SSL セッションの追跡が使用されているかどうかを判断する

App Service では、Tomcat ランタイムの外部でセッションのオフロードが実行されるため、SSL セッションの追跡は使用できません。 代わりに別のセッションの追跡モード (COOKIE または URL) を使用してください。 SSL セッションの追跡が必要な場合は、App Service を使用しないでください。

AccessLogValve が使用されているかどうかを判断する

AccessLogValve を使用している場合は、directory パラメーターを /home/LogFiles またはそのいずれかのサブディレクトリに設定する必要があります。

移行

構成のパラメーター化

多くの場合、移行前の手順で、server.xml および context.xml ファイル内の一部のシークレットや外部依存関係 (データソースなど) を識別します。 識別した各項目について、ユーザー名、パスワード、接続文字列、または URL を環境変数に置き換えます。

たとえば、context.xml ファイルに次の要素が含まれているとします。

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="jdbc:postgresql://postgresdb.contoso.com/wickedsecret?ssl=true"
    driverClassName="org.postgresql.Driver"
    username="postgres"
    password="t00secure2gue$$"
/>

この場合は、次の例に示されているように変更できます。

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="${postgresdb.connectionString}"
    driverClassName="org.postgresql.Driver"
    username="${postgresdb.username}"
    password="${postgresdb.password}"
/>

App Service プランをプロビジョニングする

App Service の価格」の利用可能なサービス プランのリストから、仕様が現在の実稼働のハードウェアの仕様を満たしているか超えているプランを選択します。

注意

ステージング/カナリア デプロイを実行する場合、またはデプロイ スロットを使用する場合は、App Service プランにその追加容量が含まれている必要があります。 Java アプリケーションでは、Premium 以上のプランを使用することをお勧めします。 詳細については、「Azure App Service でステージング環境を設定する」を参照してください。

その後に、App Service プランを作成します。 詳細については、「Azure で App Service プランを管理する」を参照してください。

Web アプリを作成してデプロイする

App Service プランでは、Tomcat サーバーにデプロイされている WAR ファイルごとに (ランタイム スタックとして Tomcat のバージョンを選択して) Web アプリを作成する必要があります。

注意

1 つの Web アプリに複数の WAR ファイルをデプロイすることは可能ですが、非常に望ましくない操作です。 1 つの Web アプリに複数の WAR ファイルをデプロイすると、各アプリケーションを独自の使用要件に従ってスケーリングできなくなります。 さらに、後続の配置パイプラインの複雑さも増大します。 1 つの URL で複数のアプリケーションを使用できるようにする必要がある場合は、Azure Application Gateway などのルーティング ソリューションの使用を検討してください。

Maven アプリケーション

アプリケーションが Maven POM ファイルから作成されている場合は、Maven 用の Webapp プラグインを使用して Web アプリを作成し、アプリケーションをデプロイします。

Maven 以外のアプリケーション

Maven プラグインを使用できない場合は、次のような他のメカニズムを使用して Web アプリをプロビジョニングする必要があります。

Web アプリが作成されたら、利用可能なデプロイ メカニズムのいずれかを使用してアプリケーションをデプロイします。

JVM ランタイムオプションを移行する

アプリケーションで特定のランタイム オプションが必要な場合は、最適なメカニズムを使用してそれらを指定します

シークレットを取り込む

アプリケーション固有のシークレットを格納するには、アプリケーション設定を使用します。 複数のアプリケーションで同じシークレットを使用する場合、またはきめ細かなアクセス ポリシーと監査機能が必要な場合は、代わりに Azure Key Vault を使用 します。

カスタム ドメインと SSL を構成する

アプリケーションをカスタム ドメインに表示する場合は、Web アプリケーションをそれにマップする必要があります。 詳細については、「チュートリアル: 既存のカスタム DNS 名を Azure App Service にマップする」を参照してください。

その後、そのドメインの SSL 証明書を App Service Web アプリにバインドする必要があります。 詳細については、「Azure App Service で SSL バインディングを使用してカスタム DNS 名をセキュリティで保護する」を参照してください。

バックエンド証明書のインポート

データベースなどのバックエンド システムとの通信用のすべての証明書は、App Service で使用できるようにする必要があります。 詳細については、App Service での SSL 証明書の追加に関する記事をご覧ください。

データソース、ライブラリ、および JNDI リソースを移行する

データ ソースの構成手順については、「Azure App Service 向けの Linux Java アプリを構成する」の「データ ソース」セクションを参照してください。

その他のデータ ソースの手順については、Tomcat のドキュメントで「JNDI Datasource How-To」の次のセクションを参照してください。

追加のサーバー レベル クラスパスの依存関係を、データ ソースの JAR ファイルと同じ手順に従って移行します。

その他の共有サーバー レベルの JDNI リソースを移行します。

注意

webapp ごとに 1 つの WAR という推奨アーキテクチャに従っている場合は、サーバー レベル クラスパス ライブラリと JNDI リソースをアプリケーションに移行することを検討してください。 これにより、コンポーネントのガバナンスと変更管理が大幅に簡素化されます。

残りの構成を移行する

前のセクションを完了すると、カスタマイズ可能なサーバー構成が /home/tomcat/conf に格納されます。

追加の構成 (RealmJASPIC など) をコピーして移行を完了します

スケジュールされたジョブを移行する

スケジュールされたジョブを Azure で実行するには、Azure Functions のタイマー トリガーを使用することを検討してください。 ジョブ コード自体を関数に移行する必要はありません。 この関数では、アプリケーションで URL を呼び出すだけでジョブをトリガーできます。 このようなジョブ実行を動的に呼び出したり、一元的に追跡したりする必要がある場合は、Spring Batch の使用を検討してください。

または、繰り返しトリガーを使用してロジック アプリを作成し、アプリケーションの外部でコードを記述せずに URL を呼び出すこともできます。 詳細については、「概要 - Azure Logic Apps とは」と「Azure Logic Apps で繰り返しトリガーを使用して繰り返しタスクおよびワークフローを作成、スケジュール設定、および実行する」を参照してください。

注意

悪意のある使用を防ぐために、ジョブの呼び出しエンドポイントで資格情報が求められるようにする必要があります。 この場合、トリガー関数が資格情報を提供する必要があります。

再起動とスモーク テスト

最後に、Web アプリを再起動してすべての構成の変更を適用する必要があります。 再起動が完了したら、アプリケーションが正しく実行されていることを確認します。

移行後

アプリケーションを Azure App Service に移行したので、期待どおりに動作することを確認する必要があります。 これを完了したら、アプリケーションをよりクラウド ネイティブにするための推奨事項がいくつかあります。

Recommendations