How to deploy Rails and Sidekiq to Render

This article shows how to deploy a typical Rails application with custom Dockerfile to Render. We’ll deploy Rails and Sidekiq processes as well as PostgreSQL and Redis databases. We’ll also see how to add automatic pull request previews.

Render

Render is a hosting company not too different from Heroku. There are two ways of deploying your applications to Render. We can either manually deploy services from the console interface, or with Render’s infrastructure as code by writing down a blueprint file.

PostgreSQL and Redis

Before we’ll deploy the Rails and Sidekiq process we’ll create databases so the services can connect successfuly during deploy.

  • To create PostgreSQL database go to “New” -> “PostgreSQL”, choose a name, database name, user and region. I’ll assume template_db as a name, and template_db as a database and user names.

    Tip: You can directly connect your DataDog monitoring on this screen by providing Datadog API Key.

    After creating, note the DATABASE_URL value, e.g. postgres://template:mfXsKZ0XISq7qrjA5vKZd3gG1ojcjRzV@dpg-ce9ofl94reb49l4g6n90-a/template_f7g3

  • To create Redis database go to “New” -> “Redis”, choose a name and region.

    I’ll assume template_redis as a name.

    After creating, note the REDIS_URL value, e.g. redis://red-ce9og294reb49l4gbq50:6379.

Dockerfile considerations

Before we head down to add a new Rails service, we’ll edit the Business Class Dockerfile a little.

First we want to serve assets directly as we don’t have CDN at the moment. Uncomment the following line:

# Serve assets directly
ENV RAILS_SERVE_STATIC_FILES=true

Second, change the final CMD to include automatic check for migrations:

# Configure the main process to run when running the image
CMD bundle exec rails db:migrate && bundle exec puma -C config/puma.rb

This is important since Render currently doesn’t have a specific release step, so migrations have to happen during build time or before restarting the Rails process.

Rails and Sidekiq

Now we should be ready to add the main web and background processes.

  • Choose “New” -> “Web Service”, connect your GitHub or GitLab repository, and then choose Docker environment in the next step.

    Make sure to add the RUBY_VERSION, DATABASE_URL, REDIS_URL, and SECRET_KEY_BASE variables.

    You can generate a new secret by running rails secret

After clicking “Create Web service” your new web service should start its build and be deployed in a couple of minutes.

  • Choose “New” -> “Background Worker”, and input the same environment variables. Sidekiq process is not really all that different to a Rails process after all.

Note: You can also store secret files (like .env or .npmrc files and private keys) in Render. These files will then be available during builds and in your code just like regular files.

Blueprint configuration

If we prefer to maintain our services in a more pragmatic way, we can write a blueprint file.

Here’s a complete blueprint for what we did manually in previous steps:

# render.yaml
# See https://render.com/docs/blueprint-spec for details
services:
  - type: web
    name: template_rails
    env: docker
    repo: https://gitlab.com/user/application.git
    region: oregon # optional (defaults to oregon)
    plan: free # optional (defaults to starter)
    branch: master # optional (defaults to master)
    numInstances: 1 # optional (defaults to 1)
    healthCheckPath: /
    envVars:
      - key: RUBY_VERSION
        value: "3.0.1"
      - key: SECRET_KEY_BASE
        value: "0e3b249272a7f1ea40b719317f677d2d54b3d1c5835c0292344a8de5b1a41f945cf7a70d15d8394ac96f01df867435a2aa8586ee9831d1b059ae5eea3b19fffd"
      - key: DATABASE_URL
        fromDatabase:
          name: template_db
          property: connectionString
      - key: REDIS_URL
        fromService:
          type: redis
          name: template_redis
          property: connectionString

  - type: worker
    name: sidekiq
    env: docker

  - type: redis
    name: template_redis
    ipAllowList: []
    plan: free # optional (defaults to starter)
    maxmemoryPolicy: noeviction # optional (defaults to allkeys-lru)

databases:
  - name: template_db
    databaseName: template_db # optional (Render may add a suffix)
    user: template_db # optional
    plan: free
    postgresMajorVersion: 15
    ipAllowList: []

The above blueprint file can be saved as render.yaml (note it cannot be render.yml) and added from the console under “Blueprints” tab next to the “Dashboard” link. Make sure the file is commited to the repository.

Conclusion

This is one of the most minimal Render setups for Ruby on Rails applications, including the default Business Class code, and apart from deploying a separate worker process can be even run for free (with the limitations of the free plan).