Home Using sbt jib google's jib inspired sbt plugin to dockerize Play!Framework application
Post
Cancel

Using sbt jib google's jib inspired sbt plugin to dockerize Play!Framework application

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.

This post is licensed under CC BY 4.0 by the author.