Building using sbt

sbt uses a plugin called sbt-native-packager to allow conveniently packaging Java and Scala applications built using sbt as Docker images.

Setup

This plugin is automatically enabled and configured by the Lagom sbt plugin, so no setup is needed to use it.

Selecting a JDK

By default, sbt native packager uses the openjdk latest Docker image from DockerHub. At time of writing, this will give you OpenJDK 11, which is not certified by Lightbend, and it also gives you the Debian OpenJDK build, which is not certified by Lightbend either. For a full list of Lightbend certified JDK builds and versions, see here.

If you’re a RedHat customer, then you will probably want to use RedHat’s certified OpenJDK base image, which is using RHEL. These OpenJDK builds are certified by Lightbend too for use with Lightbend products. This can be configured using:

dockerBaseImage := "registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift"

Otherwise, we recommend using the AdoptOpenJDK base image:

dockerBaseImage := "adoptopenjdk/openjdk8"

Git hash based version numbers

This step is optional, but we recommend basing the version number of your application on the current git hash, since this ensures that you will always be able to map what is deployed to production back to the exact version of your application being used.

There are a number of sbt plugins available for generating a version number from a git hash, we’re going to use sbt-dynver, which incorporates the most recent git tag as the base version number, appends the git hash to that only if there are any changes since that tag, and also includes a datetime stamp if there are local changes in the repository. To add this plugin to your project, add the following to project/plugins.sbt:

addSbtPlugin("com.dwijnand" % "sbt-dynver" % "3.3.0")

For the plugin to work, you need to ensure that you don’t specify a version in your sbt build, since this will overwrite the version that sbt-dynver generates. Additionally, sbt-dynver generates versions with a + character in them (the + is used to indicate how many commits have been added since the last tag, so 1.0+4 indicates this is the 1.0 tag plus 4 commits). To replace this with a - character, add the following to build.sbt:

version in ThisBuild ~= (_.replace('+', '-'))
dynver in ThisBuild ~= (_.replace('+', '-'))

You may also want to configure the sbt native packager to tag your image as the latest image, this will be necessary if you’re using the latest tag in your deployment spec. To do this, enable dockerUpdateLatest in build.sbt:

dockerUpdateLatest := true

Configuring deployment

After building the docker image, we will need to deploy it to the built in OpenShift docker registry. To do that, we need to configure both the docker username, which should equal the OpenShift project/namespace, as well as the registry. This can be done by configuring the dockerUsername and dockerRepository settings:

dockerUsername := sys.props.get("docker.username")
dockerRepository := sys.props.get("docker.registry")

In this case, we’re reading both variables from system properties, which ensures that the build is not tied to any particular OpenShift installation. We’ll supply these system properties when we invoke sbt.

Building the docker image

Now that we’re setup, we can build our docker image. Run the following:

sbt -Ddocker.username=$NAMESPACE -Ddocker.registry=$DOCKER_REPO_URL shopping-cart/docker:publish

This will build the project that you wish to build, tag it, and then push it to the configured OpenShift registry.

Configuring OpenShift image lookup

When you push a docker image to OpenShift’s internal registry, it will automatically create an image stream that the image can be consumed from.

Since we’re using Kubernetes deployments rather than OpenShift deployment configs, in order to ensure that our deployment can consume this from the internal OpenShift registry with an unqualified tag, we need to allow local lookups on it. This can be enabled by running the following command.

oc set image-lookup shopping-cart

For more information on image stream lookups, see the OpenShift documentation.