Header

Run your own PaaS with RunAbove and Dokku

Last time, we looked at how we can run a Play application on Open Shift. Open Shift offers small instances (512MB memory) for free, but if you need more memory, it quickly gets rather expensive. For 1GB, the hour costs you 5 cents (that’s about 36$ per month). That’s too much for my hobby projects, so I started looking for alternatives. My requirements included 1GB of memory, a relational database that can hold more than just a few megabytes of data and ideally a deployment that isn’t any more work than a git push.

Unfortunately, I couldn’t find a PaaS provider that fit my needs, but I remembered reading about Dokku, the “Docker powered mini-Heroku. The smallest PaaS implementation you’ve ever seen”. Last week, I also learned about RunAbove, and that they not only offer really cheap machines, but also have pre-configured Dokku images (which I later realized isn’t such a big deal because it’s really simple to install):

If you search for runabove code on Twitter, you’ll find many discount codes that give you a $10 credit, so you can try this for free. After signing up, add a new instance:

runabove-setupThe next step will ask you for an image – choose Ubuntu 14.04 (we’re not using the predefined Dokku image because its version of Dokku is a bit dated) – an SSH key, a name, and a few seconds later your machine will be provisioned.

runabove-machinesOne neat thing our PaaS will be able to do is hosting applications on sub-domains, without having to change any DNS entries. But for this to work, we first need a domain name and a wildcard DNS entry. Don’t worry if you don’t have a spare domain name lying around, you can get one for free at Freenom. During the registration, you can choose a custom  DNS server. For example, Zonomi offers you one DNS zone for free and it allows wildcard DNS entries. Now, the setup of all this seems to resemble the chicken-egg problem: Freenom asks for the DNS server and Zonomi asks for the Domain, but in the end it all works out, just enter the configuration. I went with the domain ownpaas.tk (use the Register a Free Domain Now button at the bottom):

freenom-setup

On Zonomi, setup your domain with a wildcard for the subdomains and enter the IP address of your RunAbove instance:

zonomiAfter a few minutes, you can try to ping your domain and you’ll see that the address is resolved to the correct instance. The Ping won’t work though, because the default RunAbove network configuration doesn’t allow it. But you can ssh into your  server now:

% ssh admin@ownpaas.tk

If you can’t, you need to inspect your RunAbove network settings. Switch to Expert Mode (in the top right menu), go to Access & Security and edit your default rules. There are pre-defined rules, just add the one for SSH and while you’re at it also for HTTP.

runabove-securityThe next step is to install Dokku. Just follow their instructions on how to install the latest stable version.

% ssh admin@ownpaas.tk
admin@my-own-paas:~$ # follow the instructions
...
Almost done! For next steps on configuration:

https://github.com/progrium/dokku#configuring

If you don’t end up with the above message, just run the command again until you do. I needed three attempts… Now, we need to update the Buildpacks that Dokku uses. Buildpacks exist for many languages and frameworks and provide the framework specific configuration to Dokku (actually, they come from Heroku, but Dokku uses the same configuration).

% ssh admin@ownpaas.tk
admin@my-own-paas:~$ git clone https://github.com/progrium/buildstep.git
admin@my-own-paas:~$ cd buildstep
admin@my-own-paas:~$ sudo make build

Next, update the hostname so that Dokku knows how to deploy your applications to subdomains. Back on your local machine, copy your public key to the server and authorize it to use Dokku.

admin@my-own-paas:~$ sudo sh -c "echo ownpaas.tk > /home/dokku/HOSTNAME"
admin@my-own-paas:~$ sudo sh -c "echo ownpaas.tk > /home/dokku/VHOST"
admin@my-own-paas:~$ logout
Connection to ownpaas.tk closed.
% cat  ~/.ssh/id_rsa.pub | ssh admin@ownpaas.tk "sudo sshcommand acl-add dokku $USER"

Ok, now let’s create and deploy a Play application to our PaaS:

% activator new play-scala play-scala
% cd play-scala/
% git init
% git add .
% git commit -a -m "init"
% git remote add dokku dokku@ownpaas.tk:play-scala
% git push dokku HEAD
Counting objects: 30, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (25/25), done.
Writing objects: 100% (30/30), 1010.68 KiB | 0 bytes/s, done.
Total 30 (delta 0), reused 0 (delta 0)
-----> Cleaning up ...
-----> Building play-scala ...
-----> Adding BUILD_ENV to build environment...
-----> Play 2.x - Scala app detected
-----> Installing OpenJDK 1.6...done
-----> Downloading SBT...done
-----> Priming Ivy cache (Scala-2.11, Play-2.3)... done
-----> Running: sbt update
...
-----> Creating non-ssl nginx.conf
-----> Running nginx-pre-reload
       Reloading nginx
=====> Application deployed:

http://play-scala.ownpaas.tk

And that’s it! The domain name is determined by the name of the remote repository. Next time, we’ll deploy a slightly more interesting application that uses a database!

No comment »
Header

Play 2.3 Applications on OpenShift

This is a quick how-to guide to get your Play 2.3 applications up and running on RedHat’s OpenShift PaaS. OpenShift unfortunately doesn’t support Play out of the box, and there are some pitfalls that can be quite annoying.

Why OpenShift?

As I said, OpenShift – contrary to many other PaaS providers like CloudBees or Heroku – does not support Play directly, but you can use a third-party “cartridge” (that’s what they call the set of scripts and the initial template) to run Play. So why OpenShift? For a pet project, that I wanted to run as cheaply as possible, I needed a database with more than the usual 5MB / 10k rows you get with most free PaaS offerings. On OpenShift, you simply get 1GB of total storage, including your database.

Getting Started

First you need to create a new application from scratch and choose an URL for your application. Fortunately, we don’t actually have to start from scratch but can  use Michel Daviot‘s  OpenShift Play Framework Cartridge. Leave the Source Code field empty, but set the Cartridge to the following URL: http://cartreflect-claytondev.rhcloud.com/reflect?github=tyrcho/openshift-cartridge-play2.

openshift-create-new-application

Let OpenShift create the application and take a break. Seriously, it will take up to ten minutes to create the application. And even if the application overview page tells you that the application is ready, it might still need some additional time until it’s actually up and running. The primary reason is most likely that the underlying VMs just aren’t that powerful and don’t have that much RAM (512MB), and also that SBT initially needs to download Play and all its dependencies.

openshift-application-overview

In the end, you should be able to access your new application:

openshift-welcome-to-play

That’s wasn’t too hard, but the application isn’t very useful yet. In the next step, we are going to replace the Hello World template with an actual Play application.

Replacing the Template Application

Now let’s replace the template with an actual application. We’re going to run the Activator Play Slick Demo, so we need to first clone that repository. Then we add the OpenShift repository as a new remote (you will  find the URL in the application overview page).

git clone https://github.com/loicdescotte/activator-play-slick.git
git remote add openshift ssh://XXX@playslick-mstocker.rhcloud.com/~/git/playslick.git/
git push -f openshift HEAD

When you push the new code, you’ll see OpenShift compile your code:

Counting objects: 46, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (41/41), done.
Writing objects: 100% (46/46), 8.09 KiB | 0 bytes/s, done.
Total 46 (delta 15), reused 0 (delta 0)
remote: Building git ref 'master', commit 4e8c09a
remote:
remote: [info] Loading project definition from /var/lib/openshift/53bcfe2c500446884400021a/app-root/runtime/repo/project
remote: [info] Set current project to activator-play-slick (in build file:/var/lib/openshift/53bcfe2c500446884400021a/app-root/runtime/repo/)
...
remote: [success] Total time: 162 s, completed Jul 9, 2014 8:29:16 AM
remote: Preparing build for deployment
remote: Deployment id is 9a7ca0fe
remote: Activating deployment
remote:
remote:
remote: -------------------------
remote: Git Post-Receive Result: success
remote: Activation status: success
remote: Deployment completed with status: success
To ssh://53bcfe2c500446884400021a@playslick-mstocker.rhcloud.com/~/git/playslick.git/
 + a6011c5...4e8c09a HEAD -> master (forced update)

Building the application succeeded, but it won’t work:

openshift-unavailable

Fortunately, we can log into the VM. The exact ssh command is listed on the application overview, beneath the clone URL. The most interesting file on the VM is probably the log file, which you can find at play2/logs/play.log. The play2 directory also contains the scripts and hooks. To figure out how OpenShift will start and stop your application, take a look at play2/bin/control.

[playslick-mstocker.rhcloud.com]\> ls play2/
bin  env  hooks  logs  metadata  README.md  template

[playslick-mstocker.rhcloud.com]\> ls play2/logs
play.log

[playslick-mstocker.rhcloud.com]\> ls play2/bin
control  install  setup

This gives a clue why the application doesn’t work:

[playslick-mstocker.rhcloud.com]\> less play2/logs/play.log
nohup: failed to run command `target/universal/stage/bin/play': No such file or directory

[playslick-mstocker.rhcloud.com]\> head play2/bin/control
#!/bin/bash -e

function start {
    cd $OPENSHIFT_REPO_DIR
    # build on first time
    [ -d target ] || build
    rm -f target/universal/stage/RUNNING_PID
    nohup target/universal/stage/bin/play -Duser.home=${OPENSHIFT_DATA_DIR} -Dhttp.port=8080 -Dhttp.address=${OPENSHIFT_PLAY2_IP} -DapplyEvolutions.default=true -Dconfig.resource=openshift.conf -mem 512 > $OPENSHIFT_PLAY2_LOG_DIR/play.log 2>&1 &
}

OpenShift (or rather, the cartridge we used) expects that the project is called play, but ours is activator-play-slick. We can either modify the control script or rename your project; I simply renamed the project name in the build.sbt. We can also see that the control script uses the openshift.conf file for the configuration, which doesn’t exist yet. So let’s create the conf/openshift.conf file in your repository and have it include the main configuration, so that we can overwrite OpenShift specific parts later on:

include "application"

There’s one last thing we need to do: the application uses play-slick to auto-generate the evolutions, but this doesn’t seem to be working when we run the staged application. To generate the evolution, we can simply run sbt test (if you know a direct way to run the play-slick DDL plug-in, please let me know). Now commit the generated conf/evolutions folder, the openshift.conf file and the changes to the build file to the repository. Push the changes to OpenShift, take another coffee and now we should see the application.

openshift-kitty

Using MySql instead of H2

As a final step, let us replace the default H2 database with MySQL. On the application overview page, add the MySQL Cartridge to your application. This will again take some time, but in the end it will give you the connection details. You don’t have to write this down because it will be provided to your application through environment variables. Add the following configuration to your openshift.conf:

db.default.slick.driver=scala.slick.driver.MySQLDriver
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://"${OPENSHIFT_MYSQL_DB_HOST}":"${OPENSHIFT_MYSQL_DB_PORT}"/"${OPENSHIFT_APP_NAME}
db.default.user=${OPENSHIFT_MYSQL_DB_USERNAME}
db.default.password=${OPENSHIFT_MYSQL_DB_PASSWORD}

Also, don’t forget to add the MySQL driver to your build.sbt:

libraryDependencies ++= Seq(
  "org.webjars" %% "webjars-play" % "2.2.2",
  "com.typesafe.play" %% "play-slick" % "0.7.0-M1",
  "mysql" % "mysql-connector-java" % "5.1.30")

Now it gets a bit ugly: the H2 database definition is not compatible with MySQL, and I haven’t figured out how to just run the play-slick DDL generation, so we just adapt the schema by hand:

create table CAT (name TEXT NOT NULL, color TEXT NOT NULL);

Commit and push those changes, wait a moment and now your data will be stored in MySQL!

I hope this guide was useful, and I’d be happy to hear your experiences in running Play applications on OpenShift.

10 comments »
Header

Detecting and Naming Boolean Parameters

After a recent discussion on the Scala-Internals mailing list on the pros and cons of methods that take boolean arguments, the consensus was that they should always be passed as named arguments. The compiler doesn’t enforce this, so it’s up to us IDE and tools developers to provide a solution. The code-analysis branch for the Eclipse Scala IDE can now warn you of such boolean arguments that are passed to Scala methods:

The warning comes with a quick-fix that inserts the parameter name:

Of course, the competition isn’t sleeping either, the IntelliJ Scala plug-in just got a bunch of new Intentions.

6 comments »
« Older