If you’ve ever worked on or thought about creating your own web app using Ruby on Rails, then you’ve probably heard of Heroku.
A child of the famed Y Combinator accelerator program, Heroku provides services that make it dead simple to get a Rails app up and running within minutes in a professional server environment.
There’s a good reason why it’s so popular – they offer a free tier that just works!
While lots of developers feels comfortable with their own code, the thought of fiddling with a server configuration which serves up their magical creations to the hundreds (thousands? bazillions?) of visitors that discovered their site makes their head spin. Heroku fixes this by removing the Ops out of DevOps.
But, what happens when your site needs secure SSL? +$20/month.
How about error logging and reporting? +$15/month.
Backups? More memory? Additional worker processes?
Needless to say, your bill can grow very quickly. As a small business, it’s important that I keep my costs down, especially when I’m just trying to spin apps out before I know if they are ever going to go anywhere.
I wondered to myself. How could I get the ease and features offered by Heroku, but in a package that was more friendly towards my budget?
So I did some searching, and found an even better answer that allows me to host my own Heroku clone on my own server for a measly $5 a month using a DigitalOcean droplet, saving me money and the frustration of receiving an overpriced bill for an app that I’m still working on.
That’s more like it.
Now, in this tutorial, I’ll show you how you can set up your own, too.
Requirements:
30 minutes of time
A credit card and billing address
A sense of courage
INTRODUCING DOKKU
Dokku is a Docker powered mini-Heroku in around 200 lines of Bash that lets you set up your own Platform-as-a-Service infrastructure at a fraction of the cost. This makes it possible for you to host your own apps with all of the features offered by an actual provider like Heroku.
Let’s get going on setting this puppy up.
HOSTING ON DIGITAL OCEAN
For the purposes of this tutorial, we are going to set up the Dokku software on a $5 VPS over at Digital Ocean. It’s a great alternative to traditional shared hosting because it is built on super fast solid state drives and it is very friendly on the wallet.
If you’re new to Digital Ocean, you can sign up through this link and receive a free $10 credit, good for two free months of Dokku hosting.
After you’ve created and logged in to your Digital Ocean account, it’s time to start setting up the server.
Create a New Droplet
DigitalOcean calls its virtual private servers droplets; each droplet that you spin up is a new VPS for your personal use. The setup is very easy – let’s create one now.
Start by clicking the green Create Droplet button at the top of the navigation menu.
Choose an Image: Click on the One-Click Apps tab, and choose Dokku v0.6.5 on 14.04Choose a Size: $5/monthAdd block storage: NoneChoose a Datacenter Region: New York 3Select additional options: NoneAdd your SSH Keys: (Optional) NoneFinalize and Create: 1 droplet, with a hostname of Dokku
Once you’ve selected the options above, click the big green Create button at the bottom of the page.
After about a minute, you should receive an email that contains information related to the new droplet that you just created, including your server’s IP Address and root password. Keep this email handy – in fact, I’d recommend saving that data somewhere in a safe and secure place for future referencing.
CONFIGURING DOKKU
Now that your droplet is up and running, you need to make a few configuration changes to our new Dokku install.
Using your web browser, visit the IP address that you received in the email from DigitalOcean. You should see a page load up that looks similar to this:
The important setting here is the Public Key box. If you opted not to add an SSH key during the droplet creation process, you’ll need to copy your SSH public key and paste it here so that Dokku knows to trust your computer every time that you want to connect and deploy to your Dokku installation
If you’re not sure what an SSH key is, I’d recommend following GitHub’s excellent tutorial on creating an SSH key.Once you have generated your SSH key, make sure to paste it in the Public Key box on your Dokku setup screen.
When you’re ready, click the blue Finish Setup button.
You’ll immediately be forwarded to the Dokku Application Deployment guide, but you can now safely close your browser window, since we’ll be using the CLI to finish setting up and deploying your Rails app.
Getting comfy with your CLI
Note: if you are comfortable accessing servers via shell, you can skip down to the Controlling Dokku from your Computer section below.
Forewarning: remember how I asked you earlier if you were feeling courageous?
This is going to be the part that scares most people away. But you are ready. You can do this. We’re in this together, and with the power of two we can do anything! Besides, all you really need is to be good at following linear instructions.
We’re going to use Terminal or Command Prompt to log in to your Digital Ocean server via Secure Shell.
These programs offer a command-line interface (CLI), which is a means of interacting with your droplet where you’ll issue commands to the droplet in the form of successive lines of text. That’s right baby, no menus or shiny icons here. You’re a real hacker now.
It’s time. Let’s open your CLI and get rockin.
OSX: Terminal is located in the Applications/Utilities folder. Alternatively, you can use Spotlight to search for and open it.Windows: Command Prompt is found in different locations based on the Windows version you have. Here are instructions for Windows 8, Windows 7, Windows Vista, and Windows XP
You’ll know you’re ready to go when that big, scary, empty black box pops up. For the remainder of this tutorial, we’ll call this box the CLI.
Controlling Dokku from your Computer
A quick note: the sections below using a convention of highlighting text to show what you must enter into your CLI. If you see text that looks like this, it means that you should literally type like this into your CLI and press enter.
One of the nice things about Heroku is its integration with the Heroku Toolbelt – a set of CLI tools which allow you to issue commands to manage your Heroku install via your CLI without having to manually log in to the server every time.
To replicate this behavior with Dokku, you’ll want to install the dokku-cli gem on to your computer, which will provide your computer with some Dokku controls and superpowers that it doesn’t ship with by default.
Note: if you’re using Windows, you may need to first install Ruby to get this to work. Here’s a detailed description on the steps you should take to get Ruby set up
Open up your CLI and enter the following command to install it:
gem install dokku-cli
Your CLI will show you some cool information to prove to you that it is up for the challenge of installing our new gem. Once it finishes yelling at you, you can verify that the dokku-cli
app installed correctly by typing the following command into your CLI:
dokku
Do you see a bunch of dokku-cli
commands listed (such as dokku certs:add CRT KEY
and dokku events
) and no errors? SWEET!!! Let’s move on.
GETTING RAILSY WIT IT
Okay, so we have Dokku set up, just waiting in the bleachers to catch a home run ball (or, your Rails app.) We’re just about ready to send your Rails app up to the Dokku server.
What’s that? You don’t have a Rails app ready to go? Well, you can use a sample one for now, I guess. Heroku actually provides one on their GitHub account for demonstration purposes. You can download it to your local system with the following command:
cd ~ && git clone git@github.com:heroku/ruby-rails-sample.git
Note: not sure what Git is, or, don’t have it installed? Check out this article from GitHub which provides and overview of Git and a walkthrough on getting it installed on your computer.
This will create a new folder called ruby-rails-sample
in your user’s home directory, which contains a demo Rails app that you can use for the remainder of this tutorial.
Initializing your Dokku app
Now it’s time to introduce our new friend Dokku to our old friend Rails app. Let’s use the CLI to connect to our droplet with the following command, replacing your.droplet.ip.address
with your actual DigitalOcean droplet IP address:
ssh root@your.droplet.ip.address
This will start a new SSH session on your Droplet, which provides you with full control over the Dokku install. Once you’re logged in, you’re essentially using the Droplet’s CLI at this point, so let’s tell the Droplet’s Dokku install to create a new app called ruby-rails-sample
(or, whatever else you want to call your app):
dokku apps:create ruby-rails-sample
You did it! …didn’t you?
Installing Postgres
One of the main benefits of using Rails to create your web apps is ActiveRecord, a super easy-to-use abstraction layer which allows you to write code that talks to your database and fetches or writes the data that you’re looking for.
Obviously, in order to use ActiveRecord to access our database, we need to first create a database. I know, I’m a genius.
In order to create our database, we’ll install a plugin for Dokku which allows us to use Postgres as the database software. Any time we install a plugin in Dokku, we need root/admin privileges, so we’ll prefix the following command with a call to sudo
:
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git
Note: any command that begins with sudo may ask you to enter your root password after issuing the command. This password can be found in the email that you received from Digital Ocean.You might not see the traditional ****** or ••••••• characters when you type or paste your password into your CLI, but it is still being pasted successfully.
Dokku will do its thing and spew out a lot of information while it downloads and installs the Postgres plugin. Once it’s done, let’s create a new Postgres service with the name rails-database
(or, you can also call this whatever you want)
dokku postgres:create rails-database
Finally, we’ll link our new Postgres service that we just created to our ruby-rails-sample
app that we created in the previous step. This will also automatically set the POSTGRES_URL
environment variable on your dokku host, so that dokku knows how to connect to the database when your Rails app tells it to.
dokku postgres:link rails-database ruby-rails-sample
BAM! Our Postgres database is ready to rock and base our data.
Note: If you’re using a custom Rails app instead of the example app provided by Heroku, you’ll need to make sure that your database configuration is set to use Postgres in production instead of the default SQLite. Heroku has an excellent tutorial article which walks you through making this change.
Add a swap file
How are you feeling? Ready to take over the world with your CLI skills? Maybe hack a matrix or two? Good. Let’s move on.
Rails apps require a decent amount of memory to run efficiently, but our $5 DigitalOcean droplet only comes with 512MB – not nearly enough to support our app’s deployment, processing, and traffic.
To get around this, we can create a file on the server’s hard drive called a swap file which will write some of the contents of the server’s memory to a file instead of storing it in RAM. Let’s not get too technical; here’s how to create your swap file:
First, allocate a new 2GB file with the following command:
sudo fallocate -l 2G /swapfile
You won’t see any output after this command; that’s good. It means that it worked. Now, let’s modify the permissions of the new file so that it can be used by your server with this command:
sudo chmod 600 /swapfile
Again, no output this time. Excellent. Next, let’s prepare the swap file for… swapping. Enter this:
sudo mkswap /swapfile
You should see some output that resembles the following:
12Setting up swapspace version 1, size = 2097148 KiB
Now, we need to enable swap on the swap file. You read that right. Enter this command:
sudo swapon /swapfile
Lastly, let’s make sure the swap file is always used, even after we restart the server. We’re going to do this with a program called nano (cute, right?), which is a virtual text editor that will take over your CLI screen and transform it to a working application.
Let’s open the configuration file in nano by issuing this command.
sudo nano /etc/fstab
Although this window looks a little different from a traditional text editor like Microsoft Word, it actually behaves very similarly. You can use the arrow keys on your keyboard to move the cursor around in the text file and make changes.
Finally, use your down arrow key to move the cursor to the bottom of the screen and add the following line:
/swapfile none swap sw 0 0
Phew, we’re done here! Press CTRL+X to save the configuration file, press Y to confirm your changes, and then Return to return to your Digital Ocean droplet.
At this point, we’re all done with our droplet, so it’s time to disconnect with this command:
exit
SETTING UP GIT AND DOKKU
We’re in the home stretch. Can you taste it? Victory is upon us.
At this point, dokku-cli
doesn’t know anything about the Droplet that you created on DigitalOcean. Let’s introduce the two to each other so they can form a lifelong relationship and maybe go on a dinner date.
First, make sure you are inside of the root directory of your app by changing to it with the following command, replacing ruby-rails-sample
with the name of your actual Rails app name.
cd ~/ruby-rails-sample
dokku-cli
will look at the initialized Git repository that exists inside of your Rails root directory and reference the remote named dokku
for the correct connection information to your droplet.
Since your repository doesn’t currently have a dokku
remote, create it with the following command, replacing the IP address with your DigitalOcean droplet IP that you received after creating your droplet.
git remote add dokku dokku@your.droplet.ip.address:ruby-rails-sample
Upload your Rails app to your Droplet
We’re at the last command, but it’s arguably the most important. Your Rails app needs to be uploaded to your droplet so that you can access it from anywhere in the world!
Deploying your app is as simple as pushing it up to GitHub. Dokku has some receive hooks set up that are listening for any connections through Git and will know how to handle those requests, so all we have to do is push our master branch to the dokku remote. Easy enough with this command:
git push dokku master
You should start to see some output that looks similar to this:
1234567891011121314Counting objects: 231, done. Delta compression using up to 8 threads. Compressing objects: 100% (162/162), done. Writing objects: 100% (231/231), 36.96 KiB | 0 bytes/s, done. Total 231 (delta 93), reused 147 (delta 53) -----> Cleaning up...-----> Building ruby-rails-sample from herokuish...-----> Adding BUILD_ENV to build environment...-----> Ruby app detected-----> Compiling Ruby/Rails...=====> Application deployed: http://your.droplet.ip.address:27749
Wait… that’s it? Pretty amazing, huh?
Try holding the command key and double-clicking the droplet url that Dokku reports back in the CLI after a successful deployment. You should see your app running – congrats! You’ve successfully deployed to a Dokku server in 30 minutes or less!
Touchdown!
YES! We are all done here. I knew you could do it, champ. Close down that CLI and revel in your success.
Questions or comments? Use the comments below or hit me up on Twitter, @davekiss
MAKING IT EVEN BETTER
What’s this? You’re still reading, even after you’ve scored the game winning goalsportshomerun? Well, together, we can make your app and deployment process even better with a few more tweaks. Read on, if you so choose.
Configuring Pre-Flight Checks
Any time you deploy your Rails application to your DigitalOcean droplet, Dokku will restart your server to ensure that what is being delivered to your users is all up to date with the latest version.
However, this can become problematic; while Dokku checks to make sure your application container is up and running correctly, by default, it doesn’t actually check to see if your Rails server has been launched safely. What this means is that while Dokku may report in as successfully restarting your container, your users may see temporary errors indicating otherwise while your Rails app continues to boot.
Let’s resolve this by creating a file named CHECKS
in our Rails root and add some instructions for Dokku to follow to verify the Rails server has finished loading after deployment:
1234WAIT=10 ATTEMPTS=6 /check.txt it_works
Now, we need to create a custom route in our config/routes.rb
file that handles requests to the /check.txt
endpoint. Add the following route, which will return the it_works
text that our CHECKS
file is expecting:
get '/check.txt', to: proc {[200, {}, ['it_works']]}
Let’s break this all down:
We set the WAIT
value to 10
to wait 10 seconds before checking since the app takes a little while to boot.If after 6 ATTEMPTS
the Dokku check continues to fail, Dokku will revert back to the previous app version and consider the deployment as failed.Dokku will hit the /check.txt
route, and if it received it_works
as the response, the deploy will be considered successful.
Add and commit your changes to Git, then push it up to Dokku. You’ll see some output similar to the following:
123456-----> Running pre-flight checks-----> Attempt 1/6 Waiting for 10 seconds ... CHECKS expected result: http://localhost/check.txt => "it_works"-----> All checks successful!
Nice work! Your app now implements zero-downtime deployments.
Automatic Database Migrations
By default, any changes that you make to your Rails app database require that you manually run rake db:migrate
to process your migration files and apply your changes to your database.
We can ensure that Dokku does this automatically for you when you deploy by creating an app.json
file in your Rails app root, which Dokku will look to for instructions on what it should do when you deploy your App.
Let’s create a file named app.json
in the root of your Rails app and add the following instructions:
1234567891011121314{ "name": "ruby-rails-sample", "description": "My awesome Rails app, running on Dokku!", "keywords": [ "dokku", "rails" ], "scripts": { "dokku": { "postdeploy": "bundle exec rake db:migrate" } }}
This is telling dokku that after your deploy is successful, run bundle exec rake db:migrate
automatically to handle any changes you made to your database between app versions. Noice!
Setting up your domain name
Now that you have your droplet and app ready to go, chances are likely that you want to hook up a real domain name to visit instead of just an IP address.
To do this, you’ll need to make some DNS changes on your domain registrar’s site and on DigitalOcean. This might be GoDaddy, HostGator, Hover, NameCheap, BlueHost, or even somewhere else.
Check out the following article for detailed instructions on how to set up your domain name to point to your new Rails app running on Dokku