Kotlin (Ktor & Docker)でHello Worldしてみる
先日書いた通り、今年はKotlinに挑戦してみます。
その第一歩としてとりあえずHello Worldしてみるところから始めてみました。
今回はKtorを使ってみることにします。
Ktor
KtorはKotlinを開発しているJetBrains社製のWebフレームワークです。
Ktor自体もKotlinで書かれており、軽量で柔軟性に富んだ (Lightweight and Flexible) フレームワークとのことです。
JavaやJVM言語のフレームワークと言えばSpring Bootが有名かと思います。
当初Spring Bootを使ってやってみようと進めていたのですが、JetBrains社製のKtorは言わばKotlinの公式フレームワークなのでこちらで再度やり直すことにしました。
Hello Worldしてみる
今回は上記2つをDocker上で動くようにしてみたいと思います。
こちらのKtor公式ドキュメントを参考に進めていきます。
Ktorのプロジェクトを作成
Ktorのプロジェクトの作り方は色々あります。
IntelliJ IDEA Ultimateを使っていればIDE上で作成することもできるようですが、まだ無課金なので今回はKtor Project Generatorを使います。
プロジェクト名やバージョン等を設定したら「Add plugins」をクリックします。
認証やルーティング等、様々なプラグインを追加できます。これらは後からでも追加できるので後回しでも良さそうです。
とりあえず今回はRouting
とCORS
を追加しました。
「Generate project」をクリックするとzipファイルのダウンロードが始まります。解凍するとプロジェクトに必要なファイルが一式揃っています。
Dockerの設定
Dockerの設定を行っていきます。今回はDBも用意したいのでDocker composeを使います。
まずはDockerfile
をプロジェクトルート直下に作成します。
FROM eclipse-temurin:17 EXPOSE 8080:8080 RUN mkdir /app COPY ./build/libs/*-all.jar /app/blog.jar ENTRYPOINT ["java", "-jar", "/app/blog.jar"]
上記公式ではopenjdk
のイメージを使用していますが、OpenJDKのDockerイメージは非推奨となり今後更新されないため、eclipse-temurin
を代わりに使用します。
参考: Docker HubのOpenJDKイメージの利用を更新するためのアドバイス - 赤帽エンジニアブログ
続いてdocker-compose.yml
を作成します。
version: "3" services: app: build: context: . dockerfile: ./Dockerfile ports: - 8080:8080
Dockerの設定は取り急ぎ以上です。
ビルド
先程のDockerfile
から分かる通り、ビルド済みのjarファイルをローカルからコンテナ上の/app/hoge.jar
にコピーしています。
なのでDockerイメージのビルド前にKotlinのビルドが必要です。
./gradlew buildFatJar
完了したら今度はDockerイメージをビルドします。
docker compose build
そして最後にコンテナを立ち上げます。
docker compose up -d
無事起動したらhttp://localhost:8080
にアクセスして以下のように表示されたらOKです。
が、これだと都度Kotlinのビルド⇒Dockerイメージのビルド⇒コンテナ起動しないと変更が反映されないので修正していきます。
Dockerfileを修正
以下のように修正します。
FROM eclipse-temurin:17 EXPOSE 8080:8080 RUN mkdir /app WORKDIR /app/
docker-compose.yml修正
以下のように修正します。
version: "3" services: app: volumes: - .:/app/ build: context: . dockerfile: ./Dockerfile ports: - 8080:8080 tty: true
tty: true
を追加してコンテナの起動状態を継続させています。
Auto-reload
KtorにはAuto-reloadという機能があり、変更を検知して再コンパイルしてくれます。
これを有効にするにはdevelopment mode
をONにして監視対象のパスを追加します。
ktor { deployment { port = 8080 watch = [ classes ] // 追加 } application { modules = [ com.example.ApplicationKt.module ] } development = true // 追加 }
ここまで設定したら再度イメージをビルドして立ち上げます。
docker compose build --no-cache
docker compose up -d
app
コンテナ内でバックグラウンドでビルドします。
docker compose exec app ./gradlew -t build -x test
以下のように表示されたらOK。
BUILD SUCCESSFUL in 2m 16s 11 actionable tasks: 11 up-to-date Waiting for changes to input files... (ctrl-d to exit) <-------------> 0% WAITING
別タスクでアプリケーションを起動します。
docker compose exec app ./gradlew run
しばらく待つと以下のように表示されます。
2023-01-12 13:01:17.457 [main] INFO Application - Application started in 2.62 seconds. 2023-01-12 13:01:18.126 [main] INFO Application - Responding at http://0.0.0.0:8080 <===========--> 85% EXECUTING [51s] > :run
この状態でコードを修正すると再度./gradlew -t build -x test
が走り、変更が反映されます。
まとめ
取り急ぎ開発できる体制は整いました。
が、まだわからないことだらけです。./gradlew -t build -x test
すると毎回zipファイルがダウンロードされるし、その他不要なタスクも大量にありそうです。
そのあたりの設定も少しずつ見ていきたいと思います。