Buildpacks を使用した Google App Engine Java アプリから Cloud Run への移行

1. 概要

この一連の Codelab(セルフペース型のハンズオン チュートリアル)は、Google App Engine(Standard)の Java デベロッパーが一連の移行手順をご案内し、アプリをモダナイズできるようにすることを目的としています。この手順に従うことで、アプリのポータビリティを高め、Cloud Run、App Engine のコンテナ ホスティング シスターサービス、その他のコンテナ ホスティング サービス向けにコンテナ化できます。

このチュートリアルでは、Buildpack を使用して App Engine アプリをコンテナ化し、Cloud Run フルマネージド サービスにデプロイする方法について説明します。Buildpack は CNCF プロジェクトであり、任意のクラウドで実行できる高度なポータビリティのアプリをソースコードから直接作成できます。

App Engine から Cloud Run に移行するために必要な手順に加えて、Java 8 App Engine アプリを Java 17 にアップグレードする方法についても説明します。

移行対象のアプリケーションで App Engine の以前のバンドル サービスやその他の App Engine 固有の機能を多用している場合は、この Codelab よりも Java 11/17 向けの App Engine バンドル サービスにアクセスするガイドの方が適している可能性があります。

GCP コンソールの

  • Cloud Shell を使用する
  • Cloud Run、Artifact Registry、Cloud Build API を有効にする
  • Cloud Build で Buildpack を使用してアプリをコンテナ化する
  • コンテナ イメージを Cloud Run にデプロイする

必要なもの

アンケート

このチュートリアルをどのように使用されますか?

通読するのみ 通読し、演習を行う

Java のご利用経験についてお答えください。

初心者 中級者 上級者

Google Cloud サービスの使用経験はどの程度ありますか?

初心者 中級者 上級者

2. 背景情報

App Engine や Cloud Functions などの PaaS システムは、システム管理者と DevOps がソリューションの構築に集中できるようにするなど、チームとアプリケーションに多くの利便性を提供します。サーバーレスなプラットフォームにより、アプリは必要に応じて自動スケーリングでき、従量課金制でゼロにスケールダウンして費用を管理できるほか、さまざまな一般的な開発言語を使用できます。

しかし、コンテナの柔軟性も魅力的です。コンテナでは任意の言語、ライブラリ、バイナリを選択できるため、サーバーレスの利便性とコンテナの柔軟性の両方を活用できます。これが Google Cloud Run の目的です。

Cloud Run の使用方法は、この Codelab の範囲外です。詳しくは、Cloud Run のドキュメントをご覧ください。このチュートリアルでは、Cloud Run(または他のコンテナ ホスト型サービス)用に App Engine アプリをコンテナ化する方法を学習します。先に進む前に、いくつか知っておくべきことがあります。主に、ユーザー エクスペリエンスが若干異なる点です。

この Codelab では、コンテナの構築とデプロイ方法について学びます。Buildpack を使用してアプリをコンテナ化する方法、App Engine 構成から移行する方法、Cloud Build のビルドステップを定義する方法を学習します。これにより、App Engine 固有の特定の機能が廃止されます。このパスに沿いたくない場合は、アプリを App Engine に保持しながら、Java 11/17 ランタイムにアップグレードすることもできます。

3. セットアップ/事前作業

1. プロジェクトをセットアップする

このチュートリアルでは、新しいプロジェクトappengine-java-migration-samples リポジトリのサンプルアプリを使用します。プロジェクトに有効な請求先アカウントがあることを確認します。

既存の App Engine アプリを Cloud Run に移行する場合は、そのアプリを使用して手順を進めることができます。

次のコマンドを実行して、プロジェクトに必要な API を有効にします。

gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com

2. ベースライン サンプルアプリを入手する

自分のマシンまたは Cloud Shell でサンプルアプリのクローンを作成し、baseline フォルダに移動します。

このサンプルは、App Engine へのデプロイを想定した Java 8 のサーブレット ベースの Datastore アプリです。App Engine へのデプロイ用にこのアプリを準備する方法については、README の手順に沿って行ってください。

3. (省略可)ベースライン アプリをデプロイする

以下の手順は、Cloud Run に移行する前にアプリが App Engine で動作することを確認する場合にのみ必要です。

README.md の手順を参照してください。

  1. gcloud CLI をインストールする/gcloud CLI を再確認する
  2. gcloud init を使用してプロジェクトの gcloud CLI を初期化する
  3. gcloud app create を使用して App Engine プロジェクトを作成する
  4. サンプルアプリを App Engine にデプロイする
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. アプリが App Engine で問題なく実行されることを確認する

4. Artifact Registry リポジトリを作成する

アプリをコンテナ化したら、イメージを push して保存する場所が必要です。Google Cloud でこの処理を行うには、Artifact Registry を使用することをおすすめします。

次のように、gcloud を使用して migration という名前のリポジトリを作成します。

gcloud artifacts repositories create migration --repository-format=docker \
--description="Docker repository for the migrated app" \
--location="northamerica-northeast1"

このリポジトリは docker 形式タイプを使用しますが、利用可能な複数のリポジトリ タイプがあります。

この時点で、ベースラインの App Engine アプリが作成され、Google Cloud プロジェクトは Cloud Run に移行する準備が整っています。

4. アプリケーション ファイルを変更する

アプリで App Engine の以前のバンドル サービス、構成、または App Engine 専用の他の機能を頻繁に使用している場合は、新しいランタイムにアップグレードする際に、引き続きこれらのサービスにアクセスすることをおすすめします。この Codelab では、スタンドアロン サービスをすでに使用しているアプリ、またはそうするようにリファクタリングできるアプリの移行パスを示します。

1. Java 17 へのアップグレード

アプリが Java 8 上にある場合は、セキュリティ アップデートに対応し、新しい言語機能を利用できるようにするため、11 や 17 などの新しい LTS 候補にアップグレードすることを検討してください。

まず、pom.xml のプロパティを更新して以下を含めます。

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>

これにより、プロジェクト バージョンが 17 に設定され、Java 17 言語機能にアクセスし、コンパイルされたクラスを Java 17 JVM と互換性を持たせたいことをコンパイラ プラグインに通知します。

2. ウェブサーバーを含める

App Engine と Cloud Run との間には、移行する際に考慮すべき相違点が数多くあります。1 つ異なる点として、App Engine の Java 8 ランタイムでは、ホストするアプリ用に Jetty サーバーが提供され、管理されますが、Cloud Run はそうではありません。Spring Boot を使用して、ウェブサーバーとサーブレット コンテナを提供します。

次の依存関係を追加します。

<dependencies>
<!-- ... -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <version>2.6.6</version>
       <exclusions>
           <!-- Exclude the Tomcat dependency -->
           <exclusion>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-tomcat</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <!-- Use Jetty instead -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jetty</artifactId>
       <version>2.6.6</version>
   </dependency>
<!-- ... -->
</dependencies>

Spring Boot はデフォルトで Tomcat サーバーを埋め込みますが、このサンプルでは、移行後のデフォルトの動作の違いを最小限に抑えるために、そのアーティファクトを除外し、Jetty を使用します。

3. Spring Boot の設定

Spring Boot では、変更なしでサーブレットを再利用できますが、検出できるようにするには、いくつかの構成が必要です。

com.example.appengine パッケージに次の MigratedServletApplication.java クラスを作成します。

package com.example.appengine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
@EnableAutoConfiguration
public class MigratedServletApplication {
    public static void main(String[] args) {
        SpringApplication.run(MigratedServletApplication.class, args);
    }
}

これには @ServletComponentScan アノテーションが含まれています。これは、(デフォルトでは現在のパッケージ内)の @WebServlets を検索し、想定どおりに使用できるようにします。

4. ビルド構成

次に、構成を削除して、アプリケーションを WAR としてパッケージ化します。特に Maven をビルドツールとして使用するプロジェクトでは、jar パッケージ化がデフォルトの動作であるため、多くの構成は必要ありません。

pom.xml ファイルの packaging タグを削除します。

<packaging>war</packaging>

次に、spring-boot-maven-plugin を追加します。

<plugins>
<!-- ... -->
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.6.6</version>
  </plugin>
<!-- ... -->
</plugins>

5. App Engine の構成、サービス、依存関係から移行する

この Codelab の冒頭で説明したように、Cloud Run と App Engine は異なるユーザー エクスペリエンスを提供するように設計されています。App Engine が標準で提供する特定の機能(Cron サービスや タスクキュー サービスなど)は、手動で再作成する必要があります。これらの機能については、後続のモジュールで詳しく説明します。

このサンプルアプリでは以前のバンドル サービスを使用していませんが、アプリで以前のバンドル サービスを使用している場合は、次のガイドをご覧ください。

今後は Cloud Run にデプロイするため、appengine-maven-plugin は削除できます。

<plugin>
 <groupId>com.google.cloud.tools</groupId>
 <artifactId>appengine-maven-plugin</artifactId>
 <version>2.4.1</version>
 <configuration>
   <!-- can be set w/ -DprojectId=myProjectId on command line -->
   <projectId>${app.projectId}</projectId>
   <!-- set the GAE version or use "GCLOUD_CONFIG" for an autogenerated GAE version -->
   <version>GCLOUD_CONFIG</version>
 </configuration>
</plugin>

5. アプリケーションのコンテナ化とデプロイ

この時点で、ソースコードからアプリを Cloud Run に直接デプロイする準備が整いました。これは、Cloud Build をバックグラウンドで使用して、手動でデプロイする手間を省く優れた方法です。この機能を使用するには、次の権限の少なくとも 1 つを持つアカウントが必要で、環境の設定手順に沿って設定されているか、Cloud Shell を使用する必要があります。

前提条件が満たされている場合は、ソース ディレクトリから次のコマンドを実行します。

gcloud run deploy SERVICE --source .

deploy コマンドを実行すると、次のようなプロンプトが表示されます。

  • ソースコードの場所を指定
  • サービス名の指定
  • Cloud Run API を有効にする
  • リージョンの選択

プロンプトに応答すると、ビルドとデプロイのプロセスが開始されます。このプロセスで、Cloud Build は次の処理を行います。

  • ソースを ZIP 圧縮して Cloud Storage バケットに保存します。
  • バックグラウンドで Cloud Native Computing Foundation Buildpack を使用してイメージをビルドします。
  • 結果のコンテナ イメージを保存するレジストリを作成します(まだ存在しない場合)。
  • アプリをホストする Cloud Run サービスを作成します(まだ存在しない場合)。

ビルドとデプロイが完了すると、新しいリビジョンが公開され、トラフィックの 100% が処理されていることを示すメッセージが表示されます。

6. 概要/クリーンアップ

これでアプリのアップグレード、コンテナ化、移行が完了しました。これでチュートリアルは終了です。

次のステップでは、Cloud Build でデプロイできるようになった CI/CD とソフトウェア サプライ チェーンのセキュリティ機能について詳しく学びます。

省略可: サービスをクリーンアップまたは無効にする

このチュートリアル中にサンプルアプリを App Engine にデプロイした場合は、課金が発生しないようにアプリを無効にしてください。次の Codelab に進む準備ができた時点で、再度有効にできます。App Engine アプリを無効にしている間は、トラフィックが発生しないため料金は発生しませんが、無料割り当てを超えると、Datastore の使用量に対して課金される場合があります。上限を超えないよう削除してください。

また、移行を続けず、完全に削除したい場合は、サービスを削除するか、プロジェクトを完全にシャットダウンしてください。

7. 参考情報

App Engine 移行モジュールの Codelab に関する問題 / フィードバック

この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:

移行リソース

オンライン リソース

このチュートリアルに関連する可能性のあるオンライン リソースは次のとおりです。

App Engine

Cloud のその他の情報

動画

ライセンス

この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。