Java ランタイム環境

Java ランタイムは、ウェブサービスのコードとその依存関係をインストールしてサービスを実行する役割を果たすソフトウェア スタックです。

app.yaml ファイルで、App Engine スタンダード環境用の Java ランタイムを宣言します。次に例を示します。

runtime: javaVERSION

ここで、VERSION は、Java MAJOR のバージョン番号です。たとえば、最新の Java バージョン(Java 21)を使用するには、21 を指定します。

サポートされる他の Java バージョンと、Java バージョンに対応する Ubuntu のバージョンについては、ランタイム サポート スケジュールをご覧ください。

始める前に

  1. Google Cloud CLI の最新バージョンをダウンロードするか、gcloud CLI を最新バージョンに更新します。

    gcloud components update
    
  2. Maven を使用してデプロイするには、App Engine Maven プラグインpom.xml ファイルに追加する必要があります。

    <plugin>
       <groupId>com.google.cloud.tools</groupId>
       <artifactId>appengine-maven-plugin</artifactId>
       <version>2.7.0</version>
    </plugin>

    デプロイには、gcloud app deploy コマンドや App Engine Gradle プラグインの使用などの他のオプションがあります。

  3. アプリケーション フレームワークの手順に従って、実行可能 JAR ファイルのビルドを構成します。

フレームワークの互換性

App Engine Java ランタイムでは、実行可能な JAR ファイルをデプロイできます。ランタイムには、ウェブサービス フレームワークは含まれません。つまり、サーブレット ベースのフレームワークやライブラリの使用に制限されません。ネイティブの依存関係またはネットワーク スタック(Netty ライブラリなど)を使用します。

Google Cloud GitHub リポジトリには、一般的な Java ウェブ フレームワークを使用した hello world サンプルがあります。

これらのフレームワークに限定されるものではありません。お好みのフレームワーク(Grails、Blade、Play、Vaadin、jHipster など)をお試しください。

Maven ソース プロジェクトを Java ランタイムにデプロイする

Maven プロジェクトをソースコードとしてデプロイできます。ビルドしてデプロイするには、Google Cloud の Buildpack を使用します。

Maven プロジェクトをソースコードとしてデプロイするには、プロジェクトの最上位ディレクトリに移動し、次のように入力します。

gcloud app deploy pom.xml

ビルドとデプロイのログがストリーミングされます。詳細なログは Cloud Console の Cloud Build の履歴のセクションで確認できます。

GraalVM 実行可能ファイルの使用

App Engine スタンダード環境用の Java ランタイムは、GraalVM ネイティブ イメージ実行可能ファイルをサポートしています。GraalVM ネイティブ イメージ内に Java アプリをコンパイルしたら、app.yaml ファイルentrypoint 設定を使用して実行可能ファイルを指定できます。

たとえば、ファイル名が myexecutable の実行可能ファイルには、次の app.yaml 構成ファイルがあります。

runtime: java17 # or another supported runtime
entrypoint: ./myexecutable

Google Cloud クライアント ライブラリを使用して、アプリケーションを GraalVM ネイティブ イメージとしてコンパイルできます。詳細については、ネイティブ イメージをコンパイルする方法のドキュメントをご覧ください。

Java のバージョン

Java ランタイムは、app.yaml ファイルで指定されているバージョンの最新の安定版を使用します。App Engine では、パッチリリース バージョンは新しいものに自動で更新されますが、マイナー バージョンの更新は自動的には行われません。

たとえば、アプリケーションが Java 11.0.4 でデプロイされ、その後のマネージドプラットフォームのデプロイ時にバージョン Java 11.0.5 に自動的に更新されることはあっても、Java 12 には自動更新されません。

Java のバージョンをアップグレードする方法については、既存のアプリケーションをアップグレードするをご覧ください。

ランタイムの Open JDK 環境

App Engine は、gVisor によって保護されたコンテナにおいて、最新の Ubuntu Linux ディストリビューションとサポート対象の openjdk-11-jdk(Java 11 ランタイム用)または openjdk-17-jdk(Java 17 ランタイム用)で、Java アプリを実行します。

Java バージョンでサポートされている Ubuntu のバージョンについては、ランタイム サポート スケジュールをご覧ください。

App Engine ではベースイメージが維持され、OpenJDK 11 パッケージおよび OpenJDK 17 パッケージが更新されます。その際、アプリを再デプロイする必要はありません。

デプロイされたアプリは、ランタイムの /workspace ディレクトリにあります。/srv のシンボリック リンクからもアクセスできます。

App Engine Java のリリース

バージョン 2.x.x 以降のすべてのリリース済みアーティファクトでは、オープンソースのリリース メカニズムを使用します。バージョン 1.9.9xx 以前のリリース済みアーティファクトでは、内部ビルドシステムを使用します。詳細については GitHub リポジトリをご覧ください。

依存関係

依存関係の宣言と管理については、依存関係の指定をご覧ください。

アプリケーションの起動

Spring Boot、Micronaut、Ktor などのフレームワークは、デフォルトで実行可能な uber JAR をビルドします。Maven または Gradle ビルドファイルが実行可能な Uber JAR をビルドする場合、ランタイムは Uber JAR アプリケーションを実行してアプリケーションを起動します。

または、App Engine は app.yaml ファイルのオプションの entrypoint フィールドの内容を使用します。次に例を示します。

runtime: java21 # or another supported runtime
entrypoint: java -Xmx64m -jar YOUR-ARTIFACT.jar

例に示す YOUR-ARTIFACT.jar アプリケーション jar は次の要件を満たす必要があります。

  • ルート ディレクトリ内に app.yaml ファイルとともに存在する。
  • META-INF/MANIFEST.MF メタデータ ファイルに Main-Class エントリが含まれている。
  • 必要に応じて、他の依存 jar への相対パスのリストを格納する Class-Path エントリを含んでいる。これらはアプリケーションとともに自動的にアップロードされます。

アプリで HTTP リクエストを受信するには、PORT 環境変数で指定されたポートをリッスンするウェブサーバーをエントリポイントで起動する必要があります。PORT 環境変数の値は App Engine サービス環境によって動的に設定されます。この値は、app.yaml ファイルの env_variables セクションには設定できません。

カスタム エントリポイントによって、アプリケーション コードと直接の依存関係のみを含む thin JAR ファイルとしてアプリケーションを構築しパッケージ化できます。アプリケーションをデプロイする際は、App Engine プラグインは uber JAR パッケージ全体ではなく、変更されたファイルのみをアップロードします。

PORT 環境変数を必ず使用する

アプリのログファイルにポート 8080 と NGINX に関する警告が表示された場合、アプリのウェブサーバーはデフォルトのポート 8080 でリッスンしています。これにより、App Engine は NGINX レイヤを使用して HTTP レスポンスを圧縮できなくなります。PORT 環境変数(通常は 8081)で指定されたポートで、ウェブサーバーが HTTP リクエストに応答するように構成することをおすすめします。例:

/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.appengine;

import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

public class Main {

  public static void main(String[] args) throws IOException {
    // Create an instance of HttpServer bound to port defined by the 
    // PORT environment variable when present, otherwise on 8080.
    int port = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));
    HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);

    // Set root URI path.
    server.createContext("/", (var t) -> {
      byte[] response = "Hello World!".getBytes();
      t.sendResponseHeaders(200, response.length);
      try (OutputStream os = t.getResponseBody()) {
        os.write(response);
      }
    });

    // Create a second URI path.
    server.createContext("/foo", (var t) -> {
      byte[] response = "Foo!".getBytes();
      t.sendResponseHeaders(200, response.length);
      try (OutputStream os = t.getResponseBody()) {
        os.write(response);
      }
    });

    server.start();
  }
}

以前の Java のバージョンとの互換性

Java 8 とサポートされている Java の最新バージョンの違いについては、Java 8 ランタイムと Java 11+ ランタイムの主な違いをご覧ください。

環境変数

ランタイムは以下の環境変数を設定します。

環境変数 説明
GAE_APPLICATION App Engine アプリケーションの ID。この ID の先頭には「region code~」が付きます。たとえば、ヨーロッパでデプロイされたアプリケーションの場合は「e~」となります。
GAE_DEPLOYMENT_ID 現在のデプロイの ID。
GAE_ENV App Engine の環境。standard に設定します。
GAE_INSTANCE 現在サービスが実行されているインスタンスの ID。
GAE_MEMORY_MB アプリケーション プロセスで使用可能なメモリ量(MB)。
GAE_RUNTIME app.yaml ファイル内で指定したランタイム。
GAE_SERVICE app.yaml ファイル内で指定したサービス名。サービス名が指定されていない場合は、default に設定されます。
GAE_VERSION サービスの現在のバージョン ラベル。
GOOGLE_CLOUD_PROJECT アプリケーションに関連付けられた Google Cloud プロジェクト ID。
PORT HTTP リクエストを受信するポート。
NODE_ENV(Node.js ランタイムでのみ使用可能) サービスがデプロイされたとき production に設定。

app.yaml ファイル内で追加の環境変数を定義できますが、上記の値は NODE_ENV を除きオーバーライドできません。

HTTPS プロキシと転送プロキシ

App Engine は、ロードバランサにおいて HTTPS 接続を終了し、リクエストをアプリケーションに転送します。アプリケーションによっては、元のリクエストの IP とプロトコルが何か確認する必要があります。ユーザーの IP アドレスは、標準の X-Forwarded-For ヘッダーで確認できます。この情報が必要なアプリケーションでは、プロキシを信頼するようにウェブ フレームワークを構成してください。

ファイル システムへのアクセス

ランタイムは書き込み可能な /tmp ディレクトリを持ち、それ以外のディレクトリはすべて読み取り専用です。/tmp に書き込むとシステムメモリが消費されます。

メタデータ サーバー

アプリケーションの各インスタンスは、App Engine メタデータ サーバーを使用してインスタンスとプロジェクトに関する情報を照会できます。

次のエンドポイントを介してメタデータ サーバーにアクセスできます。

  • http://metadata
  • http://metadata.google.internal

メタデータ サーバーに送信されるリクエストには、リクエスト ヘッダー Metadata-Flavor: Google を挿入する必要があります。このヘッダーは、メタデータ値を取得する目的でリクエストが送信されたことを示します。

次の表に、特定のメタデータを取得するための HTTP リクエストの各エンドポイントを示します。

メタデータ エンドポイント 説明
/computeMetadata/v1/project/numeric-project-id プロジェクトに割り当てられているプロジェクト番号。
/computeMetadata/v1/project/project-id プロジェクトに割り当てられているプロジェクト ID。
/computeMetadata/v1/instance/region インスタンスが実行されているリージョン。
/computeMetadata/v1/instance/service-accounts/default/aliases
/computeMetadata/v1/instance/service-accounts/default/email プロジェクトに割り当てられているデフォルトのサービス アカウントのメール。
/computeMetadata/v1/instance/service-accounts/default/ プロジェクトのすべてのデフォルトのサービス アカウントを一覧表示します。
/computeMetadata/v1/instance/service-accounts/default/scopes デフォルトのサービス アカウントでサポートされているすべてのスコープを一覧表示します。
/computeMetadata/v1/instance/service-accounts/default/token アプリケーションを他の Google Cloud APIs に認証させるための認証トークンを返します。

たとえば、プロジェクト ID を取得するには、リクエストを http://metadata.google.internal/computeMetadata/v1/project/project-id に送信します。