Ruby on Rails Production Stack
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-alpine4 environment: 5 - POSTGRES_USER=rails6 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}7 - POSTGRES_DB=rails_production8 volumes: 9 - postgres_data:/var/lib/postgresql/data10 networks: 11 - rails_net1213 redis: 14 image: redis:7-alpine15 volumes: 16 - redis_data:/data17 networks: 18 - rails_net1920 rails: 21 build: 22 context: .23 dockerfile: Dockerfile24 command: bundle exec puma -C config/puma.rb25 environment: 26 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production27 - REDIS_URL=redis://redis:6379/028 - SECRET_KEY_BASE=${SECRET_KEY_BASE}29 - RAILS_ENV=production30 - RAILS_SERVE_STATIC_FILES=true31 volumes: 32 - rails_storage:/app/storage33 depends_on: 34 - postgres35 - redis36 networks: 37 - rails_net3839 sidekiq: 40 build: 41 context: .42 dockerfile: Dockerfile43 command: bundle exec sidekiq44 environment: 45 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production46 - REDIS_URL=redis://redis:6379/047 - SECRET_KEY_BASE=${SECRET_KEY_BASE}48 - RAILS_ENV=production49 depends_on: 50 - postgres51 - redis52 networks: 53 - rails_net5455 nginx: 56 image: nginx:alpine57 ports: 58 - "80:80"59 - "443:443"60 volumes: 61 - ./nginx.conf:/etc/nginx/nginx.conf:ro62 depends_on: 63 - rails64 networks: 65 - rails_net6667volumes: 68 postgres_data: 69 redis_data: 70 rails_storage: 7172networks: 73 rails_net: .env Template
.env
1# Rails Production2POSTGRES_PASSWORD=secure_postgres_password3SECRET_KEY_BASE=your_very_long_secret_key_base_here45# Rails at http://localhostUsage Notes
- 1Rails at http://localhost
- 2Run db:migrate before start
- 3Precompile assets
- 4Sidekiq for background jobs
- 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 file2cat > docker-compose.yml << 'EOF'3services:4 postgres:5 image: postgres:15-alpine6 environment:7 - POSTGRES_USER=rails8 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}9 - POSTGRES_DB=rails_production10 volumes:11 - postgres_data:/var/lib/postgresql/data12 networks:13 - rails_net1415 redis:16 image: redis:7-alpine17 volumes:18 - redis_data:/data19 networks:20 - rails_net2122 rails:23 build:24 context: .25 dockerfile: Dockerfile26 command: bundle exec puma -C config/puma.rb27 environment:28 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production29 - REDIS_URL=redis://redis:6379/030 - SECRET_KEY_BASE=${SECRET_KEY_BASE}31 - RAILS_ENV=production32 - RAILS_SERVE_STATIC_FILES=true33 volumes:34 - rails_storage:/app/storage35 depends_on:36 - postgres37 - redis38 networks:39 - rails_net4041 sidekiq:42 build:43 context: .44 dockerfile: Dockerfile45 command: bundle exec sidekiq46 environment:47 - DATABASE_URL=postgres://rails:${POSTGRES_PASSWORD}@postgres:5432/rails_production48 - REDIS_URL=redis://redis:6379/049 - SECRET_KEY_BASE=${SECRET_KEY_BASE}50 - RAILS_ENV=production51 depends_on:52 - postgres53 - redis54 networks:55 - rails_net5657 nginx:58 image: nginx:alpine59 ports:60 - "80:80"61 - "443:443"62 volumes:63 - ./nginx.conf:/etc/nginx/nginx.conf:ro64 depends_on:65 - rails66 networks:67 - rails_net6869volumes:70 postgres_data:71 redis_data:72 rails_storage:7374networks:75 rails_net:76EOF7778# 2. Create the .env file79cat > .env << 'EOF'80# Rails Production81POSTGRES_PASSWORD=secure_postgres_password82SECRET_KEY_BASE=your_very_long_secret_key_base_here8384# Rails at http://localhost85EOF8687# 3. Start the services88docker compose up -d8990# 4. View logs91docker compose logs -fOne-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 | bashTroubleshooting
- 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
Components
railspumasidekiqpostgresqlredisnginx
Tags
#rails#ruby#puma#sidekiq#production
Category
Full Web StacksAd Space
Shortcuts: C CopyF FavoriteD Download