Contents

Deja-Vue

My pizza service analogy works well as an example as it covers showing pages,
posting forms, and reading changed data. And I have over time written several howtos that use the pizza service analogy,
the Play framework, and hosting with various cloud providers:

Activator

Download and install Activator, Lightbend's (né Typesafe) extension of SBT, the near default Scala build tool.
Activator includes a UI which you do not need,
but does include the handy new command to scaffold Play and Akka applications.

Activator comes in two flavours: full and mini. Full includes common dependencies for Play and Akka. Full will save you a little time initially, but soon the dependencies versions will move along and you have to download them all like mini via SBT's use of Ivy anyway.

SBT

I recommend also installing SBT, as 99% of the time you don't need the extra cruft of Activator.
There are other Scala build tools such as Maven and Gradle,
but there is little reason to use those with Scala and again you will painfully swim against the current of 99% of projects and companies that defaults to SBT.

Dockerfile

You have a few options of how you build your images.
Mostly due to relatively slowness of downloading all Ivy dependencies from scratch on every build.

You can build the jar file outside of Docker.
Then just add the jar or target/stage folder to the Dockerfile. This is result in very fast Docker image builds,
but adds another step that is just as slow before it.

For that you either build manually in the project folder via sbt package or sbt stage (for Play apps).

Either on every build, this is the least complicated method but also very, very slow.
This is the method we will use in this document.

Or you depend on a base image with all the dependencies preload in ~/.ivy2.
Similar to my play-framework-base.
You then extend your Dockerfile from this base image.
Note the versions of the dependencies in the base and your project must match for it to be of use.

Create a Dockerfile in the root folder.
This will use my my play-framework image,
so the default dependencies for Play is already part of the image but not any other dependencies.

Pizzeria service

Lets create the actual pizzeria service.
We will create a normal landing page that in our case shows the pizza menu and order form.
We will have a POST endpoint to send our order to,
and a confirmation page to confirm our pizza order has been received.

Though first lets remove some parts we are not using in this application.
(of course in your future applications you may use these, so be aware of them)

In the project's build.sbt file lets remove some dependencies we won't need in this example (cache, ws, scalatest),
keeping jdbc as we will need that later.
And also add a hack with devnull to support docker restarts.

vi build.sbt
name := """pizzeria"""

version := "1.0-SNAPSHOT"

lazy val root = (project in file(".")).enablePlugins(PlayScala)

scalaVersion := "2.11.8"

libraryDependencies ++= Seq( jdbc
)

javaOptions in Universal ++= Seq(
"-Dpidfile.path=/dev/null"
)

Show menu

Lets edit the routes file.
We will remove the references to Async, Home and CountControllers.
And add a PizzaController.
Open conf/routes in your editor of choice.

This can now be tested via a browser by clicking on the order
buttons on the menu, or directly via curl.

This still doesn't really do anything,
it just returns blank pages as we havent specified a template.
It only returns the expected http error code.
We could also include the erroneous form in the BadRequest response
but we are keeping it simple for now.

Lets add the showConfirmation method to PizzaController.
It will try to find the order,
and either display a confirmation page with it,
or a blank page with a 404 not found http status code
if there was no orders found with the supplied id.

When in production it is recommend using proper database instance(s) outside Docker.
For example clustered PostgreSQL, Amazon RDS,
Google Bigtable, Redis on Heroku,
Cassandra on Mesos etc.
I am on the fence on this one, I understand why due to Docker's ephemeral nature and historic issue with data persistence,
but I do run many databases in containers, especially less ciritical system...

For persistance library this Pizzeria uses Anorm.
Anorm is very thin wrapper around normal SQL made by the original Play developers themselves.
A more common framework is Slick, and is the default for Play these days.
Slick is functional relational mapper,
and often involves more compexity that is needed by too many layers of abstractions.

In the project's build.sbt file we will add some dependencies we will need,
and actually use the jdbc alias we kept earlier.

This should show a redirect to confimation page.
And if we GET that it should show we ordered a Margherita.

curl localhost:9000/order/1

Build a Docker image of our finished Pizzeria service.
And tag it.

docker build -t pizzeria .;
docker tag pizzeria:latest pizzeria:1.0

Docker Cloud

Docker Cloud is a handy way to manage your public docker containers.
It enables you to easily build and host your images.
It lets you orchestrate and deploy your container stacks.
And monitor and scale as appropriate.

Docker Cloud does not actually host your actual running containers.
Hosting is still done with normal
IAAS cloud providers.
Such as Amazon AWS, etc.
Docker Cloud instead manages the containers on these instances for you.
It can directly create instances for you on some of the IAAS providers,
or you can connect an existing node to Docker Cloud
by installing an agent service.
You can also spread your containers horizontally across nodes on different IAAS providers.

There is a reasonable free tier that lets your experiment and run quite a few containers for free.
(As I am grand-fathered in as
a user of Docker Cloud's predecessor, Tutum so my free tier is slightly more generous).
Combine this with the free tiers at many IAAS providers you can experiment for quite some time totally free.

DigitalOcean is the easiest to integrate with.
Amazon AWS I would guess is the most popular as many will already have a presence there.
I prefer Google Cloud as provider,
via the Bring Your Own Node feature.

Create a node or two.
Keep in mind the pizzeria service is a JVM based image so will be memory hungry,
and for now compute shy. So the t2.nano and t2.micro instances on AWS will be too small
where
as a $20 instance on DigitalOcean or a t2.small instance on AWS is a good start, and R4 instances better suited later on.
For example I mostly use 6.5GB with 1 cpu custom instances on Google Cloud to host 4-5 containers per node.

Note unless you are within the free tier on your IAAS, the node choices will cost you money.

Service

Create a service,
which is basically your application. There are lots of options you dont need to worry about right now but essentialy:

Specify the docker image and version to use (the latest of the pizzeria repository)

Think of a nickname for the service (pizzeria)

Set how many containers to scale across (1 for now)

Toggle whether to auto deploy updates to the image tag (yes)

Decide whether to expose a port as published, and if that is dynamic or static.
(We will publish port 9010 for our pizzeria).

Deploy

If that works, then you should be forwarded to the final screen where a summary of the service is shown.
Note the Endpoints section, where you shold have a Service and a Container endpoints.
The service endpoint should look something like:

tcp://pizzeria.12abcd34.svc.dockerapp.io:9010

The service endpoint is clickable, but change the protocol from tcp to http.

Note: If you plan to add SSL to your apps by following my
Let's Encrypt with Nginx,
then this service endpoint is the one you need to proxy to.

Stack

Stacks
are not need in this pizzeria example.
But if you were to separate the service into e.g. a back-end, front-end and database,
like my docker compose based example,
then Stacks is where you define the separate services within Docker Cloud.

Alternatives

Spray / Akka HTTP

Heroku

Heroku is a PAAS.
And is the smoothest and quiest way to deploy a pizzeria service to a cloud/hosting provider.
I love Heroku, and run many applications with it, but it is not perfect.
They do support a Docker build flow, but mostly you do not use Docker with Heroku.
Instead you push your code (via Gitremote)
and use their build flow to generate and host their own containers.