Building and deploying Java 17 apps on Cloud Run with cloud native buildpacks on Temurin
With a custom Dockerfile
On Cloud Run, you deploy containerised applications, so you have to decide the way you want to build a container for your application. In a previous article, I showed an example of using your own Dockerfile, which would look as follows with an OpenJDK 17, and enabling preview features of the language:
To further improve on that Dockerfile, you could use a multistage Docker build to first build the app in one step with Gradle, and then run it in a second step. Also you might want to parameterize the command as the JAR file name is hard-coded.
To build the image, you can build it locally with Docker, and then push it to Container Registry, and then deploy it:
Instead of building locally with Docker, you could also let Cloud Build do it for you:
You specify the version of the plugin, but you also indicate that you want to use Java 17 by choosing a base image with that same version. Be sure to change the placeholders for your project ID and service name. Feel free to lookup the documentation about the JIB Gradle plugin. You can then let Gradle build the container with ./gradlew jib, or with ./gradlew jibDockerBuild if you want to use your local Docker daemon.
With Cloud Native Buildpacks
Now that we covered the other approaches, let’s zoom in on using Cloud Native Buildpacks instead, in particular, the Google Cloud Native Buildpacks. With buildpacks, you don’t have to bother with Dockerfiles or with building the container before deploying the service. You let Cloud Run use buildpacks to build, containerize, and deploy your application from sources.
Out of the box, the buildpack actually targets Java 8 or Java 11. But I’m interested in running the latest LTS version of Java, with Java 17, to take advantage of some preview features like records, sealed classes, switch expressions, etc.
In my Gradle build, I specify that I’m using Java 17, but also enable preview features:
Like in Cédric Champeaus’s blog post, to enable preview features, you should also tell Gradle you want to enable them for compilation, test, and execution tasks:
So far so good, but as I said, the default native buildpack isn’t using Java 17, and I want to specify that I use preview features. So when I tried to deploy my Cloud Run app from sources with the buildpack, simply by running the gcloud deploy command, I would get an error.
To circumvent this problem, I had to add a configuration file, to instruct the buildpack to use Java 17. I created a project.toml file at the root of my project:
I specify that the runtime version must use Java 17. But I also add the --enable-preview flag to enable the preview features at runtime.
Adoptium Temuring OpenJDK 17
The icing on the cake is that the build is using Adoptium’s Temurin build of OpenJDK 17, as we recently announced! If you look at the build logs in Cloud Build, you should see some output mentioning it, like:
Way to go! Java 17 Micronaut app, deployed on Temurin on Cloud Run thanks to cloud native buildpacks! I win at buzzword bingo 🙂