Host Your Sinatra App on Heroku
Have a Sinatra app you just wrote that you're dying to publicly showcase or put to use online? Or perhaps you made one a while ago and have been delaying hosting it on Heroku because of the possible headache the process will be? In either case, you've come to the right place, and the goal of this blog is to get you up and running, hosting your Sinatra app on Heroku in about 30 minutes.
Heroku Setup
- You'll need to create a Heroku account
- Install Heroku CLI : https://devcenter.heroku.com/articles/getting-started-with-ruby#set-up
- Login to to Heroku from Heroku CLI (heroku login)
Your git and Heroku accounts will now be sync.
Additionally, Heroku provides great documentation and a walkthrough on these steps here.
Update Your Database
Unless you built your Sinatra with a Postgres database, Sinatra comes out of the box with Sqlite3 database. Heroku is compatible with the former, not the latter, so if you have a Sqlite3 database, you'll need to switch it to Postgres. Here's how:
Environment.rb
My original file looked like this:
ENV['SINATRA_ENV'] ||= "development" require 'bundler/setup' Bundler.require(:default, ENV['SINATRA_ENV']) ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database => "db/#{ENV['SINATRA_ENV']}.sqlite" ) require_all 'app'
Then I added both a test database and production database with the following code. You can omit the test database if you want:
require 'bundler/setup' Bundler.require configure :test do ENV['SINATRA_ENV'] ||= "test" require 'bundler/setup' Bundler.require(:default, ENV['SINATRA_ENV']) ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database => "db/#{ENV['SINATRA_ENV']}.sqlite" ) end configure :development do ENV['SINATRA_ENV'] ||= "development require 'bundler/setup' Bundler.require(:default, ENV['SINATRA_ENV']) ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database => "db/#{ENV['SINATRA_ENV']}.sqlite" ) end configure :production do db = URI.parse(ENV['DATABASE_URL'] || 'postgres:///localhost/mydb') ActiveRecord::Base.establish_connection( :adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme, :host => db.host, :username => db.user, :password => db.password, :database => db.path[1..-1], :encoding => 'utf8' ) end require_all 'app'
Initially made all three databases with Postgres, and created test and development databases locally for this. I had several issues when I first tried hosting to Heroku, so I swapped SQLite back in for the test and development DBs. If you want to use postgres for all three, the code in the environment.rb will look like this.
require 'bundler/setup' Bundler.require configure :production, :development, :test do db = URI.parse(ENV['DATABASE_URL'] || 'postgres:///localhost/mydb') ActiveRecord::Base.establish_connection( :adapter => db.scheme == 'postgres' ? 'postgresql' : db.scheme, :host => db.host, :username => db.user, :password => db.password, :database => db.path[1..-1], :encoding => 'utf8' ) end require_all 'app'
You can see both (with comments) in my repo on Github.
Database.yml
If you do not have one already, you'll want to create a database.yml file in your config directory, adding your databases in the following format:
development: adapter: sqlite3 database: db/development.sqlite3 pool: 5 timeout: 5000 test: adapter: sqlite3 database: db/test.sqlite3 pool: 5 timeout: 5000 production: adapter: postgresql database: catan pool: 5
Friendly Warning
Let me save you a lot of time debugging database migration issues in Heroku
You might see documentation that shows the postgres configuration in the database.yml file to look like this:
#--------------------DO NOT DO THIS---------------# production: adapter: postgresql database: catan encoding: unicode pool: 5 timeout: 5000 #username: user #password: <%= ENV['DATABASE_PASSWORD'] %> #host: <%= ENV['DATABASE_HOST'] %> #--------------------DO NOT DO THIS---------------#
This will certainly cause you issues. You don't need any of these extra parameters (timeout, username, password, host). Heroku will provide them, and it will cause migration issues if you write them in. Simply omit them and write the production database configuration in three lines like I've illustrated above.
If you do chose to use Postgres for your test and development databases, then you will need to complete all of these params. If you're committing to a public repo, it might be wise to save the username and password to your Postgres database in a .env that is included in your .gitignore??
You'll also want to make sure your username and password for your Postgres database is accurate - don't copy mine and forget to edit it :).
If this is still unclear, the Heroku documentation for changing your database from sqlite3 to Postgres is helpful.
Update Gemfile
At this point, you'll need to add the Postgres gem to your Gemfile (gem 'pg'). If you are keeping SQLite for your development database, then you NEED to group it under development (and test) in your gemfile. If you do not, and have the SQLITE3 gem listed in the main body of your Gemfile, you'll hit an error when you try to push your app to Heroku. Fortunately, Heroku ignores the gems in your test or development group, so tuck SQLite3 there.
source 'https://rubygems.org' gem 'activerecord', '~> 4.2', '>= 4.2.6', :require => 'active_record' gem 'bcrypt' gem "pg", "~> 0.21" gem 'rake' gem 'require_all' gem 'shotgun' gem 'sinatra' gem 'sinatra-activerecord', :require => 'sinatra/activerecord' gem 'thin' group :test, :development do gem "pry" #comment out sqlite gem if using postgresql for test and development database gem 'sqlite3', '~> 1.3.6' end group :test do gem 'rspec' gem 'capybara' gem 'rack-test' gem 'database_cleaner' end
Now is also a good time to run bundle install to see if there are any dependency surprises you need to fix. If you're running Ruby version 2.6.1+ and it's been a while since you've run Sinatra, you should expect to encounter a few issues. I walk through debugging 3 dependency issues in this post.
At this point, I also ran my database migrations locally to ensure they worked and I had successfully configured the database.
Since I had a test database I wanted to configure, I ran
rake db:migrate SINATRA_ENV=test
and then ran
rake db:migrate SINATRA_ENV=development
If all this is working, the bulk of the preparation for getting your app hosted is done. Move on to the next step!
add a Procfile
This is simply done in 2 steps. From your project's directory
touch Procfile
then use
bundle exec rackup config.ru -p $PORT to the Procfile
I want to stress 2 things here. The 1 line of code in the Procfile needs to be absolutely identical to what I've posted here. If there's a typo or even any uneccessary whitespace, it will create an "App-crashed" error in Heroku. Please a make the Procfile file simply that. No file extensions. Just Procfile.
RakeFile
Now that you've added and updated database configurations in your environment.rb, you can clean up your rake file.
Out of the box, your Sinatra might have ENV["SINATRA_ENV"] ||= "development" in the first line of the rake file. This now redundant if we are using require_relative './config/environment'. The entirety of your Rakefile can now look like this:
require_relative './config/environment' require 'sinatra/activerecord/rake' task :console do Pry.start end
(if you debug with Tux instead of Pry, go ahead and substitute Tux in the code above :)
STOP
before you go any further, run:
`rackup config.ru`
in your terminal
If your app executes fine without any issue, you can proceed to the actual deployment steps for Heroku below. If your app breaks, I strongly encourage you to stop here, debug, and get everything running smoothly. Having the slightest thing off can disrupt the deployment or break the app when you run it in Heroku, so confirm your app performs as expected before moving forward.
Deploy to Heroku
If your migrations worked successfully, and your app boots up successfully and renders in localhost on your machine (using shotgun), then it's time to deploy to Heroku.
This is also a simple 2 step process. After committing and pushing your most recent project changes to Github:
heroku apps:create <name_of_your_app>
then
git push heroku master
At this point, Heroku should create an app of your naming, and then you'll push your most recently committed version of your app to Heroku.
Simple enough.
Before you go any further, let me stop you. At this point, I had some issues with creating a database migration and breaking Heroku, so let me share a few things here.
Run
heroku addons
This should return the following:
This shows Heroku has already established a Postgres Database for your app
If you do not see a Postgres database listed, you'll want to run the following command to create one in Heroku:
heroku addons:add heroku-postgresql: plan-name
If your account plan was hobby-dev, like mine above, that is what you'd use as the value for plan name.
With the database created, you can now run a migration. If you've made migrations files in Sinatra already (which I'm assuming you have since this was a project), we can forego creating migrations files and simply migrate:
heroku run rake db:migrate
With that, you should see a successful migration.
Those beautiful horizontal lines
Using the command heroku open you should see your app open up in a web browser hosted by Heroku. If you see an error at this point, run
heroku restart
and then try running
heroku open
again.
If everything goes well, at this point, you should have a live site!
If you are getting App-crashed errors, check your Procfile and make sure everything is perfect in there, check out this short article, and then Googling.
Documentation
The official Heroku Documentation
Getting started (example of hosting a generic app) on Heroku
Heroku walkthrough hosting Rails5 (which you can follow along as an analogy for Sinatra)
How to install Postgres (probably the most useful of the Heroku docs for this process)
Blogs discussing Hosting your Sinatra App on Heroku (in Chronological Order)
2013 - The Official Flatiron School blog
2013 - Deploying a Simple Sinatra App with Postgres to Heroku
2013 - Get Started with Sinatra on Heroku
2018 - Deploying Sinatra App to Heroku
2017 - I Deployed My Sinatra App to Heroku
My Project:
Do you like playing Settlers of Catan? I wrote a Sinatra app that keeps in-game stats of the most frequent roles in a game of Catan, providing data that can influence your strategy.
Check it out:
Fullstack Web Developer | Ruby On Rails | Javascript | React
3 年Hi Trevor! I've found your article while I was having a hard time deploying my Sinatra app to Heroku. I just wanted to thank you so much for all the wisdom and knowledge shared. It helped me so much and my app is finally in production. Thank you. PS: Catan is one of my favorite games too :)
Coaching Career Changers in Tech, Climate and Beyond
4 年Playing Catan online has been such a fun way to stay connected with friends and family. Your app would be very handy!!