docker.recipes

Ruby on Rails Production Stack

advanced

Production Rails with Puma, Sidekiq, PostgreSQL, and Redis.

Overview

Ruby on Rails is a full-stack web application framework built on Ruby that follows convention-over-configuration principles, enabling rapid development of database-backed web applications. Created by David Heinemeier Hansson in 2004, Rails popularized the Model-View-Controller (MVC) architecture and RESTful design patterns, making it the backbone for companies like GitHub, Shopify, and Basecamp. This production stack combines Rails with Puma as the multi-threaded web server, Sidekiq for background job processing, PostgreSQL for robust data persistence, Redis for caching and job queues, and Nginx for reverse proxy and static file serving. The architecture addresses critical production concerns including horizontal scaling through Puma's thread-based concurrency, asynchronous job processing via Sidekiq, high-performance caching with Redis, and enterprise-grade data integrity through PostgreSQL's ACID compliance. This configuration is ideal for growing startups transitioning from development to production, established companies running Rails applications at scale, and teams requiring a battle-tested stack that can handle complex business logic, background processing, and high-traffic scenarios while maintaining Rails' developer productivity advantages.

Key Features

  • Puma multi-threaded web server with configurable worker processes and thread pools for concurrent request handling
  • Sidekiq background job processing with Redis-backed queues supporting retry logic and job scheduling
  • PostgreSQL ACID-compliant database with JSON/JSONB support for mixed relational and document data models
  • Redis in-memory data store providing sub-millisecond response times for session storage and caching layers
  • Nginx reverse proxy with SSL/TLS termination, static file serving, and load balancing capabilities
  • Rails Active Storage integration for file uploads with configurable storage backends
  • Production-optimized environment variables including SECRET_KEY_BASE and database connection pooling
  • Containerized asset pipeline with precompiled assets for optimized static resource delivery

Common Use Cases

  • 1E-commerce platforms requiring background order processing, inventory management, and payment handling
  • 2Content management systems with file uploads, caching, and complex user permission hierarchies
  • 3SaaS applications needing multi-tenancy, scheduled jobs, and real-time notifications
  • 4API backends for mobile applications with database-heavy operations and background sync processes
  • 5Enterprise web applications requiring audit trails, complex reporting, and data integrity guarantees
  • 6Startup MVPs transitioning from development to production with scalable architecture patterns
  • 7Legacy Rails applications being containerized for cloud deployment and DevOps automation

Prerequisites

  • Minimum 2GB RAM (1GB+ for PostgreSQL, 512MB+ for Redis, 512MB+ for Rails/Puma processes)
  • Ruby application with Gemfile containing rails, puma, sidekiq, and pg gems
  • Dockerfile configured for Rails production environment with asset precompilation
  • Environment variables: POSTGRES_PASSWORD, SECRET_KEY_BASE for secure deployment
  • Nginx configuration file (nginx.conf) with upstream Rails server definitions
  • Rails database migrations and schema ready for production deployment

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 postgres:
3 image: postgres:15-alpine
4 environment:
5 - POSTGRES_USER=rails
6 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
7 - POSTGRES_DB=rails_production
8 volumes:
9 - postgres_data:/var/lib/postgresql/data
10 networks:
11 - rails_net
12
13 redis:
14 image: redis:7-alpine
15 volumes:
16 - redis_data:/data
17 networks:
18 - rails_net
19
20 rails:
21 build:
22 context: .
23 dockerfile: Dockerfile
24 command: bundle exec puma -C config/puma.rb
25 environment:
26 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production
27 - REDIS_URL=redis://redis:6379/0
28 - SECRET_KEY_BASE=${SECRET_KEY_BASE}
29 - RAILS_ENV=production
30 - RAILS_SERVE_STATIC_FILES=true
31 volumes:
32 - rails_storage:/app/storage
33 depends_on:
34 - postgres
35 - redis
36 networks:
37 - rails_net
38
39 sidekiq:
40 build:
41 context: .
42 dockerfile: Dockerfile
43 command: bundle exec sidekiq
44 environment:
45 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production
46 - REDIS_URL=redis://redis:6379/0
47 - SECRET_KEY_BASE=${SECRET_KEY_BASE}
48 - RAILS_ENV=production
49 depends_on:
50 - postgres
51 - redis
52 networks:
53 - rails_net
54
55 nginx:
56 image: nginx:alpine
57 ports:
58 - "80:80"
59 - "443:443"
60 volumes:
61 - ./nginx.conf:/etc/nginx/nginx.conf:ro
62 depends_on:
63 - rails
64 networks:
65 - rails_net
66
67volumes:
68 postgres_data:
69 redis_data:
70 rails_storage:
71
72networks:
73 rails_net:

.env Template

.env
1# Rails Production
2POSTGRES_PASSWORD=secure_postgres_password
3SECRET_KEY_BASE=your_very_long_secret_key_base_here
4
5# Rails at http://localhost

Usage Notes

  1. 1Rails at http://localhost
  2. 2Run db:migrate before start
  3. 3Precompile assets
  4. 4Sidekiq for background jobs
  5. 5Active Storage configured

Individual Services(5 services)

Copy individual services to mix and match with your existing compose files.

postgres
postgres:
  image: postgres:15-alpine
  environment:
    - POSTGRES_USER=rails
    - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    - POSTGRES_DB=rails_production
  volumes:
    - postgres_data:/var/lib/postgresql/data
  networks:
    - rails_net
redis
redis:
  image: redis:7-alpine
  volumes:
    - redis_data:/data
  networks:
    - rails_net
rails
rails:
  build:
    context: .
    dockerfile: Dockerfile
  command: bundle exec puma -C config/puma.rb
  environment:
    - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production
    - REDIS_URL=redis://redis:6379/0
    - SECRET_KEY_BASE=${SECRET_KEY_BASE}
    - RAILS_ENV=production
    - RAILS_SERVE_STATIC_FILES=true
  volumes:
    - rails_storage:/app/storage
  depends_on:
    - postgres
    - redis
  networks:
    - rails_net
sidekiq
sidekiq:
  build:
    context: .
    dockerfile: Dockerfile
  command: bundle exec sidekiq
  environment:
    - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production
    - REDIS_URL=redis://redis:6379/0
    - SECRET_KEY_BASE=${SECRET_KEY_BASE}
    - RAILS_ENV=production
  depends_on:
    - postgres
    - redis
  networks:
    - rails_net
nginx
nginx:
  image: nginx:alpine
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
  depends_on:
    - rails
  networks:
    - rails_net

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 postgres:
5 image: postgres:15-alpine
6 environment:
7 - POSTGRES_USER=rails
8 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
9 - POSTGRES_DB=rails_production
10 volumes:
11 - postgres_data:/var/lib/postgresql/data
12 networks:
13 - rails_net
14
15 redis:
16 image: redis:7-alpine
17 volumes:
18 - redis_data:/data
19 networks:
20 - rails_net
21
22 rails:
23 build:
24 context: .
25 dockerfile: Dockerfile
26 command: bundle exec puma -C config/puma.rb
27 environment:
28 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production
29 - REDIS_URL=redis://redis:6379/0
30 - SECRET_KEY_BASE=${SECRET_KEY_BASE}
31 - RAILS_ENV=production
32 - RAILS_SERVE_STATIC_FILES=true
33 volumes:
34 - rails_storage:/app/storage
35 depends_on:
36 - postgres
37 - redis
38 networks:
39 - rails_net
40
41 sidekiq:
42 build:
43 context: .
44 dockerfile: Dockerfile
45 command: bundle exec sidekiq
46 environment:
47 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production
48 - REDIS_URL=redis://redis:6379/0
49 - SECRET_KEY_BASE=${SECRET_KEY_BASE}
50 - RAILS_ENV=production
51 depends_on:
52 - postgres
53 - redis
54 networks:
55 - rails_net
56
57 nginx:
58 image: nginx:alpine
59 ports:
60 - "80:80"
61 - "443:443"
62 volumes:
63 - ./nginx.conf:/etc/nginx/nginx.conf:ro
64 depends_on:
65 - rails
66 networks:
67 - rails_net
68
69volumes:
70 postgres_data:
71 redis_data:
72 rails_storage:
73
74networks:
75 rails_net:
76EOF
77
78# 2. Create the .env file
79cat > .env << 'EOF'
80# Rails Production
81POSTGRES_PASSWORD=secure_postgres_password
82SECRET_KEY_BASE=your_very_long_secret_key_base_here
83
84# Rails at http://localhost
85EOF
86
87# 3. Start the services
88docker compose up -d
89
90# 4. View logs
91docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/rails-production/run | bash

Troubleshooting

  • ActiveRecord::ConnectionNotEstablished: Verify DATABASE_URL format and ensure PostgreSQL container is running before Rails startup
  • Redis::CannotConnectError in Sidekiq: Check REDIS_URL environment variable and confirm Redis container accessibility on port 6379
  • Puma workers timing out under load: Adjust thread pool settings in config/puma.rb and increase container memory allocation
  • Rails asset compilation failures: Ensure RAILS_ENV=production and SECRET_KEY_BASE are set during Docker build process
  • 502 Bad Gateway from Nginx: Verify Rails application is binding to 0.0.0.0 rather than localhost in Puma configuration
  • Sidekiq jobs not processing: Confirm background job classes are loaded and Redis connection pool size accommodates worker threads

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space