Skip to content
Back to Deployment

Deploying Ruby on Rails

Convention-over-configuration Ruby framework with Puma, Kamal, or Heroku, plus asset pipeline and Sidekiq.

PlatformsAdvanced

Why

Rails' convention-over-configuration and rich defaults (ActiveRecord, ActionPack) enable rapid development. Kamal (formerly MRSK) provides zero-downtime Docker deploys to any server without Kubernetes.

Platform-as-a-Service adoption grew 24% in 2024 as teams shift from VM management to git-push deploys. the cloud infrastructure market reached $330B in 2024, growing 22% year-over-year (Synergy Research), and PaaS layers capture the majority of new workloads.

When

Use Rails for Ruby web apps, MVPs, and teams valuing developer happiness. Choose Kamal for VPS deploys; Heroku for simplicity.

How

1. Build — bundle install --deployment, RAILS_ENV=production bundle exec rake assets:precompile 2. Puma — bundle exec puma -C config/puma.rb, multi-worker web server 3. Kamal — kamal deploy, zero-downtime Docker to VPS via SSH 4. Heroku — git push heroku main, auto-builds with buildpacks 5. DB — rails db:migrate on deploy (release phase on Heroku) 6. Sidekiq — bundle exec sidekiq for async jobs, Redis required 7. Env — RAILS_ENV=production, SECRET_KEY_BASE, DATABASE_URL

Example

# Dockerfile — Rails + Puma FROM ruby:3.3-slim AS build WORKDIR /app COPY Gemfile Gemfile.lock ./ RUN bundle install --deployment COPY . . RUN RAILS_ENV=production bundle exec rake assets:precompile FROM ruby:3.3-slim WORKDIR /app COPY --from=build /app /app EXPOSE 3000 CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"] # config/puma.rb — production workers ENV.fetch("WEB_CONCURRENCY", 2).to_i threads_count = ENV.fetch("RAILS_MAX_THREADS", 5).to_i threads threads_count, threads_count preload_app! # config/deploy.yml — Kamal service: myapp image: myuser/myapp servers: - 203.0.113.10 env: clear: RAILS_ENV: production secret: - DATABASE_URL - SECRET_KEY_BASE

Common Problems

  • ⚠Assets missing in production — forgot assets:precompile or config.assets.compile=false
  • ⚠Puma single worker — not using WEB_CONCURRENCY, only one CPU core utilized
  • ⚠Sidekiq jobs silently fail — Redis not configured or Sidekiq process not running

Best Practices

  • ✓Use Kamal for zero-downtime Docker deploys to VPS — simpler than Kubernetes, no extra infra
  • ✓Set preload_app! in Puma — saves memory by sharing code between workers via copy-on-write
  • ✓Set up health checks and graceful shutdown — handle SIGTERM to drain in-flight requests before exit

FAQ