Ruby on Rails Deploy Explained: Deploy to Dokku

Sinopsis

This article is the third from the Ruby on Rails deploy explained series. In the previous article we set our application to conform to the 12 factor rules and now it can be easily pushed to Heroku, or, as shown in this guide, – to Dokku - your own, cheap and fairly fancy PaaS.

Installation

There are a lot of tutorials for that. However, I'll try to give you some instructions beyond them and touch all the gotchas.

It's better if you already have the domain name. If you don't, it would be nice to know what it can be. In the latter case, you can temporary add it to /etc/hosts:

your.server.ip.addr yourdomain.com

Now, pick up a hosting account on Digital Ocean or anywhere else and let's go. First of all, get an instance with 2GB RAM or more. If you choose a droplet with less than 2 GB of RAM you may experience troubles with it. Fortunately, it's not expensive. I suggest you to:

  • Use your FQDN as a hostname for that instance.
  • Do not take predefined Dokku image unless you just want to play.
  • Use Ubuntu 14.04 x64.
  • Uncheck IPv6 checkbox on Digital Ocean, because there are some known issues with IPv6 on Digital Ocean and Docker.

Log in to your droplet via ssh:

$ ssh root@yourdomain.com

I used to install dokku-alt - a main fork of the original dokku. But a lot of problems in upstream have been fixed and upstream seems to be much better maintained at present. So we'll use the main one.

To install it, run:

$ wget https://raw.github.com/progrium/dokku/v0.4.0/bootstrap.sh
$ sudo DOKKU_TAG=v0.4.0 bash bootstrap.sh
or whatever version is the latest now 

At the end the script will suddenly hang and will suggest you to open browser at some URL. Ignore it and hit Ctrl+C.

For Amazon Linux users

I have mentioned, that you should use Ubuntu. So, in your case it will look like installed but you will run out of free space on disk very fast.

Dokku works on Docker (which will be explained later) and Docker uses a copy-on-write file system. By default, it brings AUFS with it but requires a kernel rebuild. You may not like this or you may not have such an option, for example, on Amazon Linux. But there is a good alternative for you: use BTRFS. This section is about YMMV, so I leave you with that wiki. Come back!

Swap

On Digital Ocean, as well as on many other cloud providers, swap is disabled by default. If you took a box with less than 2GB, you may run out of memory. I advise you to enable swap: execute the following (it will create 512MB swap file and you can adjust it as you want):

cd /var
touch swap.img
chmod 600 swap.img

dd if=/dev/zero of=/var/swap.img bs=1024k count=1000
mkswap /var/swap.img
swapon /var/swap.img
free

echo "/var/swap.img    none    swap    sw    0    0" >> /etc/fstab

Initial configuration

Place the initial configuration:

$ cd /home/dokku
$ echo "yourdomain.com" > VHOST
$ echo "yourdomain.com" > HOSTNAME

The first domain is the one which is used in nginx vhost configurations and it is very important. The second - is just a domain name that will be used for newly deployed applications by default.

Install needed plugins

In practice, the database is necessary. What does your app require – Postres, MySQL, MariaDB, Redis...? Check the plugin list and install whatever you need. For instance, Postgres:

$ dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres

SSH

Now put your ssh key there:

locally
$ cat ~/.ssh/id_rsa.pub | ssh root@yourdomain.com "sudo sshcommand acl-add dokku $USER"

Time to deploy!

Your app is ready, Dokku is ready and now deploy goes like a breeze.

$ git remote add staging dokku@yourdomain.com:staging
or production
$ git push staging master

The staging at the end of line works as an application name in dokku. I highly encourage you to have the same name for git remote and for app name. Your app will be available at staging.yourdomain.com.

Talk to dokku

Dokku installs fairly special .ssh/authorized_keys so that you can call dokku commands from your local machine. To do this, log in via ssh to the machine as a dokku user. For example:

$ ssh dokku@yourdomain.com apps:list
locally is an equivalent to
$ dokku apps:list
on remote server

You may also want to look at Dokkufy.

From here, I'll provide commands as dokku something, assuming that you know how to run them from your developer machine.

Database

There is no doubt that your app has a database. After the first deployment it will most likely fail. This can be easily fixed if you have installed a database plugin on an appropriate step. For Postgres:

dokku postgres:create staging-database
dokku postgres:link staging-database myapp
dokku run staging rake db:create db:migrate

That's it. And check your app, at this point it works.

Other configuration

Do you remember that you moved it to environment variables? Now you can provide such variables for the process:

dokku config:set staging STRIPE_API_KEY=somesome STRIPE_API_SECRET=secretsecret

Periodical tasks, cron

Some options here:

I'd stick with Sidetiq.

Use top-level domain

It is easy, as it is:

$ dokku domains:set staging yourdomain.com

You can even use another domain if it is pointing to the same server: either via A or via CNAME.

Management

You already saw dokku run:

$ dokku run staging rake db:migrate
$ dokku run staging rails console
it will run interactively

You can do much more: run dokku without arguments and learn. A useful thing is:

$ dokku logs staging -t

Redeploy/deploy for new developers

It's easy:

Once on your machine
$ curl https://github.com/new-developer.keys | head -1 | ssh root@yourdomain.com "sudo sshcommand acl-add dokku <new-developer>"
Once on new developer machine
$ git remote add staging dokku@yourdomain.com:staging
The deploy/redeploy
$ git push staging master

Conclusion

With Dokku, you can deploy application by yourself without much knowledge and without involving an admin. You may control all aspects of the setup, have proper tools to monitor everything and be happy.

Later on, we will discuss how it works, how to scale it and other interesting things.