Skip to content

Instantly share code, notes, and snippets.

@bradbajuz
Last active March 12, 2019 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bradbajuz/40e444553a824f40e5b57a8ecd1cac57 to your computer and use it in GitHub Desktop.
Save bradbajuz/40e444553a824f40e5b57a8ecd1cac57 to your computer and use it in GitHub Desktop.
part-1-rolling-your-own-heroku-with-dokku

Setting up Heroku like deployment is pretty easy. There are lot of reasons why to do this but a big one specifically is cost. Heroku is expensive compared to a $20 DigitalOcean droplet. Of course, learning how to be a system administrator is required but not at all difficult.

In this series of how-to's, we'll be starting off deploying a Ruby on Rails app using a DigitalOcean droplet, Ubuntu, Docker and Dokku all for $5 a month that can easily be scaled to $20 a month (recommended for production apps).

Setup a Droplet

  1. Don't have a DigitalOcean account, create one.

  2. Create a droplet:

  3. Select the One-click Apps tab:

  • Choose an image - Dokku 0.7.2 on 16.04
  • Choose a size - $5/month for now
  • Choose a datacenter region - Closest location
  • Add a new SSH key
  • Make sure your key is selected
  • Choose a hostname - Sub-domain name or domain name. Affects hostname in Ubuntu (i.e. root@hostname)
  1. Click "Create"

Configure Dokku

  1. Copy the public IP associated with newly created droplet:
  2. Open a new tab in a web browser and paste the IP address in the URL field
  3. The Dokku setup page should be shown:
  4. Update hostname and select to use the virtualhost:
  • Make sure the Public Key is entered in the box
  • Make sure the hostname reflects the same hostname chosen when creating the droplet (i.e. domain.com)
  • Use a domain as is (i.e. domain.com), leave "Use virtualhost naming for apps" unchecked.
  • Use a sub-domain (i.e. blog.domain.com), make sure "Use virtualhost naming for apps" is checked.
  1. Click "Finish Setup"

Update the Droplet

Update Ubuntu, Docker, Dokku and any other tools before deploying any code. Docker and Dokku have pretty significant version updates that should installed before anymore configuration or deployment.

  1. SSH into newly created droplet:
ssh root@<ip-address>
Type 'Yes' and enter to connect
  1. Do a mass update:
apt update
apt upgrade
Type 'Y' to continue
  1. Update left back packages, reboot and remove old packages:
apt dist-upgrade
Type 'Y' to continue
Hit 'Enter' to enter web based configuration for Dokku
shutdown -r now
ssh root@<ip-address>
apt autoremove
Type 'Y' to continue

Create a swap file

Chosen the 512MB size droplet, let's create a swap file.

Note: DigitalOcean doesn't recommend creating a swap files on their virtual servers because heavy swapping can decrease the life and performance of Solid State Drives (SSD). Going to use this droplet in production, upgrade it to at least the 1GB droplet. The 2GB droplet is recommended for production apps.

  1. Setup a 2GB (2048MB) swap file:
fallocate -l 2048m /mnt/swap_file.swap
  1. Update permissions on the swap file:
chmod 600 /mnt/swap_file.swap
  1. Make the swap file a swap file:
mkswap /mnt/swap_file.swap
  1. Turn on the swap file:
swapon /mnt/swap_file.swap
  1. The swap file has to mount after a reboot:
nano /etc/fstab
  1. Type or copy in the fstab file you opened:
# Mount swap file
/mnt/swap_file.swap none swap sw 0 0
  1. Reboot droplet, ssh back in and check to see if swap mounted:
shutdown -r now
ssh root@45.55.148.216
swap on -s

Create a Dokku app

The app name is of choosing but if using a sub-domain name (i.e. blog.domain.com), then name the app the sub-domain name (i.e. blog).

  1. Create the Dokku app:
dokku apps:create appname

(i.e. blog if using a sub-domain) 2. Install a database:

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

Note: We'll be using the official Dokku PostgreSQL plugin, which will install PostgreSQL 9.6 3. Create a database:

dokku postgres:create db_databasename

Note: The name of the database can be of choosing. The name can even be the same as the app name 4. Link database to app:

dokku postgres:link db_databasename appname
  1. See app environmental variables:
dokku config appname

Note: The environmental variable to link the database to the app has been configured automatically

Deploy Rails App

  1. Create a new Rails app or use an existing one

  2. Add the git remote for the droplet (make sure to be in the root directory of the Rails app):

git remote add dokku dokku@droplet-ip:appname

Note: Feel free to customize the the name of the git remote (i.e. git remote add custom name)

  1. Add the Dokku environmental variable name to the app's database.yml under production:
url: <%= ENV['DATABASE_URL'] %>

Should resemble below:

production:  
	adapter: postgresql
	url: <%= ENV['DATABASE_URL'] %> # Created when linking database to app
	encoding: unicode
	pool: 5
  1. Add necessary gems:
ruby '2.3.3'
group :production 
  gem 'rails_12factor'
end
gem 'pg'
gem 'puma'
  1. In the root directory of the Rails app, create a Procfile with the line below added:
web: bundle exec puma -C config/puma.rb
  1. In the root directory of the Rails app, create a CHECKS file with the lines below added:
WAIT=8 # Wait 8 seconds before each attempt
ATTEMPTS=6 # Retry checks 6 times, if it still doesn't work, the deploy has failed and the old container (app) will be kept

Note: Make sure there is a newline (extra line) at the bottom 7. In the root directory of the Rails app, create a puma.rb file with the lines below added:

workers 1 # Change to match your CPU core count. Consumes more RAM
threads_count = Integer(ENV['MAX_THREADS'] || 5) # Consumes more CPU
threads threads_count, threads_count
preload_app!
rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
 # Worker specific setup for Rails 4.1+
 # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
  ActiveRecord::Base.establish_connection
end
  1. Install gems:
bundle install
  1. Deploy to the droplet:
git add .
git commit -m "Commit message"
git push
git push dokku master
  1. Run migrations:
ssh dokku@domainname run dokkuappname rake db:migrate
  1. Access newly created site using the IP address of the droplet:
  • Open a browser and either type or copy and paste the IP address of the droplet in the URL bar and hit "Enter"

Access app with domain or sub-domain instead of IP address

  • Sub-Domain: Add an A record, which will be the sub-domain name that points to the static IP address of the droplet
  • Domain Only: Update the A record of the domain to point to the static IP address of the droplet

Setup Dokku Script

A small script to ease the creation of a dokku app. Change appname to correspond to your app name. To run the script, make sure you give it proper permissions: chmod +x setup_dokku_app.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment