Deploying Rails application with Dokku

Posted on 2020-02-01 by Karol Bąk Comments
ruby
rails
dokku
devops

Heroku, AWS, Google Cloud are great services for hosting Rails application but they are expensive. If you are developing a small app, kicking off a startup or just playing with Rails you can use cheaper solutions - cloud hosting, like DigitalOcean or Upcloud. The problem is the setup - you need to install dependencies on your own. Then deploy your application manually or using for example capistrano, which also requires a lot of setup. What if we had self-hosted heroku?

About dokku

Dokku is a simple PaaS that allows you to easily deploy your application. It’s a great solution if you want to save some money and use cheap cloud providers instead of heroku or AWS. Dokku will handle whole app setup for us. In this article I’ll show how to deploy Rails app with postgres, sidekiq and redis. We’ll secure our app with SSL using Let’s Encrypt certificate. It will be even easier if you are familiar with heroku.

Getting started

First of all we need a server with a debian or ubuntu installed. I’ll use 1 CPU / 1 GB RAM machine on DigitalOcean.

Connect to your machine via SSH as a root and install dokku:

wget https://raw.githubusercontent.com/dokku/dokku/v0.28.1/bootstrap.sh
DOKKU_TAG=v0.28.1 bash bootstrap.sh

Please take a look at dokku documentation for newest version.

Installation can take up to few minutes. After it’s done, add your public ssh key:

Copy if from ~/.ssh/authorized_keys if it’s already there:

cat ~/.ssh/authorized_keys | dokku ssh-keys:add admin

or add a new one:

echo 'CONTENTS_OF_ID_RSA_PUB_FILE' | dokku ssh-keys:add admin

Setting up the application

Now let’s create an app. In my case it will be mytestapp. Just replace it with your app’s name:

dokku apps:create mytestapp

To avoid setting up all dependencies manually we’ll use heroku buildpacks (isn’t it great?!):

dokku buildpacks:add mytestapp https://github.com/heroku/heroku-buildpack-nodejs.git
dokku buildpacks:add mytestapp https://github.com/heroku/heroku-buildpack-ruby.git

Setup all necessary envs:

dokku config:set mytestapp RAILS_ENV=production
dokku config:set mytestapp RAILS_MASTER_KEY=your_master_key

Dokku uses Procfile to determine what processes should be running. So if you don’t have one, create a file called Procfile with following content:

web: bundle exec puma -C config/puma.rb

Database

Now let’s focus on database. The easiest way to install postgres is to use dokku plugin:

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

Now link postgres database to the app:

dokku postgres:link mytestapp_db mytestapp

It will set DATABASE_URL env variable (same as heroku postgres).

If you want to run migrations automatically after deploy add following line to the Procfile:

release: bundle exec rails db:migrate

SSL

Now it’s the time to add a domain and setup SSL. We’ll need to add both non-www and www version of the domain.

dokku domains:add mytestapp test.kukicola.io
dokku domains:add mytestapp www.test.kukicola.io

Now we can install Let’s Encrypt plugin and generate certificate.

dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
dokku config:set --no-restart mytestapp [email protected]
dokku letsencrypt:enable mytestapp

Since Let’s Encrypt certificates are valid only for 3 months we can add a cron job to automatically renew them:

dokku letsencrypt:cron-job --add

Deploy

We are ready to deploy our app! It’s the same as on heroku. First we need to add remote repository:

git remote add dokku dokku@IP_ADDRESS:mytestapp

Then we can deploy our app:

git push dokku master

Now our app should be up and running! By default dokku will run 1 instance of web process. We can change with following command:

dokku ps:scale mytestapp web=2

Sidekiq, background processes

If your app is using sidekiq or any other background processes you need to add additional commands to Procfile. For example:

worker: bundle exec sidekiq -C config/sidekiq.yml

In order to use sidekiq you need redis. You can install it in the same way as postgres:

dokku plugin:install https://github.com/dokku/dokku-redis.git redis
dokku redis:create mytestapp_redis
dokku redis:link mytestapp_redis mytestapp

Remember that dokku will not spawn any non-web instances by default so after deploy run:

dokku ps:scale mytestapp worker=1

You don’t need to do it every time. Dokku will remember the number of instances between builds.

Summary

So as you can see deploying Rails application with dokku is very easy. After short setup it can be a great substitute for heroku. Unfortunately it has one big disadvantage - it’s a single server solution, so if you need high scalability it may not be the best option. Let me know in comments if you had any problems with deploying your app. If you would like to read more take a look at Dokku docs.