If you are in doubt about using Docker, Google Trends says enough about its popularity.


Until a few release ago, it was quite a hassle to run Docker. However it has become stable lately. I have been using Docker for 1.5 years and my experience has been quite amazing. I love how I can run a Docker image built on my laptop in production without any headache. Also, it’s very easy to distribute a runnable image or run someone else’s image on your machine. You need Docker insatlled on your system and you can just run the application.

In this post, we are going to create Docker image for a simple Scala application.


What is Docker?

Docker is a tool designed to run applications in an isolated environment using containers. Containerization is an OS level virtualization method to run multiple systems on a single kernel without launching an entire virtual machine. On Linux based operating systems, it is achieved using LXC (Linux Containers). Docker uses built-in Linux containment features like CGroups, Namespaces, UnionFS, chroot to run applications in the virtual environment.

LXC is an API for Linux containment features. Initially, Docker was built on top of LXC. Starting with Docker 0.9, it has been replaced with libcontainer.

To learn more about Docker, official documentation is a good place to start.


Docker with Scala Build

To create Docker image for a Scala application, we’ll use sbt-native-packager.

sbt-native-packager focuses on creating a Docker image which can “just run” the application built by SBT.

To achieve this, a few entries have to added in settings of project definition.

Let’s create Docker image for a simple service. Here is one that uses Akka HTTP. I just picked the first example I saw in Akka HTTP documentation. This service listens on 8080 and displays a simple hello page for /hello path. Full code is available on GitHub.

To build Docker image for this service, project definition in Build.scala looks like

L15 specifies the main class of the project.

L16 specifies a list of TCP ports to expose from the Docker image. Your application must be listening on one of these ports.

L17 specifies the entry point for Docker. This command will be executed when Docker container is run.

L18 specifies the repository to which the image should be pushed when docker:publish is run.

L19 specifies the base image to be used when building Docker image for this project.

Run docker:publishLocal after compilation to publish the Docker image locally.


Docker with Play Application

With Play framework, project definitions are written in build.sbt by default. Here, root or main project definition looks like

L15 prevents Docker from creating images for the subprojects separately.


Build your own Baseimage

I personally prefer phusion/baseimage which is a minimal Ubuntu baseimage. In a lot of cases, it so happens that you need some packages to run your applications. Rather than adding the code to install these packages in all build files separately, it’s easier to build an image containing all the packages and use it as baseimage for your projects.

For example, if you need Java installed, you can create a Dockerfile with following code and build your own baseimage.


Resources

  1. Example Code: https://github.com/neerajgangwar/dockerize-scala-app
  2. Official Docs: https://docs.docker.com
  3. sbt-native-packager: http://www.scala-sbt.org/sbt-native-packager/formats/docker.html