DEV Community

Cover image for Deploying Your Rails 6 App
Jake Malachowski for Render

Posted on • Updated on

Deploying Your Rails 6 App

This article was originally published at: https://render.com/docs/deploy-rails. It's recommended to read the linked version with improved syntax highlighting.

This guide will demonstrate how you can set up a local Ruby on Rails 6 environment, create a simple view, and deploy it to Render. The application will be configured to use a Render PostgreSQL database.

The repository used for this demo can be found here and the sample app can be viewed here.

Create a Ruby on Rails Project

In this step, we will set up a local development environment with a basic project structure.

We will be calling this example project myrailssite. You can replace this with a name of your choosing.

Install Rails

To install Ruby on Rails on your machine, use the gem install command. Be sure you have the required dependencies installed (Ruby, Node.js and Yarn 1.x).
We are using Rails 6 in this tutorial, so verify that you have the correct version installed:

$ gem install rails
$ rails --version
Rails 6.0.3.2

Create a New Project

  1. In your terminal, navigate to the directory where you will be creating your project. Then, run the following commands to generate a new project:

     $ rails new myrailssite --database=postgresql
    

    You can make use of arguments to customize the generated project. Enter rails new -h for further details.

  2. Create a local database for your application:

     $ rails db:create
     Created database 'myrailssite_development'
     Created database 'myrailssite_test'
    



This should create a fully functional basis for you new Rails application! To verify, you can start the development server:

$ rails server

To see your application in action, open a browser window and navigate to http://localhost:3000. You should see the Rails default information page:

Rails Successful Installation

Create the Hello World Landing Page

In this section, you will create a simple Rails application with a static view using Ruby on Rails. If you plan to deploy your sample Rails project on Render, skip to Update Your App For Render and deploy an empty project.

Checkout the official Getting Started with Rails guide for further reading on how to create Rails applications.

Create Your First Page

  1. In order to create a new Rails controller, you need to run the controller generator. Set the controller's name to Render and set up an action named index using the following command:

     $ rails g controller Render index
    

    The generator will create several files in your project:

     create  app/controllers/render_controller.rb
      route  get 'render/index'
     invoke  erb
     create    app/views/render
     create    app/views/render/index.html.erb
     invoke  test_unit
     create    test/controllers/render_controller_test.rb
     invoke  helper
     create    app/helpers/render_helper.rb
     invoke    test_unit
     invoke  assets
     invoke    scss
     create      app/assets/stylesheets/render.scss
    

2. Open the config/routes.rb file and add the following line:

Rails.application.routes.draw do
 get 'render/index'

 # For more details on this file's DSL, see https://guides.rubyonrails.org/routing.html
 root 'render#index'

This file will tell Rails that you want your render/index action to be accessible from the root URL of your application.

3. Open the app/views/render/index.html.erb file and replace its contents with:

<main class="container">
  <div class="row text-center justify-content-center">
    <div class="col">
      <h1 class="display-4">Hello World!</h1>
    </div>
  </div>
</main>

Add Third-Party CSS

In this step you will integrate Bootstrap into your application for easy styling.

  1. In order to install Bootstrap, run the following command in your terminal:

     $ yarn add bootstrap
    
  2. Rename your app/assets/stylesheets/application.css to app/assets/stylesheets/application.scss:

     $ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
    
  3. Open app/assets/stylesheets/application.scss and replace its contents with:

     /*
      * This is a manifest file that'll be compiled into application.css, which will include all the files
      * listed below.
      *
      * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
      * vendor/assets/stylesheets directory can be referenced here using a relative path.
      */
    
     @import "bootstrap/scss/bootstrap";
    
     @import "**/*";
    

So far, we imported Bootstrap into our CSS pack. This means Bootstrap will now be a part of the stylesheets served with our application.

Then, we replaced the existing require_* Rails directives with a plain SASS @import rule.

Both methods import all stylesheets from the app/assets/styleshets directory and its subdirectories. However, the use of the @import rule allows the imported stylesheets to access the SASS variables defined by Bootstrap.

4. Open app/views/layouts/application.html.erb and add the following modifications to the heading:

<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
  <head>
   <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>Hello Rails on Render!</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  ...
</html>

Add an Image Asset

  1. In order to add an asset to your project, download this banner and save it as app/assets/images/render.png:

render.png

2. In your layout, in app/views/layouts/application.html.erb, reference the downloaded image:

   ...
   <body>
      <header class="container mt-4 mb-4">
        <a href="https://render.com">
          <%= image_tag 'render.png', class: 'mw-100' %>
        </a>
      </header>
      <%= yield %>
   </body>
   </html>

You can now verify that your app is working using the following command:

$ rails server

Rails Hello World

Update Your App For Render

In order for your Rails project to be ready for production, you will need to make a few adjustments. If you haven't already, you will be required update your project to use a Render PostgreSQL database) instead of a SQLite database.

Modify Existing Rails Project for PostgreSQL

This is only required if the application was created without specifying --database=postgresql.

  1. In your Gemfile change the requirement for the existing database driver:

    from:

     gem 'sqlite3'
    

    to:

     gem 'pg'
    
  2. Install your new dependencies using the following command. This will also update your Gemfile.lock:

     $ bundle install
    
  3. Open config/database.yml and update it to use the postgresql database adapter.:

     # 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: myrailssite_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 that initialized the database.
       #username: myrailssite
    
       # 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: myrailssite_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 as a unix environment variable when you boot
     # the app. Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
     # for a full rundown on how to provide these environment variables in a
     # production deployment.
     #
     # On Heroku and other platform providers, you may have a full connection URL
     # available as an environment variable. For example:
     #
     #   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
     #
     # You can use this database configuration with:
     #
     #   production:
     #     url: <%= ENV['DATABASE_URL'] %>
     #
     production:
       <<: *default
       database: myrailssite_production
       username: myrailssite
       password: <%= ENV['MYRAILSSITE_DATABASE_PASSWORD'] %>
    

Go Production-Ready

Before deploying any serious application in production, some minor tweaks are required.

  1. Open config/database.yml and find the production section. Modify it to gather the database configuration from the DATABASE_URL environment variable:
   production:
      <<: *default
      url: <%= ENV['DATABASE_URL'] %>

2. Open config/puma.rb and uncomment and add the highlighted lines:

 # Puma can serve each request in a thread from an internal thread pool.
 # The `threads` method setting takes two numbers: a minimum and maximum.
 # Any libraries that use thread pools should be configured to match
 # the maximum value specified for Puma. Default is set to 5 threads for minimum
 # and maximum; this matches the default thread size of Active Record.
 #
 max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
 min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
 threads min_threads_count, max_threads_count

 # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
 #
 port        ENV.fetch("PORT") { 3000 }

 # Specifies the `environment` that Puma will run in.
 #
 environment ENV.fetch("RAILS_ENV") { "development" }

 # Specifies the `pidfile` that Puma will use.
 pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }

 # Specifies the number of `workers` to boot in clustered mode.
 # Workers are forked web server processes. If using threads and workers together
 # the concurrency of the application would be max `threads` * `workers`.
 # Workers do not work on JRuby or Windows (both of which do not support
 # processes).
 #
 workers ENV.fetch("WEB_CONCURRENCY") { 4 }

 # Use the `preload_app!` method when specifying a `workers` number.
 # This directive tells Puma to first boot the application and load code
 # before forking the application. This takes advantage of Copy On Write
 # process behavior so workers use less memory.
 #
 preload_app!

 # Allow puma to be restarted by `rails restart` command.
 plugin :tmp_restart

3. Open config/environments/production.rb and enable the public file server when the RENDER environment variable is present (which always is on Render):

 # Disable serving static files from the `/public` folder by default since
 # Apache or NGINX already handles this.
 config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? || ENV['RENDER'].present?

Create a Build Script

You will need to run a series of commands to build your app. This can be done using a build script. Create a script called bin/render-build.sh at the root of your repository:

#!/usr/bin/env bash
# exit on error
set -o errexit

bundle install
bundle exec rake assets:precompile
bundle exec rake assets:clean
bundle exec rake db:migrate

Make sure the script is executable before checking it into Git:

$ chmod a+x bin/render-build.sh

We will configure Render to call this script on every push to the Git repository.

Commit all changes and push them to your GitHub repository. Now your application is ready to be deployed on Render!

Deploy to Render

There are two ways to deploy your application on Render, either by declaring your services within your repository in a render.yaml file, or by manually setting up your services using the dashboard. In the following steps, we will walk you through both options.

Use render.yaml to Deploy

  1. Create a file named render.yaml at the root of your directory with the following content. The file will include information about your Rails Web Service and the Database that is used by your application. Don't forget to commit and push it to your remote repository.
   databases:
      - name: myrailssite
        databaseName: myrailssite
        user: myrailssite

   services:
      - type: web
        name: myrailssite
        env: ruby
        buildCommand: "./bin/render-build.sh"
        startCommand: "bundle exec puma -C config/puma.rb"
        envVars:
          - key: DATABASE_URL
            fromDatabase:
              name: myrailssite
              property: connectionString
          - key: RAILS_MASTER_KEY
            sync: false

2. On the Render Dashboard, go to the YAML page and click the New From YAML button. Select your repository (after giving Render the permission to access it, if you haven't already).

3. In the deploy window, set the value of the RAILS_MASTER_KEY to the contents of your config/master.key file. Then click Approve.

That's it! Your app will be live on your .onrender.com URL as soon as the build finishes.

Deploy Manually

If you don't wish to deploy your Rails app through YAML deploys, you can follow these steps for a manual deploy.

  1. Create a new PostgreSQL database on Render. Note your database internal connection string; you will need it later.

  2. Create a new Web Service, pointing it to your application repository (make sure Render has a permission to access it).

  3. Select Ruby for the environment and set the following properties:

Property Value
Build Command ./bin/render-build.sh
Start Command bundle exec puma -C config/puma.rb

4. Add the following environment variables under the Advanced section:

Key Value
DATABASE_URL The internal connection string for the database you created above
RAILS_MASTER_KEY Paste contents of the config/master.key file

That's it! You can now finalize your service deployment. It will be live on your .onrender.com URL as soon as the build finishes.

Additional Notes

By default, Render uses the latest LTS version of Ruby. You can also modify the version of Ruby used by specifying it in .ruby-version at the root of your project, or in your Gemfile like this:

ruby '2.7.1'

Top comments (0)