Back to Blog
Tutorial8 min read2026-05-01

How to Deploy Ruby on Rails to the Cloud

Deploy a Ruby on Rails application to PandaStack using Docker — containerise with Puma, connect PostgreSQL, and ship via GitHub.

Deploy Ruby on Rails to Production

Ruby on Rails is a battle-tested full-stack framework that shaped modern web development. Despite newer entrants, Rails remains a powerhouse for rapidly building database-backed web applications, APIs, and internal tools. Rails 8 in 2026 brings Solid Queue, Solid Cache, and Kamal for deployments — but for teams using Docker and a PaaS, the container route is straightforward and reliable.

PandaStack runs Rails as a Docker container, provides managed PostgreSQL, and deploys on every GitHub push.

Prerequisites

  • Ruby 3.3+ installed locally (rbenv or asdf recommended)
  • Rails 7.2+ installed
  • Docker installed locally
  • A GitHub account
  • PandaStack CLI: npm install -g @pandastack/cli

Step 1 — Create a Rails Application

gem install rails
rails new my-rails-app --database=postgresql --api
cd my-rails-app

The --api flag creates a lightweight Rails app without views and browser middleware — ideal for REST APIs. Remove it if you need a full-stack app with HTML views.

Add a health check and a sample endpoint. Create app/controllers/health_controller.rb:

class HealthController < ApplicationController
  def index
    render json: { status: 'ok' }
  end
end

Create app/controllers/api/v1/hello_controller.rb:

module Api
  module V1
    class HelloController < ApplicationController
      def index
        render json: { message: 'Hello from PandaStack!' }
      end
    end
  end
end

Add routes in config/routes.rb:

Rails.application.routes.draw do
  get '/health', to: 'health#index'

  namespace :api do
    namespace :v1 do
      get '/hello', to: 'hello#index'
    end
  end
end

Step 2 — Write a Production Dockerfile

FROM ruby:3.3-alpine

RUN apk add --no-cache     build-base     nodejs     npm     postgresql-dev     tzdata     curl

WORKDIR /app

COPY Gemfile Gemfile.lock ./
RUN bundle config set --local without 'development test'     && bundle install --jobs 4 --retry 3

COPY . .

ENV RAILS_ENV=production
ENV RAILS_LOG_TO_STDOUT=true

RUN bundle exec rails assets:precompile 2>/dev/null || true

EXPOSE 3000

CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

The || true on assets:precompile is safe for API-only apps that have no asset pipeline. For full-stack apps, ensure SECRET_KEY_BASE is set as a build arg or environment variable.

Add a .dockerignore:

.git
log/
tmp/
node_modules/
.env

Build and test locally:

docker build -t my-rails-app .
docker run -p 3000:3000   -e DATABASE_URL=postgresql://postgres:password@host.docker.internal:5432/myapp_dev   -e SECRET_KEY_BASE=$(rails secret)   my-rails-app
curl http://localhost:3000/health

Step 3 — Configure Puma for Production

Update config/puma.rb:

workers ENV.fetch("WEB_CONCURRENCY") { 2 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count

port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }

on_worker_boot do
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end

preload_app!

Step 4 — Configure pandastack.json

{
  "type": "container",
  "healthCheckPath": "/health"
}

Step 5 — Set Environment Variables

In the PandaStack dashboard under Environment Variables, add:

RAILS_ENV=production
RAILS_LOG_TO_STDOUT=true
SECRET_KEY_BASE=your-very-long-secret-key
DATABASE_URL=postgresql://user:password@pandastack-db-host:5432/rails_prod
WEB_CONCURRENCY=2
RAILS_MAX_THREADS=5

Generate a secret key:

rails secret
# Outputs a 128-character hex string — use this as SECRET_KEY_BASE

Step 6 — Provision a PostgreSQL Database

panda db create --type postgres --name rails-db

PandaStack adds the DATABASE_URL to your project environment automatically.

Step 7 — Push to GitHub and Deploy

git add .
git commit -m "Rails API with Docker and PandaStack config"
gh repo create my-rails-app --private --source=. --push
panda deploy

Or connect at [dashboard.pandastack.io](https://dashboard.pandastack.io) → New Project → select your GitHub repository.

After the first deployment, run database migrations:

panda exec -- bundle exec rails db:migrate RAILS_ENV=production

Verify the Deployment

curl https://my-rails-app.pandastack.io/health
# {"status":"ok"}

curl https://my-rails-app.pandastack.io/api/v1/hello
# {"message":"Hello from PandaStack!"}

panda logs --follow

Summary

Rails on PandaStack runs via Puma in a Docker container backed by managed PostgreSQL. Set SECRET_KEY_BASE, DATABASE_URL, and other secrets in the dashboard, push to GitHub, and PandaStack builds and deploys automatically. Full reference at [docs.pandastack.io](https://docs.pandastack.io).

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also