Disclaimer: this plugin is far from being production ready, yet it’s a great attempt to bring jib to sbt
This post describes how to dockerize a Play!Framework application using sbt-jib plugin
The first sections of this post assume no knowledge on Play! or previous project, but configuration is applicable to existing projects.
Creating a Play!Framework
this post requires sbt to be installed.
So in order to scaffold a Play!Framework application to Dockerize let’s start by running the following command:
sbt new playframework/play-java-seed.g8
This should take a while.. as sbt downloads all dependencies and scaffolds a new project.
This is an interactive command, as you will be prompted for your organization, and project name.
Setting sbt-jib plugin in Project
After generating the project, we should have a Play! project structure.
In order to set plugins available to our project we must edit the following file:
with the following contents
```scala
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.0")
// Defines scaffolding (found under .g8 folder)
// http://www.foundweekends.org/giter8/scaffolding.html
// sbt "g8Scaffold form"
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")
addSbtPlugin("de.gccc.sbt" % "sbt-jib" % "0.2.3")
Ok, so we now have sbt-jib plugin in our project, but first we must activate it in our build.sbt
file.
So on the root of our project, let’s edit build.sbt to enable sbt-jib plugin.
1
2
3
4
5
6
7
8
9
10
11
name := """jib-sbt-play"""
organization := "com.ilhicas"
version := "1.0.0-SNAPSHOT"
lazy val root = (project in file("."))
.enablePlugins(PlayJava, JibPlugin)
scalaVersion := "2.12.8"
libraryDependencies += guice
So with JibPlugin
under enabled plugins we should be able to use plugin tasks.
Running sbt-jib plugin to build our first image
Let’s start by compiling and running a task equivalent to google’s maven jib plugin goal of dockerBuild that is responsible for building a local docker image.
To compile and build docker image we run the following command in the root of the project
sbt compile jibDockerBuild
We should get a similar output to:
1
2
3
4
[info] Executing in batch mode. For better performance use sbt's shell
[success] Total time: 1 s, completed 23/04/2019, 22:27:06
[success] image successfully created & uploaded
[success] Total time: 107 s, completed 23/04/2019, 22:28:53
Ok, so now we should have an image:
1
com.ilhicas/jib-sbt-play:1.0.0-SNAPSHOT c15d53c5f3c6 49 years ago 520MB
Ok, first alert using this plugin, image has a 49 years ago timestamp. As of the time of writing I haven’t figured out to fix it yet, as project is currently undocumented, and my sbt knowledge is far from extensive, or better yet, almost inexistent :D .
Ok, so I’m using Java 11
and my sources are being compiled against it, and jib plugin uses the gcr.io/distroless/java
to run our compiled classes, however, you are not able to run classes compiled against java > 8.
So if we run our newly created image against the default image using a java version greater than 8.
1
docker run --rm -p 80:9000 com.ilhicas/jib-sbt-play:1.0.0-SNAPSHOT
We will run into some troubles:
1
Exception in thread "main" java.lang.UnsupportedClassVersionError: controllers/HomeController has been compiled by a more recent version of the Java Runtime
Customizing jib-sbt plugin settings
Ok, so how to change base image plugin will use?
According to the settings we are able to see under source control of plugin we can see that there is a setting named jibBaseImage
So let’s edit our build.sbt again, this time setting the properties for the plugin, such as our base image, and some friendly image tagging.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name := """jib-sbt-play"""
organization := "com.ilhicas"
version := "1.1.0"
lazy val root = (project in file("."))
.enablePlugins(PlayJava, JibPlugin)
.settings(
jibBaseImage := "openjdk:11-jre",
jibName := "jib-hello",
jibOrganization := "ilhicas"
)
scalaVersion := "2.12.8"
libraryDependencies += guice
Image tagging is a composition of jibOrganization/jibName:version
Ok, so now we have a Java 11
compatible base image.
In order to avoid some of my Play!Framework noob mistakes when writing this post, let’s set a play.http.secret.key
property, otherwise and since Play will run under production, failure to set this property results in a thrown error and container will exit.
Edit conf/application.conf
with the following example content:
1
2
3
# This is the main configuration file for the application.
# https://www.playframework.com/documentation/latest/ConfigFile
play.http.secret.key="^L^lY@/U7nFeFUbV=7EO[^NzhINnbrhS;gvik3tv:A7mvt0N9gcH6TOmxPpvd7nA"
Ok so now we are ready to go.
So let’s run the command to generate our new image.
1
sbt compile jibDockerBuild
This should take around a minute or two.
After our new image is built we are now able to run it.
1
docker run --rm -p 80:9000 ilhicas/jib-hello:1.1.0
Since play by default runs under port 9000, we are mapping it to our host under port 80, and we should be able to visit localhost
and be greeted by Play Hello World project.
And that’s it for this post, hope you found it helpful.