Getting Started on Heroku with Rails 5.x
Last updated October 11, 2024
Table of Contents
- Local setup
- Create a new Rails app (or upgrade an existing one)
- Add the pg gem
- Create a welcome page
- Heroku gems
- Specify your Ruby version
- Store your app in Git
- Create a Heroku app
- Provision a Database
- Deploy your application to Heroku
- Migrate your database
- Visit your application
- View logs
- Dyno sleeping and scaling
- Run the Rails console
- Run Rake commands
- Configure your webserver
- Rails asset pipeline
- Troubleshooting
- Next Steps
- Deleting your app and Add-on
This article is archived. It is no longer receiving updates. It is presented here for historical reference only. We cannot guarantee that any statements made are still true or that the instructions will still work. This version of Rails is no longer supported by Rails core. If you are starting a new application, we recommend you use the most recently released version of Rails.
As of November 28th, 2022, free Heroku dynos, free Heroku Postgres and free Heroku Key-Value Store plans are no longer available.
We recommend using our low-cost plans to complete this tutorial. Eligible students can apply for platform credits through our new Heroku for GitHub Students program.
Ruby on Rails is a popular web framework written in Ruby. This guide covers using Rails 5 on Heroku. For information on running previous versions of Rails on Heroku, see the tutorial for Rails 4.x or Rails 3.x.
For this guide you will need:
- Basic familiarity with Ruby/Rails and Git
- A locally installed version of Ruby 2.2.0+, Rubygems, Bundler, and Rails 5+
- A verified Heroku Account
- A subscription to the Eco dynos plan (recommended)
Local setup
Install the Heroku CLI on your development machine.
Once installed, the heroku
command is available from your terminal. Log in using your Heroku account’s email address and password:
$ heroku login
heroku: Enter your Heroku credentials
Email: schneems@example.com
Password:
Could not find an existing public key.
Would you like to generate one? [Yn]
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub
Press Enter at the prompt to upload your existing ssh
key or create a new one, used for pushing code later on.
Create a new Rails app (or upgrade an existing one)
If you are starting with an existing app that uses a previous version of Rails, upgrade it to Rails 5 before continuing. If you’re not starting from an existing app at all, a vanilla Rails 5 app works great as a sample app.
To create a new app, first make sure that you’re using Rails 5.x by running rails -v
. If necessary, you can get the new version of rails by running the following:
$ gem install rails --no-document
Successfully installed rails-7.0.4.3
1 gem installed
Then create a new app and move into its root directory:
$ rails new myapp --database=postgresql
Then move into your application directory.
$ cd myapp
$ bundle lock --add-platform x86_64-linux --add-platform ruby
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Writing lockfile to /Users/rschneeman/Documents/projects/rundoc/test/fixtures/rails_5/tmp/myapp/Gemfile.lock
$ bundle install
Create a database locally:
$ bin/rake db:create
Database 'myapp_development' already exists
Database 'myapp_test' already exists
Add the pg gem
If you’re using an existing app that was created without specifying --database=postgresql
, you need to add the pg
gem to your Rails project. Edit your Gemfile
and change this line:
gem 'sqlite3'
To this:
gem 'pg'
We highly recommend using PostgreSQL during development. Maintaining parity between your development and deployment environments prevents subtle bugs from being introduced because of differences between your environments. Install Postgres locally now if it is not already on your system.
Now re-install your dependencies (to generate a new Gemfile.lock
):
$ bundle install
For more information on why Postgres is recommended instead of Sqlite3, see why you cannot use Sqlite3 on Heroku.
In addition to using the pg
gem, ensure that your config/database.yml
file is using the postgresql
adapter. The development section of your config/database.yml
file should look something like this:
$ cat config/database.yml
# PostgreSQL. Versions 9.3 and up are supported.
#
# Install the pg driver:
# gem install pg
# On macOS with Homebrew:
# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On macOS with MacPorts:
# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
# gem install pg
# Choose the win32 build.
# Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem "pg"
#
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: myapp_development
# The specified database role being used to connect to postgres.
# To create additional roles in postgres see `$ createuser --help`.
# When left blank, postgres will use the default role. This is
# the same name as the operating system user running Rails.
#username: myapp
# The password associated with the postgres role (username).
#password:
# Connect on a TCP socket. Omitted by default since the client uses a
# domain socket that doesn't need configuration. Windows does not have
# domain sockets, so uncomment these lines.
#host: localhost
# The TCP port the server listens on. Defaults to 5432.
# If your server runs on a different port number, change accordingly.
#port: 5432
# Schema search path. The server defaults to $user,public
#schema_search_path: myapp,sharedapp,public
# Minimum log levels, in increasing order:
# debug5, debug4, debug3, debug2, debug1,
# log, notice, warning, error, fatal, and panic
# Defaults to warning.
#min_messages: notice
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: myapp_test
# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
<<: *default
database: myapp_production
username: myapp
password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>
Be careful here. If you omit the sql
at the end of postgresql
in the adapter
section, your application will not work.
Create a welcome page
Rails 5 no longer has a static index page in production by default. When you’re using a new app, there will not be a root page in production, so we need to create one. We will first create a controller called welcome
for our home page to live:
$ rails generate controller welcome
Next we’ll add an index page:
In file app/views/welcome/index.html.erb
write:
<h2>Hello World</h2>
<p>
The time is now: <%= Time.now %>
</p>
Now we need to make Rails route to this action. We’ll edit config/routes.rb
to set the index page to our new method:
In file config/routes.rb
, on line 2 add:
root 'welcome#index'
You can verify that the page is there by running your server:
$ rails server
And visiting http://localhost:3000 in your browser. If you do not see the page, use the logs that are output to your server to debug.
Heroku gems
Previous versions of Rails required you to add a gem to your project rails_12factor to enable static asset serving and logging on Heroku. If you are deploying a new application, this gem is not needed. If you are upgrading an existing application, you can remove this gem provided you have the apprpriate configuration in your config/environments/production.rb
file:
# config/environments/production.rb
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
Specify your Ruby version
Rails 5 requires Ruby 2.2.0 or above. Heroku has a recent version of Ruby installed by default, however you can specify an exact version by using the ruby
DSL in your Gemfile
. Depending on your version of Ruby that you are currently running it might look like this:
ruby "2.7.8"
You should also be running the same version of Ruby locally. You can check this by running $ ruby -v
. You can get more information on specifying your Ruby version on Heroku here.
Store your app in Git
Heroku relies on Git, a distributed source control management tool, for deploying your project. If your project is not already in Git, first verify that git
is on your system:
$ git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
If you don’t see any output or get command not found
you need to install Git on your system.
Once you’ve verified that Git works, first make sure you are in your Rails app directory by running $ ls
:
The output should look like this:
$ ls
Gemfile
Gemfile-e
Gemfile.lock
README.md
Rakefile
app
bin
config
config.ru
db
lib
log
public
storage
test
tmp
vendor
Now run these commands in your Rails app directory to initialize and commit your code to Git:
$ git init
$ git add .
$ git commit -m "init"
You can verify everything was committed correctly by running:
$ git status
On branch main
nothing to commit, working tree clean
Now that your application is committed to Git you can deploy to Heroku.
Create a Heroku app
Using a dyno and a database to complete this tutorial counts towards your usage. Delete your app, and database as soon as you’re done to control costs.
Make sure you are in the directory that contains your Rails app, then create an app on Heroku:
$ heroku create --stack heroku-20
Creating app... done, fathomless-escarpment-09880, stack is heroku-20
https://fathomless-escarpment-09880.herokuapp.com/ | https://git.heroku.com/fathomless-escarpment-09880.git
You can verify that the remote was added to your project by running:
$ git config --list --local | grep heroku
remote.heroku.url=https://git.heroku.com/fathomless-escarpment-09880.git
remote.heroku.fetch=+refs/heads/*:refs/remotes/heroku/*
If you see fatal: not in a git directory
then you are likely not in the correct directory. Otherwise you can deploy your code. After you deploy your code, you need to migrate your database, make sure it is properly scaled, and use logs to debug any issues that come up.
Following changes in the industry, Heroku has updated our default git branch name to main
. If the project you’re deploying uses master
as its default branch name, use git push heroku master
.
Provision a Database
Provision a Postgresql database using Add-ons.
An essential-0
Postgres size costs $5 a month, prorated to the minute. At the end of this tutorial, you will be prompted to delete your database to minimize costs.
$ heroku addons:create heroku-postgresql:essential-0
Creating heroku-postgresql:essential-0 on ⬢ shrouded-anchorage-34700... ~$0.007/hour (max $5/month)
Database should be available soon
postgresql-encircled-75487 is being created in the background. The app will restart when complete...
Use heroku addons:info postgresql-encircled-75487 to check creation progress
Use heroku addons:docs heroku-postgresql to view documentation
Your Heroku app now has access to a Postgresql database. The credentials are stored in the DATABASE_URL
environment variable, which Rails will connect to by convention.
Deploy your application to Heroku
Deploy your code:
$ git push heroku main
remote: Updated 80 paths from 53ee028
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.3.25
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.7.8
remote: -----> Installing dependencies using bundler 2.3.25
remote: Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote: Fetching gem metadata from https://rubygems.org/..........
remote: Fetching rake 13.0.6
remote: Installing rake 13.0.6
remote: Fetching builder 3.2.4
remote: Fetching erubi 1.12.0
remote: Fetching concurrent-ruby 1.2.2
remote: Fetching minitest 5.18.0
remote: Installing minitest 5.18.0
remote: Fetching racc 1.6.2
remote: Installing builder 3.2.4
remote: Installing erubi 1.12.0
remote: Fetching crass 1.0.6
remote: Installing concurrent-ruby 1.2.2
remote: Fetching rack 2.2.7
remote: Installing racc 1.6.2 with native extensions
remote: Installing crass 1.0.6
remote: Installing rack 2.2.7
remote: Fetching nio4r 2.5.9
remote: Fetching websocket-extensions 0.1.5
remote: Installing nio4r 2.5.9 with native extensions
remote: Installing websocket-extensions 0.1.5
remote: Fetching marcel 1.0.2
remote: Fetching mini_mime 1.1.2
remote: Installing mini_mime 1.1.2
remote: Installing marcel 1.0.2
remote: Fetching date 3.3.3
remote: Fetching timeout 0.3.2
remote: Installing timeout 0.3.2
remote: Fetching msgpack 1.7.1
remote: Installing msgpack 1.7.1 with native extensions
remote: Installing date 3.3.3 with native extensions
remote: Using bundler 2.3.25
remote: Fetching method_source 1.0.0
remote: Installing method_source 1.0.0
remote: Fetching thor 1.2.2
remote: Installing thor 1.2.2
remote: Fetching zeitwerk 2.6.8
remote: Installing zeitwerk 2.6.8
remote: Fetching pg 1.5.3
remote: Installing pg 1.5.3 with native extensions
remote: Fetching redis 4.8.1
remote: Installing redis 4.8.1
remote: Fetching rack-test 2.1.0
remote: Installing rack-test 2.1.0
remote: Fetching i18n 1.13.0
remote: Installing i18n 1.13.0
remote: Fetching tzinfo 2.0.6
remote: Installing tzinfo 2.0.6
remote: Fetching sprockets 4.2.0
remote: Installing sprockets 4.2.0
remote: Fetching websocket-driver 0.7.5
remote: Installing websocket-driver 0.7.5 with native extensions
remote: Fetching net-protocol 0.2.1
remote: Installing net-protocol 0.2.1
remote: Fetching nokogiri 1.15.1 (x86_64-linux)
remote: Installing nokogiri 1.15.1 (x86_64-linux)
remote: Fetching puma 5.6.5
remote: Installing puma 5.6.5 with native extensions
remote: Fetching activesupport 7.0.4.3
remote: Installing activesupport 7.0.4.3
remote: Fetching net-imap 0.3.4
remote: Installing net-imap 0.3.4
remote: Fetching net-pop 0.1.2
remote: Installing net-pop 0.1.2
remote: Fetching net-smtp 0.3.3
remote: Installing net-smtp 0.3.3
remote: Fetching loofah 2.21.3
remote: Installing loofah 2.21.3
remote: Fetching bootsnap 1.16.0
remote: Installing bootsnap 1.16.0 with native extensions
remote: Fetching rails-dom-testing 2.0.3
remote: Installing rails-dom-testing 2.0.3
remote: Fetching globalid 1.1.0
remote: Installing globalid 1.1.0
remote: Fetching activemodel 7.0.4.3
remote: Installing activemodel 7.0.4.3
remote: Fetching mail 2.8.1
remote: Installing mail 2.8.1
remote: Fetching rails-html-sanitizer 1.5.0
remote: Installing rails-html-sanitizer 1.5.0
remote: Fetching activejob 7.0.4.3
remote: Installing activejob 7.0.4.3
remote: Fetching activerecord 7.0.4.3
remote: Fetching actionview 7.0.4.3
remote: Installing actionview 7.0.4.3
remote: Installing activerecord 7.0.4.3
remote: Fetching actionpack 7.0.4.3
remote: Installing actionpack 7.0.4.3
remote: Fetching jbuilder 2.11.5
remote: Installing jbuilder 2.11.5
remote: Fetching actioncable 7.0.4.3
remote: Fetching actionmailer 7.0.4.3
remote: Installing actioncable 7.0.4.3
remote: Installing actionmailer 7.0.4.3
remote: Fetching railties 7.0.4.3
remote: Fetching sprockets-rails 3.4.2
remote: Installing sprockets-rails 3.4.2
remote: Fetching activestorage 7.0.4.3
remote: Installing activestorage 7.0.4.3
remote: Installing railties 7.0.4.3
remote: Fetching actionmailbox 7.0.4.3
remote: Installing actionmailbox 7.0.4.3
remote: Fetching actiontext 7.0.4.3
remote: Installing actiontext 7.0.4.3
remote: Fetching importmap-rails 1.1.6
remote: Fetching rails 7.0.4.3
remote: Installing importmap-rails 1.1.6
remote: Installing rails 7.0.4.3
remote: Fetching stimulus-rails 1.2.1
remote: Fetching turbo-rails 1.4.0
remote: Installing stimulus-rails 1.2.1
remote: Installing turbo-rails 1.4.0
remote: Bundle complete! 16 Gemfile dependencies, 56 gems now installed.
remote: Gems in the groups 'development' and 'test' were not installed.
remote: Bundled gems are installed into `./vendor/bundle`
remote: Bundle completed (24.28s)
remote: Cleaning up the bundler cache.
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote: Running: rake assets:precompile
remote: I, [2023-05-22T21:28:40.619608 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/manifest-b84bfa46a33d7f0dc4d2e7b8889486c9a957a5e40713d58f54be71b66954a1ff.js
remote: I, [2023-05-22T21:28:40.619750 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/manifest-b84bfa46a33d7f0dc4d2e7b8889486c9a957a5e40713d58f54be71b66954a1ff.js.gz
remote: I, [2023-05-22T21:28:40.619853 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css
remote: I, [2023-05-22T21:28:40.619926 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css.gz
remote: I, [2023-05-22T21:28:40.620507 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/application-6472b71b26d30a0e6525e3872d53125ac65db0d91d4217d27b92d9323cefbb16.js
remote: I, [2023-05-22T21:28:40.621111 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/application-6472b71b26d30a0e6525e3872d53125ac65db0d91d4217d27b92d9323cefbb16.js.gz
remote: I, [2023-05-22T21:28:40.621198 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/turbo-4851a9a0b1d947e810dfd0448a72aef261d455183ebea681f4f28a73640a9ece.js
remote: I, [2023-05-22T21:28:40.621242 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/turbo-4851a9a0b1d947e810dfd0448a72aef261d455183ebea681f4f28a73640a9ece.js.gz
remote: I, [2023-05-22T21:28:40.621300 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/turbo.min-f309baafa3ae5ad6ccee3e7362118b87678d792db8e8ab466c4fa284dd3a4700.js
remote: I, [2023-05-22T21:28:40.621338 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/turbo.min-f309baafa3ae5ad6ccee3e7362118b87678d792db8e8ab466c4fa284dd3a4700.js.gz
remote: I, [2023-05-22T21:28:40.621397 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/turbo.min.js-8bc8f4a58d1c106d58dec8bef6c638ff12ff4d078f19d8ebd8c4277f4c9bc85a.map
remote: I, [2023-05-22T21:28:40.621434 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/turbo.min.js-8bc8f4a58d1c106d58dec8bef6c638ff12ff4d078f19d8ebd8c4277f4c9bc85a.map.gz
remote: I, [2023-05-22T21:28:40.621800 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/actiontext-28c61f5197c204db043317a8f8826a87ab31495b741f854d307ca36122deefce.js
remote: I, [2023-05-22T21:28:40.621879 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/actiontext-28c61f5197c204db043317a8f8826a87ab31495b741f854d307ca36122deefce.js.gz
remote: I, [2023-05-22T21:28:40.621946 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/trix-1563ff9c10f74e143b3ded40a8458497eaf2f87a648a5cbbfebdb7dec3447a5e.js
remote: I, [2023-05-22T21:28:40.621986 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/trix-1563ff9c10f74e143b3ded40a8458497eaf2f87a648a5cbbfebdb7dec3447a5e.js.gz
remote: I, [2023-05-22T21:28:40.622046 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/trix-ac629f94e04ee467ab73298a3496a4dfa33ca26a132f624dd5475381bc27bdc8.css
remote: I, [2023-05-22T21:28:40.622084 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/trix-ac629f94e04ee467ab73298a3496a4dfa33ca26a132f624dd5475381bc27bdc8.css.gz
remote: I, [2023-05-22T21:28:40.622140 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/es-module-shims-69d0cb4dc1d01c9dc2ed52f2ab66874fd545fe7e35c7841009b4e8c55f231dee.js
remote: I, [2023-05-22T21:28:40.622178 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/es-module-shims-69d0cb4dc1d01c9dc2ed52f2ab66874fd545fe7e35c7841009b4e8c55f231dee.js.gz
remote: I, [2023-05-22T21:28:40.623862 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/es-module-shims.min-4ca9b3dd5e434131e3bb4b0c1d7dff3bfd4035672a5086deec6f73979a49be73.js
remote: I, [2023-05-22T21:28:40.626819 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/es-module-shims.min-4ca9b3dd5e434131e3bb4b0c1d7dff3bfd4035672a5086deec6f73979a49be73.js.gz
remote: I, [2023-05-22T21:28:40.627052 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/es-module-shims.js-c69f1a5dd068dfc08a4cedc0ad77b792985bf256e162852bd03cdf764b666c4a.map
remote: I, [2023-05-22T21:28:40.627154 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/es-module-shims.js-c69f1a5dd068dfc08a4cedc0ad77b792985bf256e162852bd03cdf764b666c4a.map.gz
remote: I, [2023-05-22T21:28:40.627406 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-1bd52683afde5c8ff5572f5d49429cea5bf7744ca636fcb830c015d8cccf353e.js
remote: I, [2023-05-22T21:28:40.627589 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-1bd52683afde5c8ff5572f5d49429cea5bf7744ca636fcb830c015d8cccf353e.js.gz
remote: I, [2023-05-22T21:28:40.627744 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-autoloader-c584942b568ba74879da31c7c3d51366737bacaf6fbae659383c0a5653685693.js
remote: I, [2023-05-22T21:28:40.628465 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-autoloader-c584942b568ba74879da31c7c3d51366737bacaf6fbae659383c0a5653685693.js.gz
remote: I, [2023-05-22T21:28:40.628605 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-importmap-autoloader-db2076c783bf2dbee1226e2add52fef290b5d31b5bcd1edd999ac8a6dd31c44a.js
remote: I, [2023-05-22T21:28:40.628670 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-importmap-autoloader-db2076c783bf2dbee1226e2add52fef290b5d31b5bcd1edd999ac8a6dd31c44a.js.gz
remote: I, [2023-05-22T21:28:40.628756 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js
remote: I, [2023-05-22T21:28:40.628849 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js.gz
remote: I, [2023-05-22T21:28:40.628982 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus.min-d03cf1dff41d6c5698ec2c5d6a501615a7a33754dbeef8d1edd31c928d17c652.js
remote: I, [2023-05-22T21:28:40.629075 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus.min-d03cf1dff41d6c5698ec2c5d6a501615a7a33754dbeef8d1edd31c928d17c652.js.gz
remote: I, [2023-05-22T21:28:40.629340 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-autoloader-c584942b568ba74879da31c7c3d51366737bacaf6fbae659383c0a5653685693.js
remote: I, [2023-05-22T21:28:40.629715 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-autoloader-c584942b568ba74879da31c7c3d51366737bacaf6fbae659383c0a5653685693.js.gz
remote: I, [2023-05-22T21:28:40.629892 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-importmap-autoloader-db2076c783bf2dbee1226e2add52fef290b5d31b5bcd1edd999ac8a6dd31c44a.js
remote: I, [2023-05-22T21:28:40.629999 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-importmap-autoloader-db2076c783bf2dbee1226e2add52fef290b5d31b5bcd1edd999ac8a6dd31c44a.js.gz
remote: I, [2023-05-22T21:28:40.630250 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js
remote: I, [2023-05-22T21:28:40.631067 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js.gz
remote: I, [2023-05-22T21:28:40.631286 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus.min.js-0f3bbd3e2e72e4d7178153a52d180de4086e47082ecfc388ce82a90d8a3d7480.map
remote: I, [2023-05-22T21:28:40.631422 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/stimulus.min.js-0f3bbd3e2e72e4d7178153a52d180de4086e47082ecfc388ce82a90d8a3d7480.map.gz
remote: I, [2023-05-22T21:28:40.632405 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/activestorage-3ab61e47dd4ee2d79db525ade1dca2ede0ea2b7371fe587e408ee37b7ade265d.js
remote: I, [2023-05-22T21:28:40.633638 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/activestorage-3ab61e47dd4ee2d79db525ade1dca2ede0ea2b7371fe587e408ee37b7ade265d.js.gz
remote: I, [2023-05-22T21:28:40.633845 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/activestorage.esm-01f58a45d77495cdfbdfcc872902a430426c4391634ec9c3da5f69fbf8418492.js
remote: I, [2023-05-22T21:28:40.634773 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/activestorage.esm-01f58a45d77495cdfbdfcc872902a430426c4391634ec9c3da5f69fbf8418492.js.gz
remote: I, [2023-05-22T21:28:40.634977 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/actioncable-5433453f9b6619a9de91aaab2d7fc7ff183e5260c0107cbc9a1aa0c838d9a74e.js
remote: I, [2023-05-22T21:28:40.635109 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/actioncable-5433453f9b6619a9de91aaab2d7fc7ff183e5260c0107cbc9a1aa0c838d9a74e.js.gz
remote: I, [2023-05-22T21:28:40.635854 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/actioncable.esm-e01089c3ec4fe7817fa9abcad06cab6bdc387f95f0ca6aab4bf7ba7537f70690.js
remote: I, [2023-05-22T21:28:40.635946 #937] INFO -- : Writing /tmp/build_4b70cc8b/public/assets/actioncable.esm-e01089c3ec4fe7817fa9abcad06cab6bdc387f95f0ca6aab4bf7ba7537f70690.js.gz
remote: Asset precompilation completed (0.93s)
remote: Cleaning assets
remote: Running: rake assets:clean
remote: -----> Detecting rails configuration
remote:
remote: ###### WARNING:
remote:
remote: Potential EOL Ruby Version
remote:
remote: You are using a Ruby version that has either reached its End of Life (EOL)
remote: or will reach its End of Life on December 25th of this year.
remote:
remote: We suggest you upgrade to Ruby 3.0.x or later
remote:
remote: Once a Ruby version becomes EOL, it will no longer receive
remote: security updates from Ruby core and may have serious vulnerabilities.
remote:
remote: Please upgrade your Ruby version.
remote:
remote: For a list of supported Ruby versions see:
remote: https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
remote:
remote: ###### WARNING:
remote:
remote: No Procfile detected, using the default web server.
remote: We recommend explicitly declaring how to boot your server process via a Procfile.
remote: https://devcenter.heroku.com/articles/ruby-default-web-server
remote:
remote:
remote: -----> Discovering process types
remote: Procfile declares types -> (none)
remote: Default types for buildpack -> console, rake, web
remote:
remote: -----> Compressing...
remote: Done: 33M
remote: -----> Launching...
remote: ! The following add-ons were automatically provisioned: heroku-postgresql. These add-ons may incur additional cost, which is prorated to the second. Run `heroku addons` for more info.
remote: Released v6
remote: https://fathomless-escarpment-09880.herokuapp.com/ deployed to Heroku
remote:
remote: This app is using the Heroku-20 stack, however a newer stack is available.
remote: To upgrade to Heroku-22, see:
remote: https://devcenter.heroku.com/articles/upgrading-to-the-latest-stack
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/fathomless-escarpment-09880.git
* [new branch] main -> main
It is always a good idea to check to see if there are any warnings or errors in the output. If everything went well you can migrate your database.
Migrate your database
If you are using the database in your application, trigger a migration by using the Heroku CLI to start a one-off dyno, which is a lightweight container that is the basic unit of composition on Heroku, and run db:migrate
:
$ heroku run rake db:migrate
Any commands after the heroku run
are executed on a Heroku dyno. You can obtain an interactive shell session by running $ heroku run bash
.
Visit your application
You’ve deployed your code to Heroku. You can now instruct Heroku to execute a process type. Heroku does this by running the associated command in a dyno, which is a lightweight container that is the basic unit of composition on Heroku.
Let’s ensure we have one dyno running the web
process type:
$ heroku ps:scale web=1
You can check the state of the app’s dynos. The heroku ps
command lists the running dynos of your application:
$ heroku ps
=== web (Basic): bin/rails server -p ${PORT:-5000} -e $RAILS_ENV (1)
web.1: up 2023/05/22 16:28:53 -0500 (~ 1s ago)
Here, one dyno is running.
We can now visit the app in our browser with heroku open
.
$ heroku open
You should now see the “Hello World” text we inserted above.
Heroku gives you a default web URL for simplicity while you are developing. When you are ready to scale up and use Heroku for production you can add your own custom domain.
View logs
If you run into any problems getting your app to perform properly, you will need to check the logs.
You can view information about your running app using one of the logging commands, heroku logs
:
$ heroku logs
2023-05-22T21:28:08.718911+00:00 app[api]: Initial release by user developer@example.com2023-05-22T21:28:08.718911+00:00 app[api]: Release v1 created by user developer@example.com2023-05-22T21:28:08.851399+00:00 app[api]: Enable Logplex by user developer@example.com2023-05-22T21:28:08.851399+00:00 app[api]: Release v2 created by user developer@example.com2023-05-22T21:28:10.000000+00:00 app[api]: Build started by user developer@example.com2023-05-22T21:28:45.872424+00:00 app[api]: Set LANG, RACK_ENV, RAILS_ENV, RAILS_LOG_TO_STDOUT, RAILS_SERVE_STATIC_FILES, SECRET_KEY_BASE config vars by user developer@example.com2023-05-22T21:28:45.872424+00:00 app[api]: Release v3 created by user developer@example.com2023-05-22T21:28:46.525631+00:00 app[api]: Attach DATABASE (@ref:postgresql-rectangular-32248) by user developer@example.com2023-05-22T21:28:46.525631+00:00 app[api]: Running release v4 commands by user developer@example.com2023-05-22T21:28:46.538137+00:00 app[api]: @ref:postgresql-rectangular-32248 completed provisioning, setting DATABASE_URL. by user developer@example.com2023-05-22T21:28:46.538137+00:00 app[api]: Release v5 created by user developer@example.com2023-05-22T21:28:46.915284+00:00 app[api]: Deploy a6165823 by user developer@example.com2023-05-22T21:28:46.915284+00:00 app[api]: Release v6 created by user developer@example.com2023-05-22T21:28:46.932771+00:00 app[api]: Scaled to console@0:Basic rake@0:Basic web@1:Basic by user developer@example.com2023-05-22T21:28:49.000000+00:00 app[api]: Build succeeded
2023-05-22T21:28:49.014168+00:00 heroku[web.1]: Starting process with command `bin/rails server -p ${PORT:-5000} -e production`
2023-05-22T21:28:51.987150+00:00 app[web.1]: => Booting Puma
2023-05-22T21:28:51.987176+00:00 app[web.1]: => Rails 7.0.4.3 application starting in production
2023-05-22T21:28:51.987176+00:00 app[web.1]: => Run `bin/rails server --help` for more startup options
2023-05-22T21:28:53.054026+00:00 app[web.1]: Puma starting in single mode...
2023-05-22T21:28:53.054052+00:00 app[web.1]: * Puma version: 5.6.5 (ruby 2.7.8-p225) ("Birdie's Version")
2023-05-22T21:28:53.054053+00:00 app[web.1]: * Min threads: 5
2023-05-22T21:28:53.054053+00:00 app[web.1]: * Max threads: 5
2023-05-22T21:28:53.054053+00:00 app[web.1]: * Environment: production
2023-05-22T21:28:53.054053+00:00 app[web.1]: * PID: 2
2023-05-22T21:28:53.054285+00:00 app[web.1]: * Listening on http://0.0.0.0:39748
2023-05-22T21:28:53.058959+00:00 app[web.1]: Use Ctrl-C to stop
2023-05-22T21:28:53.256928+00:00 heroku[web.1]: State changed from starting to up
2023-05-22T21:28:57.527532+00:00 app[web.1]: I, [2023-05-22T21:28:57.527458 #2] INFO -- : [869dd3e0-d2f8-4caa-b2ac-024ed75e6b53] Started GET "/" for 165.225.32.83 at 2023-05-22 21:28:57 +0000
2023-05-22T21:28:57.529547+00:00 app[web.1]: I, [2023-05-22T21:28:57.529496 #2] INFO -- : [869dd3e0-d2f8-4caa-b2ac-024ed75e6b53] Processing by WelcomeController#index as HTML
2023-05-22T21:28:57.531098+00:00 app[web.1]: I, [2023-05-22T21:28:57.531054 #2] INFO -- : [869dd3e0-d2f8-4caa-b2ac-024ed75e6b53] Rendered welcome/index.html.erb within layouts/application (Duration: 0.3ms | Allocations: 120)
2023-05-22T21:28:57.534975+00:00 app[web.1]: I, [2023-05-22T21:28:57.534930 #2] INFO -- : [869dd3e0-d2f8-4caa-b2ac-024ed75e6b53] Rendered layout layouts/application.html.erb (Duration: 4.3ms | Allocations: 1002)
2023-05-22T21:28:57.535151+00:00 app[web.1]: I, [2023-05-22T21:28:57.535125 #2] INFO -- : [869dd3e0-d2f8-4caa-b2ac-024ed75e6b53] Completed 200 OK in 6ms (Views: 5.2ms | Allocations: 1618)
2023-05-22T21:28:57.536745+00:00 heroku[router]: at=info method=GET path="/" host=fathomless-escarpment-09880.herokuapp.com request_id=869dd3e0-d2f8-4caa-b2ac-024ed75e6b53 fwd="165.225.32.83" dyno=web.1 connect=0ms service=15ms status=200 bytes=2530 protocol=https
2023-05-22T21:28:57.606204+00:00 heroku[router]: at=info method=GET path="/assets/application-e0cf9d8fcb18bf7f909d8d91a5e78499f82ac29523d475bf3a9ab265d5e2b451.css" host=fathomless-escarpment-09880.herokuapp.com request_id=96e80556-1b99-43ef-9551-4a6f89d49f59 fwd="165.225.32.83" dyno=web.1 connect=0ms service=1ms status=200 bytes=575 protocol=https
2023-05-22T21:28:57.848847+00:00 heroku[router]: at=info method=GET path="/assets/es-module-shims.min-4ca9b3dd5e434131e3bb4b0c1d7dff3bfd4035672a5086deec6f73979a49be73.js" host=fathomless-escarpment-09880.herokuapp.com request_id=0860764c-4a8d-4b17-aa2d-964723b8b4a5 fwd="165.225.32.83" dyno=web.1 connect=0ms service=1ms status=200 bytes=12472 protocol=https
2023-05-22T21:28:57.851876+00:00 heroku[router]: at=info method=GET path="/assets/application-6472b71b26d30a0e6525e3872d53125ac65db0d91d4217d27b92d9323cefbb16.js" host=fathomless-escarpment-09880.herokuapp.com request_id=79fd01bb-6b5f-4972-ad42-f51ff8995443 fwd="165.225.32.83" dyno=web.1 connect=0ms service=1ms status=200 bytes=313 protocol=https
2023-05-22T21:28:57.900828+00:00 heroku[router]: at=info method=GET path="/assets/turbo.min-f309baafa3ae5ad6ccee3e7362118b87678d792db8e8ab466c4fa284dd3a4700.js" host=fathomless-escarpment-09880.herokuapp.com request_id=100ef50c-ae69-4457-9df2-46b0c34c802e fwd="165.225.32.83" dyno=web.1 connect=0ms service=1ms status=200 bytes=22749 protocol=https
2023-05-22T21:28:58.022168+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=fathomless-escarpment-09880.herokuapp.com request_id=006bc4b2-654c-4eb2-aba7-2c3d44f1c0bd fwd="165.225.32.83" dyno=web.1 connect=0ms service=1ms status=200 bytes=143 protocol=https
You can also get the full stream of logs by running the logs command with the --tail
flag option like this:
$ heroku logs --tail
Dyno sleeping and scaling
By default, new applications are deployed to an eco dyno. Eco apps will “sleep” to conserve resources. You can find more information about this behavior by reading about eco dyno behavior.
To avoid dyno sleeping, you can upgrade to a Basic or Professional dyno type as described in the Dyno Types article. For example, if you migrate your app to a Professional dyno, you can easily scale it by running a command telling Heroku to execute a specific number of dynos, each running your web process type.
Run the Rails console
Heroku allows you to run commands in a one-off dyno - scripts and applications that only need to be executed when needed - using the heroku run
command. Use this to launch a Rails console process attached to your local terminal for experimenting in your app’s environment:
$ heroku run rails console
irb(main):001:0> puts 1+1
2
Another useful command for debugging is $ heroku run bash
which will spin up a new dyno and give you access to a bash session.
Run Rake commands
Rake can be run as an attached process exactly like the console:
$ heroku run rake db:migrate
Configure your webserver
By default, your app’s web process runs rails server
, which uses Puma in Rails 5. If you are upgrading an app you’ll need to add puma
to your application Gemfile
:
gem 'puma'
Then run
$ bundle install
Now you are ready to configure your app to use Puma. For this tutorial we will use the default config/puma.rb
of that ships with Rails 5, but we recommend reading more about configuring your application for maximum performance by reading the Puma documentation.
Finally you will need to tell Heroku how to run your Rails app by creating a Procfile
in the root of your application directory.
Create a Procfile
Change the command used to launch your web process by creating a file called Procfile and entering this:
In file Procfile
write:
web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}
: This file must be named Procfile
exactly.
We recommend generating a Puma config file based on our Puma documentation for maximum performance.
To use the Procfile locally, you can use heroku local
.
In addition to running commands in your Procfile
heroku local
can also help you manage environment variables locally through a .env
file. Set the local RACK_ENV
to development in your environment and a PORT
to connect to. Before pushing to Heroku you’ll want to test with the RACK_ENV
set to production since this is the environment your Heroku app will run in.
$ echo "RACK_ENV=development" >>.env
$ echo "PORT=3000" >> .env
: Another alternative to using environment variables locally with a .env
file is the dotenv gem.
You’ll also want to add .env
to your .gitignore
since this is for local environment setup.
$ echo ".env" >> .gitignore
$ git add .gitignore
$ git commit -m "add .env to .gitignore"
Test your Procfile locally using Foreman. You can now start your web server by running:
$ heroku local
[OKAY] Loaded ENV .env File as KEY=VALUE Format
4:29:03 PM web.1 | Puma starting in single mode...
4:29:04 PM web.1 | * Puma version: 5.6.5 (ruby 2.7.8-p225) ("Birdie's Version")
4:29:04 PM web.1 | * Min threads: 5
4:29:04 PM web.1 | * Max threads: 5
4:29:04 PM web.1 | * Environment: development
4:29:04 PM web.1 | * PID: 63271
4:29:05 PM web.1 | * Listening on http://0.0.0.0:3000
4:29:05 PM web.1 | Use Ctrl-C to stop
Looks good, so press Ctrl+C
to exit and you can deploy your changes to Heroku:
$ git add .
$ git commit -m "use puma via procfile"
$ git push heroku main
Check ps
. You’ll see that the web process uses your new command specifying Puma as the web server.
$ heroku ps
=== web (Basic): bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development} (1)
web.1: up 2023/05/22 16:29:24 -0500 (~ 0s ago)
The logs also reflect that we are now using Puma.
$ heroku logs
Rails asset pipeline
There are several options for invoking the Rails asset pipeline when deploying to Heroku. For general information on the asset pipeline please see the Rails 3.1+ Asset Pipeline on Heroku Cedar article.
The config.assets.initialize_on_precompile
option has been removed is and not needed for Rails 5. Also, any failure in asset compilation will now cause the push to fail. For Rails 5 asset pipeline support see the Ruby Support page.
Troubleshooting
If you push up your app and it crashes (heroku ps
shows state crashed
), check your logs to find out what went wrong. Here are some common problems.
Runtime dependencies on development/test gems
If you’re missing a gem when you deploy, check your Bundler groups. Heroku builds your app without the development
or test
groups, and if your app depends on a gem from one of these groups to run, you should move it out of the group.
One common example is using the RSpec tasks in your Rakefile
. If you see this in your Heroku deploy:
$ heroku run rake -T
Running `bundle exec rake -T` attached to terminal... up, ps.3
rake aborted!
no such file to load -- rspec/core/rake_task
Then you’ve hit this problem. First, duplicate the problem locally:
$ bundle install --without development:test
…
$ bundle exec rake -T
rake aborted!
no such file to load -- rspec/core/rake_task
: The --without
option on bundler is sticky. You can get rid of this option by running bundle config --delete without
.
Now you can fix it by making these Rake tasks conditional on the gem load. For example:
begin
require "rspec/core/rake_task"
desc "Run all examples"
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = %w[--color]
t.pattern = 'spec/**/*_spec.rb'
end
rescue LoadError
end
Confirm it works locally, then push to Heroku.
Next Steps
Congratulations on deploying a Rails 5 application! To continue exploring, review the following articles next:
- Visit the Ruby support category to learn more about using Ruby and Rails on Heroku.
- The Deployment category provides a variety of powerful integrations and features to help streamline and simplify your deployments.
Deleting your app and Add-on
If you don’t need this application and database, you can now remove them from your account. You’ll only be charged for the resources you used.
This will remove your add-on you’ll lose any data saved in the database.
$ heroku addons:destroy heroku-postgresql
This will delete your application
$ heroku apps:destroy
You can confirm that your add-on and app are gone with the commands:
$ heroku addons --all
$ heroku apps -all
You’re now ready to deploy your app.