I set up a Scala project to run on Cloud Run, but immediately after it starts, I receive Success logs, and then it shuts down abruptly.
import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.*
import akka.http.scaladsl.server.Directives.*
import org.slf4j.LoggerFactory
import scala.concurrent.duration.*
import scala.concurrent.{ExecutionContextExecutor, Future}
import scala.util.{Failure, Success}
object Main extends App {
implicit val system =
ActorSystem(Behaviors.empty, "my-system")
implicit val executionContext: ExecutionContextExecutor =
system.executionContext
val logger = LoggerFactory.getLogger(this.getClass)
val route = path("fetch-api") {
get {
onComplete(fetchApiData()) {
case Success(value) =>
logger.info(s"API Response: $value")
complete(value)
case Failure(ex) => complete(s"An error occurred: ${ex.getMessage}")
}
}
}
val port = sys.env.getOrElse("PORT", "8080").toInt
val bindingFuture = Http().newServerAt("0.0.0.0", port).bind(route)
bindingFuture.onComplete {
case Success(binding) =>
logger.info(
s"Server online at http://${binding.localAddress.getHostString}:${binding.localAddress.getPort}/"
)
case Failure(exception) =>
logger.error(s"Failed to bind to $port: ${exception.getMessage}")
system.terminate()
}
def fetchApiData(): Future[String] = {
val request = HttpRequest(uri = "https://api.publicapis.org/entries")
logger.info(
"Starting method fetchApiData on URI: https://api.publicapis.org/entries"
)
Http()
.singleRequest(request)
.flatMap { response =>
logger.info(s"Status da Resposta HTTP: ${response.status}")
response.entity.toStrict(60.seconds).map { entity =>
entity.data.utf8String
}
}
.recover { case ex =>
s"An error occurred: ${ex.getMessage}"
}
}
}
Dockerfile
FROM openjdk:11-slim
RUN apt-get update && apt-get install -y curl && curl -sL "https://github.com/sbt/sbt/releases/download/v1.9.8/sbt-1.9.8.tgz" | tar -xz -C /usr/local && ln -s /usr/local/sbt/bin/sbt /usr/local/bin/sbt && apt-get clean
WORKDIR /app
COPY . /app
RUN sbt compile
RUN apt-get update && apt-get install -y curl
EXPOSE 8080
ENV PORT 8080
CMD ["sbt", "run"]
build.sbt
import sbt.Keys.libraryDependencies
ThisBuild / version := "scala-http"
ThisBuild / scalaVersion := "3.3.1"
mainClass := Some("Main")
lazy val root = (project in file("."))
.settings(
name := "Test",
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http" % "10.5.0",
"com.typesafe.akka" %% "akka-actor-typed" % "2.8.5",
"com.typesafe.akka" %% "akka-stream" % "2.8.5",
"ch.qos.logback" % "logback-classic" % "1.4.14"
)
)
Logs:
\[info\] welcome to sbt 1.9.8 (Oracle Corporation Java 11.0.16)
\[info\] loading settings for project app-build from plugins.sbt ...
\[info\] loading project definition from /app/project
\[info\] loading settings for project root from build.sbt ...
\[info\] set current project to Test (in build file:/app/)
\[warn\] there's a key that's not used by any other settings/tasks:
\[warn\] \* root / mainClass
\[warn\] +- /app/build.sbt:12
\[warn\] note: a setting might still be used by a command; to exclude a key from this `lintUnused` check
\[warn\] either append it to `Global / excludeLintKeys` or call .withRank(KeyRanks.Invisible) on the key
\[info\] running Main
\[my-system-akka.actor.default-dispatcher-3\] INFO akka.event.slf4j.Slf4jLogger -- Slf4jLogger started
Default STARTUP TCP probe succeeded after 1 attempt for container "scala3-test-1" on port 8080.
\[success\] Total time: 11 s, completed Feb 1, 2024, 6:46:42 PM
Server online at http://0.0.0.0:8080/
I tried to use the sbt docker:publishLocal with the plugin "com.github.sbt" % "sbt-native-packager" % "1.9.8" and some parameters on build.sbt dockerBaseImage := "openjdk:11" dockerExposedPorts := Seq(8080), but with this plugin the error is Revision is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable.
Any help would be great on how to create a cloud run with Scala.