Let’s build an application using Kotlin and the ktor framework. The application will respond to the /
and /hello-world
routes and listen on port 3000 by default.
initialize a new project with gradle:
# create a directory
$ mkdir ./new-project && cd new-project
$ gradle init \
--type kotlin-application \
--dsl kotlin \
--project-name runway \
--package main \
--incubating
gradle init
command, is the ktor project generator. If you prefer this method, you will have to download the generated project and extract the archive in place. Follow the instructions on the page and come back here after.Once the project is created, you have to edit app/src/main/kotlin/main/App.kt
and replace it with the following:
package main
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun main() {
// Get the port from the environment variable or use 3000 as default
val port = System.getenv("PORT")?.toIntOrNull() ?: 3000
// Start the Ktor server
embeddedServer(Netty, port) {
routing {
get("/") {
call.respondText("Hello")
}
get("/hello-world") {
call.respondText("Hello World")
}
}
}.start(wait = true)
}
app/src
.The next step is to update the app/build.gradle.kts
so we can build and run our app:
plugins {
id("org.jetbrains.kotlin.jvm") version "1.8.10"
id("io.ktor.plugin") version "2.3.12"
application
}
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
implementation("io.ktor:ktor-server-core-jvm")
implementation("io.ktor:ktor-server-netty-jvm")
}
application {
mainClass.set("main.AppKt")
}
Now run: ./gradlew build
and it should complete. Feel free to test your app with ./gradlew run
too and go to http://localhost:3000/hello-world
.
Commit the following multi-stage Dockerfile
to your repository:
FROM gradle:8.0-jdk17 AS build
WORKDIR /workspace
# Copy the Gradle wrapper and build files
COPY app/build.gradle.kts settings.gradle.kts ./
# Copy the source code
COPY app/src ./src
RUN gradle installDist
FROM openjdk:17-jdk-slim
WORKDIR /app
# Set the user to nobody (in numeric)
USER 65534:65534
# Copy the app from the build stage
COPY --from=build /workspace/build/install/runway /app
EXPOSE 3000
CMD ["/app/bin/runway"]
The Dockerfile
follows a common pattern when getting a project build and deployed: the first stage (build
) is used to install all dependencies and compile the application with gradle installDist
.
The second (final) stage uses a smaller image and copies the application from build
and instructs Runway with a USER
and a port (EXPOSE
).
git init
and commit everything!Create an application on Runway:
$ runway app create
INFO checking login status
INFO created app "amazing-coffee"
create app amazing-coffee: done
next steps:
* commit your changes
* runway app deploy
* runway open
And deploy:
$ runway app deploy && runway open
Congrats, your Kotlin app is running on Runway! ☕️