Ruby Deployment — Deploying Ruby Applications with Docker, Capistrano, and Cloud Platforms
In this tutorial, you will learn about Ruby Deployment. We cover key concepts, practical examples, and best practices to help you master this topic.
Ruby deployment strategies include Docker containers for consistency, Capistrano for server automation, and cloud platforms like Render, Heroku, and Fly.io.
What You'll Learn
- Docker containerization for Ruby apps
- Cloud platform deployment
- Capistrano for traditional servers
- Environment management and CI/CD
Why It Matters
Reliable deployment is critical for production applications. GitHub deploys Rails hundreds of times daily. Shopify handles Black Friday traffic with Ruby deployment pipelines. DodaZIP uses Docker deployment for consistent environments.
Real-World Use
SaaS platforms, e-commerce sites, API services, background job processors, microservices.
flowchart LR
A["Deployment"] --> B["Docker"]
A --> C["Cloud Platforms"]
A --> D["Capistrano"]
A --> E["CI/CD"]
A:::current --> B
style A fill:#2563eb,stroke:#2563eb,color:#fff
style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b
Dockerfile
FROM ruby:3.3-slim
RUN apt-get update && apt-get install -y \
build-essential libpq-dev nodejs \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install --jobs 4
COPY . .
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
Docker Compose
version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/app
depends_on:
- db
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Render Deployment
# render.yaml
services:
- type: web
name: my-app
env: ruby
buildCommand: bundle install && bundle exec rails assets:precompile
startCommand: bundle exec rails server
envVars:
- key: DATABASE_URL
fromDatabase:
name: my-db
property: connectionString
databases:
- name: my-db
Heroku Deployment
# config/initializers/heroku.rb
# Heroku uses PORT environment variable
port = ENV.fetch("PORT", 3000)
heroku create my-app
heroku addons:create heroku-postgresql:mini
git push heroku main
heroku run rails db:migrate
heroku open
Capistrano
# config/deploy.rb
lock "~> 3.18"
set :application, "my_app"
set :repo_url, "git@github.com:user/my_app.git"
set :deploy_to, "/var/www/my_app"
set :linked_files, %w[config/database.yml config/master.key]
set :linked_dirs, %w[log tmp/pids tmp/cache tmp/sockets vendor/bundle]
namespace :deploy do
after :finishing, "deploy:cleanup"
end
cap production deploy
Environment Variables
# config/application.rb
module MyApp
class Application < Rails::Application
config.before_configuration do
env_file = Rails.root.join("config/local_env.yml")
if env_file.exist?
YAML.safe_load(File.read(env_file)).each do |key, value|
ENV[key.to_s] = value.to_s
end
end
end
end
end
CI/CD Pipeline
# .github/workflows/ci.yml
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: bundle exec rails db:create db:migrate
- run: bundle exec rspec
Common Mistakes
1. Hardcoding Secrets
# Bad: password = "secret123"
# Good: password = ENV["DB_PASSWORD"]
2. Forgetting Asset Precompilation
# Always run assets:precompile in production build
bundle exec rails assets:precompile
3. Not Using a Process Manager
Use Puma in production. Configure workers and threads properly for your server.
4. Skipping Database Migrations
# Always run migrations after deployment
bundle exec rails db:migrate
5. Missing Health Checks
Add a health check endpoint. Configure load balancers to use it for instance health monitoring.
Practice Questions
1. What is the advantage of Docker deployment? Consistent environment across development, CI, and production. No dependency conflicts.
2. How does Render differ from Heroku? Render offers predictable pricing, no container sleeping on free tier, and native Docker support.
3. What does Capistrano do? Automates deployment to servers. Creates releases with rollback support. Runs migrations and restarts servers.
4. Why use environment variables? Keep secrets out of code. Change configuration without redeploying. Follow twelve-factor app principles.
Challenge: Write a Dockerfile and docker-compose.yml for a Sinatra app with PostgreSQL.
Solution
FROM ruby:3.3-slim
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["ruby", "app.rb"]
version: "3.8"
services:
app:
build: .
ports:
- "4567:4567"
environment:
DATABASE_URL: postgres://postgres:password@db:5432/app
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: password
FAQ
{{< faq question="What is the best Ruby hosting platform?" >}} Render and Fly.io are popular choices. Heroku is convenient but expensive. For full control, use Docker on AWS ECS or DigitalOcean. {{< /faq >}}
{{< faq question="How do I handle database migrations in production?" >}}
Run rails db:migrate as part of deployment. Capistrano and CI/CD pipelines handle this automatically. Always backup before migrating.
{{< /faq >}}
{{< faq question="Should I use Puma or Unicorn?" >}} Puma is the modern default for Rails. It handles threads and clusters. Unicorn is single-threaded and uses forked workers. {{< /faq >}}
{{< faq question="How do I scale Ruby applications?" >}} Horizontal scaling with multiple server instances. Use a load balancer. Scale Sidekiq workers separately. Use database read replicas. {{< /faq >}}
{{< faq question="What monitoring tools work with Ruby?" >}} Honeybadger, Sentry, and Rollbar for error tracking. New Relic and Scout for performance monitoring. Datadog for infrastructure. {{< /faq >}}
Try It Yourself
# Create a minimal deployment setup
mkdir deploy-demo && cd deploy-demo
cat > Gemfile << 'EOF'
source "https://rubygems.org"
gem "sinatra"
gem "puma"
EOF
cat > app.rb << 'EOF'
require "sinatra"
get "/" { "Hello from #{ENV['RACK_ENV'] || 'development'}!" }
EOF
bundle install
RACK_ENV=production bundle exec ruby app.rb
Expected output — running Sinatra server on port 4567 in production environment.
What's Next
Now that you understand deployment, explore web APIs and building production services.
| Topic | Description | Link |
|---|---|---|
| Ruby Ecosystem | Community and tools | {{< ref "46-ecosystem" >}} |
| Go Deployment | Compare Go deployment | Go |
| Ruby Web APIs | Building APIs in Ruby | {{< ref "49-web-apis" >}} |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro