姉妹記事: Spring Boot版
この記事では、Google App EngineのJava 11ランタイムを使うアプリケーションをGradleでビルド・デプロイする方法を解説します。
この構成は意外と正確な情報がありません。App Engine Java 11ランタイムのサンプルコードはMavenが使われています。Gradleを使うドキュメントもあるものの、プラグインのバージョンが古かったり、不要なはずのwarの設定があったりします。
さらにGradle Kotlin DSLを使う場合の詰まりどころもあるので、Ktor + Gradle Kotlin DSLのGradleプロジェクトをデプロイするまでをまとめておきます。
前提
環境
- macOS: 10.14.6
- Ktor: 1.2.4
- Gradle: 5.6.2
- Kotlin: 1.3.50
古い情報で混乱しないために知っておくと良いこと
- Google App EngineのJava 11はStandard環境第2世代のランタイム。
- 設定には
appengine-web.xml
ではなくapp.yaml
を使う。 - Webアプリケーションコンテナではなく、jarとしてビルドしたものを実行するので、war関連の設定は不要。
- 設定には
- Gradle 4.0以降では、Google App Engine Gradle plugin 2.xを使う。
手順
1. Ktor Project Generatorでプロジェクトをダウンロード
Ktor Project Generatorを開き、次の設定で「Build」してzipファイルをダウンロードします。
- Gradle with Kotlin DSL project
- Server Engine: Nett(デフォルト)
- Ktor 1.2.4(デフォルト)
2. Gradleを5.xにアップグレード
ダウンロードしたZIPファイルを展開してみると、Gradleのバージョンが4.xとやや古いです。Kotlin DSLサポートはGradle 5.xで改善しているので、次のコマンドで最新版にアップグレードしておきます。
./gradlew wrapper --gradle-version 5.6.2
3. routingを作成して動作確認
動作確認のため src/Application.kt
に次のようにroutingを追記します。
package com.example
import io.ktor.application.*
import io.ktor.response.*
import io.ktor.request.*
import io.ktor.routing.get // 追加
import io.ktor.routing.routing // 追加
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {
routing { // 追加
get("/") {
call.respondText("Hello, Ktor!")
}
}
}
次のコマンドで起動します。
./gradlew run
http://localhost:8080
にアクセスして、 Hello, Ktor!
と返ってくることを確認します。
4. Gradleで実行可能なFat Jarを作る
App EngineのJava 11ランタイムでは、java -jar <jarファイル>
のような形で実行するので、生成するjarファイルにはMain-Class
のマニフェストと依存ライブラリを含める必要があります。デフォルトでは実行できないjarファイルが生成されてしまうため、Gradle Shadowプラグインを使ってfat jarを作ります1。
build.gradle.kts
に次の設定を追記します。
plugins {
application
kotlin("jvm") version "1.3.50"
id("com.github.johnrengelman.shadow") version "5.1.0" // 追加
}
// ...
tasks.assemble {
dependsOn(tasks.shadowJar) // assembleの依存タスクとしてshadowJarを実行する。
}
tasks.shadowJar {
archiveClassifier.set("") // fat jarを単独のjarと同じ名前にして上書きする。
}
./gradlew build
を実行した後に、次のコマンドで起動できることを確認しておきます。
java -jar ./build/libs/ktor-demo-0.0.1-SNAPSHOT.jar
5. Google App Engine Gradle pluginを追加
Google App Engine Gradle pluginを使うために、build.gradle.kts
に次の設定を追加します。
plugins {
application
kotlin("jvm") version "1.3.50"
id("com.github.johnrengelman.shadow") version "5.1.0"
id("com.google.cloud.tools.appengine") version "2.1.0" // 追加
}
これだけだとプラグインをロードできないので、 settings.gradle.kts
に次の設定を追加します。この設定については、 https://stackoverflow.com/a/48510049 を参照してください2。
pluginManagement {
repositories {
gradlePluginPortal()
google()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "com.google.cloud.tools.appengine") {
useModule("com.google.cloud.tools:appengine-gradle-plugin:${requested.version}")
}
}
}
}
6. app.yamlを追加
トップディレクトリにapp.yaml
を次の内容で作成します。この設定はサンプルコードのapp.yamlからjarファイルの名前だけ変更してます。
runtime: java11
instance_class: F2
entrypoint: 'java -Xmx32m -jar *.jar'
build.gradle.kts
に次の設定を追記します。
appengine {
stage {
setAppEngineDirectory(".") // app.yamlをトップディレクトリに置く
}
}
次のコマンドで、デプロイ用の成果物を作成できることを確認します。
./gradlew appengineStage
次のように build/staged-app
に app.yaml
と jarファイルができていればOKです。
$ ls build/staged-app/
app.yaml ktor-demo-0.0.1-SNAPSHOT.jar
7. Google App Engineにデプロイ
build.gradle.kts
に次の設定を追加します。これらの設定は、プロジェクトIDをgcloudコマンドで設定済みのものにし、バージョンを自動生成するという意味なので、明示的に他の値にしても構いません。
設定についてはGoogle App Engine Gradle pluginのUser Guideを参照してください。
appengine {
stage {
setAppEngineDirectory(".") // app.yamlをトップディレクトリに置く
}
deploy { // 追加
projectId = "GCLOUD_CONFIG"
version = "GCLOUD_CONFIG"
}
}
次のコマンドでデプロイします。
./gradlew appengineDeploy
https://<プロジェクトID>.appspot.com
にアクセスして、 Hello, Ktor!
と表示されたら成功です。
なお gcloud
コマンドでデプロイしたい場合は、 ./gradlew appengineStage && cd build/staged-app/ && gcloud app deploy
とすればOKです。
まとめ
以上でデプロイまで完了です。この記事の実行結果のコードは次のリポジトリにあります。
https://github.com/orangain/appengine-java11-gradle-ktor
参考文献
-
Using Gradle and the App Engine Plugin | App Engine standard environment for Java 11 docs | Google Cloud
- 公式の解説だが、Gradleプラグインのバージョンが1.xで古い点と、不要なはずのwarの設定がある点は注意。
-
Ktor Application on Google App Engine Standard with Kotlin
- Ktor + Java 11のサンプルコード。Maven (not Gradle) である点がちょっと違う。
-
google app engine - How to configure AppEngine Gradle plugin using Kotlin DSL - Stack Overflow
- build.gradle.ktsでGoogle App Engine Gradle pluginを使う方法。
-
app-gradle-plugin/USER_GUIDE.md at master · GoogleCloudPlatform/app-gradle-plugin
- App Engine Gradle Pluginのリファレンス。Java 11ランタイムの場合は「App Engine app.yaml based projects」を読むことに注意3。
-
Spring Bootプロジェクトでは、Spring Bootプラグインの
bootJar
タスクがやってくれるので気にしなくて良いです。 ↩ -
https://github.com/GoogleCloudPlatform/app-gradle-plugin#how-to-use や https://stackoverflow.com/a/55075378 のように
buildscript
とapply
を使う方法もありますが、Kotlin DSLではappengine {...}
と書けなくなってしまい、代わりにconfigure<AppEngineAppYamlExtension> {...}
と書く必要があります。 ↩ -
https://cloud.google.com/appengine/docs/standard/java11/gradle-reference にもリファレンスがありますが、
projectId
が古いproject
のままになっていたして、やや古いようです。 ↩