These tutorials target Micronaut Framework 3. Read, Guides for Micronaut Framework 4.

Deploy GraalVM Native Executable to Google Cloud Run

Deploy a GraalVM Native Executable of a Micronaut application to Google Cloud Run - a fully managed serverless platform for containerized applications.

Authors: Sergio del Amo

Micronaut Version: 3.9.2

1. Getting Started

In this guide, we will create a Micronaut application written in Kotlin.

Push the Docker image of your application to Google Cloud Container Registry or to Google Cloud Artifact Registry.

The docker image runs a GraalVM Native Executable of the Micronaut application.

Develop and deploy highly scalable containerized applications on a fully managed serverless platform.

2. What you will need

To complete this guide, you will need the following:

3. Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.

4. Writing the Application

Create an application using the Micronaut Command Line Interface or with Micronaut Launch.

mn create-app example.micronaut.micronautguide --build=gradle --lang=kotlin
If you don’t specify the --build argument, Gradle is used as the build tool.
If you don’t specify the --lang argument, Java is used as the language.

The previous command creates a Micronaut application with the default package example.micronaut in a directory named micronautguide.

4.1. Controller

In order to create a microservice that responds with "Hello World" you first need a controller.

Create a Controller:

src/main/kotlin/example/micronaut/HelloController.kt
package example.micronaut

import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Produces

@Controller("/hello") (1)
class HelloController {

    @Get(2)
    @Produces(MediaType.TEXT_PLAIN) (3)
    fun index() = "Hello World"
}
1 The class is defined as a controller with the @Controller annotation mapped to the path /hello.
2 The @Get annotation maps the index method to an HTTP GET request on /hello.
3 By default, a Micronaut response uses application/json as Content-Type. We are returning a String, not a JSON object, so we set it to text/plain.
4 A String "Hello World" is returned as the result

4.2. Test

Create a test to verify that when you make a GET request to /hello you get Hello World as a response:

src/test/kotlin/example/micronaut/HelloControllerTest.kt
package example.micronaut

import io.micronaut.http.HttpRequest
import io.micronaut.http.client.HttpClient
import io.micronaut.http.client.annotation.Client
import io.micronaut.test.extensions.junit5.annotation.MicronautTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Test
import jakarta.inject.Inject

@MicronautTest (1)
class HelloControllerTest(@Client("/") val client: HttpClient) { (2)

    @Test
    fun testHello() {
        val request: HttpRequest<Any> = HttpRequest.GET("/hello")  (3)
        val body = client.toBlocking().retrieve(request)
        assertNotNull(body)
        assertEquals("Hello World", body)
    }
}
1 Annotate the class with @MicronautTest so the Micronaut framework will initialize the application context and the embedded server. More info.
2 Inject the HttpClient bean and point it to the embedded server.
3 Creating HTTP Requests is easy thanks to the Micronaut framework fluid API.

5. Google Cloud Platform

Signup for the Google Cloud Platform

5.1. Cloud SDK

Install the Cloud SDK CLI for your operating system.

Cloud SDK includes the gcloud command-line tool. Run the init command in your terminal:

gcloud init

Log in to your Google Cloud Platform:

gcloud auth login

5.2. Google Cloud Platform Project

Create a new project with a unique name (replace xxxxxx with alphanumeric characters of your choice):

gcloud projects create micronaut-guides-xxxxxx
In GCP, project ids are globally unique, so the id you used above is the one you should use in the rest of this guide.

Change your project:

gcloud config set project micronaut-guides-xxxxxx

If you forget the project id, you can list all projects:

gcloud projects list

6. Docker Push Native

Before attempting to push the image, make sure you run GraalVM JDK.

The easiest way to install GraalVM on Linux or Mac is to use SDKMan.io.

Java 11
sdk install java 22.3.r11-grl
If you still use Java 8, use the JDK11 version of GraalVM.
Java 17
sdk install java 22.3.r17-grl

For installation on Windows, or for manual installation on Linux or Mac, see the GraalVM Getting Started documentation.

After installing GraalVM, install the native-image component, which is not installed by default:

gu install native-image

Push the Docker image of your application to Google Cloud Container Registry.

Modify your Gradle build and configure the

...
..
.
dockerBuildNative {
    images = ["gcr.io/micronaut-guides-xxxxxx/micronautguide:latest"]
}
./gradlew dockerPushNative

The previous URL uses the pattern: gcr.io/micronaut-guides-xxxxxx/micronautguide:latest. Change it to use your Project ID.

You get an output such as:

....
..
.
Pushing image 'gcr.io/micronaut-guides-xxxxxx/micronautguide:latest'.

7. Google Cloud Run Deploy

You can deploy to Google Cloud Run via the CLI. Use the value you configured in your build as the image argument’s value.

gcloud run deploy \
    --image=gcr.io/micronaut-guides-xxxxxx/micronautguide:latest \
    --platform managed \
    --allow-unauthenticated

You will see an output such as:

Service name (micronautguide):
Please specify a region:

...

 [22] us-central1
 [23] us-east1
 [24] us-east4

...

 [29] cancel
Please enter your numeric choice:  23

To make this the default region, run `gcloud config set run/region us-east1`.

Deploying container to Cloud Run service [micronautguide] in project [micronaut-guides-xxxxxx] region [us-east1]
✓ Deploying... Done.
  ✓ Creating Revision...
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [micronautguide] revision [micronautguide-00002-fat] has been deployed and is serving 100 percent of traffic.
Service URL: https://micronautguide-63kwrzytgq-ue.a.run.app

8. Running the Application

curl -i https://micronautguide-li3tercjmq-ue.a.run.app/hello
HTTP/2 200
content-type: text/plain
x-cloud-trace-context: 139f91d74bfe5d24a2770fca9abef1d7
date: Sat, 02 Oct 2021 07:18:52 GMT
server: Google Frontend
content-length: 11
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"

Hello World

9. Next steps

You will probably want to deploy to Google Cloud Run from your CI server. Micronaut Launch contains feature github-workflow-google-cloud-run-graalvm, which adds a GitHub Actions Workflow that deploys a GraalVM Native executable of a Micronaut application to Google Cloud Run from Google Container Registry.