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-appThe --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
endCreate 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
endAdd 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
endStep 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/
.envBuild 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/healthStep 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=5Generate a secret key:
rails secret
# Outputs a 128-character hex string — use this as SECRET_KEY_BASEStep 6 — Provision a PostgreSQL Database
panda db create --type postgres --name rails-dbPandaStack 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 deployOr 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=productionVerify 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 --followSummary
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).