Home Education Docker Tutorial: Dockerizing Scala

Docker Tutorial: Dockerizing Scala

Author

Date

Category

Prerequisites

A working docker installation (boot2docker is fine)

Typesafe’s activator (or use ./activator found at the root of the git-repo — it will download the dependencies)

You can find/fork the sourcecode for all of the following on Github

Intro

The sbt plugin sbt-native-packager provides a really easy way to deploy your sbt project as a docker container.

In the following we will create a docker running a tiny scala helloWorld.

To use the native-packager we just add this line to your project/plugins.sbt

addSbtPlugin(“com.typesafe.sbt” % “sbt-native-packager” % “1.0.3”)

and in the build.sbt put:

enablePlugins(JavaAppPackaging)

enablePlugins(DockerPlugin)

Publishing

At this point our application is ready to run and you can deploy your docker by running

sbt docker:publishLocal

in your terminal. (This might take a while depending on how many layers you have to download)

Let’s verify the process by executing:

docker images

and we should see your newly created docker along with the base image (“java/latest”)

We can run it by executing:

docker run -it sbt-docker-example:1.0

and “Hello, world!” should be printed.

Optimizing/Customizing

There are a few settings the plugins exposes and we can override. You can find a list here.

Our current container occupies quite a lot of space ( > 800 MB) and we will try (and succeed 😛 ) to get it smaller. The current size is mostly because of the base image — “java:latest” — which is the packager’s default (it uses OpenJDK). We can override with any other image that provides a java installation.

For our example we will use frolvlad’s image which is significantly smaller and uses oracle-java. We add the following line to our build.sbt:

dockerBaseImage := “frolvlad/alpine-oraclejdk8”

Publishing the container now results in a much smaller image. However it’s broken…

sbt docker:publishLocal && docker run -it sbt-docker-example:1.0

results in:

env: can’t execute ‘bash’: No such file or directory

The native-packager depends on a working bash installation in the container. So let’s install it.

But first let’s take a look at what’s happening under the hood. We would like to know how the image is being built. Let’s take a look at the docker comands by running

sbt “show dockerCommands”

gives us:

List(Cmd(FROM,frolvlad/alpine-oraclejdk8), Cmd(WORKDIR,/opt/docker), Cmd(ADD,opt /opt), ExecCmd(RUN,List(chown, -R, daemon:daemon, .)), Cmd(USER,daemon), ExecCmd(ENTRYPOINT,List(bin/sbt-docker-example)), ExecCmd(CMD,List()))

If we blank out the scala parts (Cmd,List and ExecCmd) this looks very similar to comands we find in a Dockerfile.

We decide that the right place to install bash is right after the FROM command. Let’s override the dockerComands in our build.sbt by adding:

dockerCommands := dockerCommands.value.flatMap{
case cmd@Cmd(“FROM”,_) => List(cmd, Cmd(“RUN”, “apk update && apk add bash”))
case other => List(other)
}

We could look at the command sequence again but let’s just be bold an run the docker:

sbt docker:publishLocal && docker run -it sbt-docker-example:1.0

Et voilà, “Hello, world!” is back. And the new image size is now < 200 MB


Edit: We just published an ebook: “The Ultimate Guide to Code Review” based on a survey of 680+ developers. Enjoy!

About Codacy

Codacy is used by thousands of developers to analyze billions of lines of code every day!

Getting started is easy – and free! Just use your  GitHub, Bitbucket or Google account to sign up.

GET STARTED

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Subscribe to our newsletter

To be updated with all the latest news, offers and special announcements.

Recent posts

February’s Product Update: 1-Click Autofixes for GitHub, New People Experience and more 🚀

Welcome to our monthly product update! We’ve been working hard over the past month and have some exciting updates for you below. 🥳 We want...

Interview with Daniel Pfeiffer, CTO at Firstbird

We had a very nice talk with Daniel Pfeiffer, CTO at Firstbird; it was an informal conversation in which we looked to understand the reasons why...

Add a Custom Host to Kubernetes

I’ve been working with different MicroK8s instances a lot in the last months. Microk8s, from my point of view, it’s the absolutely perfect abstraction for deploying...

Deciphering Javascript Checkers: Know Why and When You Might Use Them

We’re all familiar with rules of grammar, which aid in communication by letting us know when to use a comma, how to spell a...

Interview with Felipe Adorno, CTO at Monkey Exchange

We have talked with Felipe Adorno, CTO at Monkey Exchange, to better understand what made the company opt for an automated code review tool...