PreviewDrop for Rails

Deploy previews for Ruby on Rails apps

Push a branch, get a live preview URL. PreviewDrop builds your Rails container and posts the link to the pull request in under 60 seconds — no CI scripts, no serverless rewrites.

TL;DR
Add a Dockerfile, connect your repo, push. PreviewDrop detects the push, builds the image, runs db:migrate, and posts a TLS-terminated PR preview URL. Puma runs as a persistent process — Action Cable, background jobs, long-polling endpoints all work the same way they do in production.

Dockerfile

Drop this at the root of your repo. PreviewDrop picks it up on the next push and builds it into a container behind a TLS-terminated subdomain.

Dockerfile
FROM ruby:3.3-slim RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY Gemfile Gemfile.lock ./ RUN bundle install --without development test COPY . . RUN SECRET_KEY_BASE=placeholder bundle exec rails assets:precompile RAILS_ENV=production EXPOSE 3000 CMD sh -c "bundle exec rails db:migrate && bundle exec rails server -b 0.0.0.0 -p ${PORT:-3000} -e production"

Environment variables

Set these in the Variables tab of your PreviewDrop project. They're encrypted at rest and injected into every preview container at start.

VariableExample valueNote
SECRET_KEY_BASE$(bundle exec rails secret)Required in production mode. Generate one with: bundle exec rails secret
RAILS_ENVproductionSet to production so Puma uses the correct config and assets are served.
RAILS_SERVE_STATIC_FILESenabledRails disables static file serving in production by default. This env var re-enables it.
DATABASE_URLpostgres://user:pass@host:5432/dbPoint at a shared dev DB or omit to use SQLite (fine for UI-only previews).

Common gotchas

SECRET_KEY_BASE is required in production mode

Rails raises an error at startup if SECRET_KEY_BASE is missing in production. Generate one with bundle exec rails secret and paste it into the PreviewDrop project variables. For previews, any long random string works — don't reuse your production secret.

RAILS_SERVE_STATIC_FILES must be set

By default Rails does not serve static assets in production — it expects nginx to do that. PreviewDrop containers don't have nginx in front. Set RAILS_SERVE_STATIC_FILES=enabled so the Puma process serves the precompiled assets itself.

Asset precompilation needs a placeholder SECRET_KEY_BASE

The Dockerfile runs assets:precompile at build time with a throw-away SECRET_KEY_BASE=placeholder. This is intentional — the real secret is injected at runtime, not baked into the image.

Node.js required for asset pipeline

The Dockerfile installs nodejs for Sprockets / importmap. If you use Webpacker or esbuild add yarn to the apt-get line and run your JS build step before assets:precompile.

Why not Vercel or Netlify?

Rails is a long-running server process — not compatible with serverless functions. Action Cable (WebSockets), Sidekiq workers, long-polling endpoints, and multi-second requests don't fit the serverless model that Vercel and Netlify use for backend code. PreviewDrop runs your Dockerfile directly: Puma, Action Cable, background jobs — the full Rails stack as a PR deploy preview, with the same container shape as your production environment.

Preview your Rails app in 5 minutes

Connect a repo, push a branch, get a URL. No credit card, no trial clock.

Start free