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).
-
Don't have a DigitalOcean account, create one.
-
Create a droplet:
-
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)
- Click "Create"
- Copy the public IP associated with newly created droplet:
- Open a new tab in a web browser and paste the IP address in the URL field
- The Dokku setup page should be shown:
- 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.
- Click "Finish Setup"
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.
- SSH into newly created droplet:
ssh root@<ip-address>
Type 'Yes' and enter to connect
- Do a mass update:
apt update
apt upgrade
Type 'Y' to continue
- 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
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.
- Setup a 2GB (2048MB) swap file:
fallocate -l 2048m /mnt/swap_file.swap
- Update permissions on the swap file:
chmod 600 /mnt/swap_file.swap
- Make the swap file a swap file:
mkswap /mnt/swap_file.swap
- Turn on the swap file:
swapon /mnt/swap_file.swap
- The swap file has to mount after a reboot:
nano /etc/fstab
- Type or copy in the fstab file you opened:
# Mount swap file
/mnt/swap_file.swap none swap sw 0 0
- Reboot droplet, ssh back in and check to see if swap mounted:
shutdown -r now
ssh [email protected]
swap on -s
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).
- 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
- See app environmental variables:
dokku config appname
Note: The environmental variable to link the database to the app has been configured automatically
-
Create a new Rails app or use an existing one
-
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)
- 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
- Add necessary gems:
ruby '2.3.3'
group :production
gem 'rails_12factor'
end
gem 'pg'
gem 'puma'
- In the root directory of the Rails app, create a Procfile with the line below added:
web: bundle exec puma -C config/puma.rb
- 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
- Install gems:
bundle install
- Deploy to the droplet:
git add .
git commit -m "Commit message"
git push
git push dokku master
- Run migrations:
ssh dokku@domainname run dokkuappname rake db:migrate
- 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"
- 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
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