Deploying Ruby Applications
This comprehensive guide covers everything you need to know about deploying Ruby applications via Deploy with Git, from simple Sinatra apps to full Rails applications.
Overview
Deploy with Git automatically detects Ruby applications by looking for:
Gemfile(primary indicator)Gemfile.lockfor dependency resolution.ruby-versionfor version specification (optional)config.rufor Rack applications
Basic Ruby Deployment
Simple Sinatra API
docker run -d \
--name sinatra-api \
-e GIT_REPO_URL=https://github.com/your-username/sinatra-api \
-e APP_PORT=4567 \
-p 4567:4567 \
runonflux/orbit:latest
What Happens Automatically
- Detection: Finds
Gemfileand identifies as Ruby project - Version Selection:
- Checks
RUBY_VERSIONenvironment variable - Checks
.ruby-versionfile - Checks
rubydirective in Gemfile (e.g.,ruby '3.2.0') - Falls back to Ruby 3.0.0
- Checks
- Runtime Installation:
- Downloads and installs Ruby via rbenv
- Installs to
/opt/flux-tools/rbenv - Configures PATH and gem environment
- Dependencies: Runs
bundle install --deployment --without development test - Build: Precompiles assets if Rails app detected
- Start: Executes appropriate server command (rails, rackup, ruby, etc.)
Framework-Specific Guides
Ruby on Rails
Rails is a full-stack web framework for Ruby. Deploy with Git automatically detects and optimizes Rails applications:
docker run -d \
--name rails-app \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e RUBY_VERSION=3.2.0 \
-e RAILS_ENV=production \
-p 3000:3000 \
runonflux/orbit:latest
Example config/puma.rb (recommended):
# Puma configuration for production
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
preload_app!
port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "production" }
on_worker_boot do
ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end
# Bind to 0.0.0.0 for container networking
bind "tcp://0.0.0.0:#{ENV.fetch('PORT') { 3000 }}"
Important Rails Configuration:
- Asset Precompilation: Automatically runs
rails assets:precompile - Database Migrations: Use deployment hooks (see below)
- Secret Key: Set
SECRET_KEY_BASEenvironment variable
Sinatra Framework
Sinatra is a lightweight DSL for creating web applications:
docker run -d \
--name sinatra-api \
-e GIT_REPO_URL=https://github.com/your-username/sinatra-api \
-e APP_PORT=4567 \
-p 4567:4567 \
runonflux/orbit:latest
Example app.rb:
require 'sinatra'
require 'json'
set :bind, '0.0.0.0'
set :port, ENV['APP_PORT'] || 4567
get '/health' do
content_type :json
{ status: 'healthy' }.to_json
end
get '/' do
'Hello from Sinatra on Flux!'
end
Example config.ru:
require './app'
run Sinatra::Application
Hanami Framework
Hanami is a modern web framework for Ruby:
docker run -d \
--name hanami-app \
-e GIT_REPO_URL=https://github.com/your-username/hanami-app \
-e APP_PORT=2300 \
-p 2300:2300 \
runonflux/orbit:latest
Rack Applications
For custom Rack applications with config.ru:
docker run -d \
--name rack-app \
-e GIT_REPO_URL=https://github.com/your-username/rack-app \
-e APP_PORT=9292 \
-p 9292:9292 \
runonflux/orbit:latest
Version Management
Specify Ruby Version
Option 1: Environment Variable
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/ruby-app \
-e APP_PORT=3000 \
-e RUBY_VERSION=3.2.0 \
-p 3000:3000 \
runonflux/orbit:latest
Option 2: .ruby-version File
3.2.0
Option 3: Gemfile
source 'https://rubygems.org'
ruby '3.2.0'
gem 'rails', '~> 7.0'
gem 'puma', '~> 6.0'
Build Configuration
Asset Precompilation (Rails)
Rails assets are automatically precompiled in production mode:
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e RAILS_ENV=production \
-e SECRET_KEY_BASE=your-secret-key \
-p 3000:3000 \
runonflux/orbit:latest
Custom Build Command
Override the default build command if needed:
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/ruby-app \
-e APP_PORT=3000 \
-e BUILD_COMMAND="bundle exec rake custom:build" \
-p 3000:3000 \
runonflux/orbit:latest
Custom Run Command
Override the default run command:
docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e RUN_COMMAND="bundle exec puma -C config/puma.rb" \
-p 3000:3000 \
runonflux/orbit:latest
Environment Variables
Ruby-Specific Variables
| Variable | Description | Default |
|---|---|---|
RUBY_VERSION | Ruby version to install | Auto-detected from Gemfile |
RAILS_ENV | Rails environment | production |
RACK_ENV | Rack environment | production |
BUNDLE_WITHOUT | Bundle groups to exclude | development test |
Rails Application Variables
docker run -d \
--name rails-app \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e RUBY_VERSION=3.2.0 \
-e RAILS_ENV=production \
-e SECRET_KEY_BASE=your-very-long-secret-key \
-e DATABASE_URL=postgresql://user:pass@db:5432/mydb \
-e REDIS_URL=redis://redis:6379/0 \
-e RAILS_LOG_TO_STDOUT=true \
-e RAILS_SERVE_STATIC_FILES=true \
-p 3000:3000 \
runonflux/orbit:latest
Advanced Scenarios
Monorepo - Deploy Specific Service
docker run -d \
--name rails-admin \
-e GIT_REPO_URL=https://github.com/your-username/monorepo \
-e PROJECT_PATH=apps/admin \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
Private Repository
docker run -d \
--name private-rails-app \
-e GIT_REPO_URL=https://github.com/your-username/private-app \
-e GIT_TOKEN=ghp_your_personal_access_token \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest
With Database Migrations
Create pre-deploy.sh in your repository root:
#!/bin/bash
# Run database migrations before deployment
echo "Running database migrations..."
bundle exec rails db:migrate RAILS_ENV=production
Create post-deploy.sh:
#!/bin/bash
# Clear cache after deployment
echo "Clearing Rails cache..."
bundle exec rails cache:clear RAILS_ENV=production
docker run -d \
--name rails-app-with-migrations \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e DATABASE_URL=postgresql://user:pass@db:5432/mydb \
-p 3000:3000 \
runonflux/orbit:latest
Learn more: Deployment Hooks Guide
CI/CD Integration
Automatic Deployment with Webhooks
docker run -d \
--name rails-app \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e API_KEY=your-secret-api-key \
-p 3000:3000 \
-p 9001:9001 \
runonflux/orbit:latest
Configure GitHub Webhook:
- Payload URL:
https://your-app-9001.app.runonflux.io/webhook - Content type:
application/json - Secret: Not needed (use X-API-Key header instead)
- Events: Just the
pushevent
Add API Key Header:
Use X-API-Key: your-secret-api-key in your webhook configuration.
Polling for Updates
docker run -d \
--name rails-app \
-e GIT_REPO_URL=https://github.com/your-username/rails-app \
-e APP_PORT=3000 \
-e POLLING_INTERVAL=300 \
-p 3000:3000 \
runonflux/orbit:latest
Troubleshooting
Asset Compilation Fails
Problem: "Asset precompilation failed"
Solution: Ensure Node.js is available for JavaScript runtime (automatically installed if detected):
# Gemfile
gem 'mini_racer' # Or 'therubyracer'
Or explicitly set Node.js version:
-e NODE_VERSION=20
Bundle Install Fails
Problem: Native extension build errors
Solution: Deploy with Git includes build-essential and common libraries. For additional dependencies, use deployment hooks:
#!/bin/bash
# pre-deploy.sh
apt-get update && apt-get install -y libspecial-dev
Server Not Binding to Port
Problem: Application not accessible
Solution: Ensure your server binds to 0.0.0.0 (not localhost):
# Puma config
bind "tcp://0.0.0.0:#{ENV.fetch('PORT') { 3000 }}"
# Sinatra
set :bind, '0.0.0.0'
# Rackup
# Use 'rackup -o 0.0.0.0 -p $PORT'
Database Connection Issues
Problem: Can't connect to database
Solution: Use DATABASE_URL environment variable:
-e DATABASE_URL=postgresql://user:pass@host:5432/dbname
And in config/database.yml:
production:
url: <%= ENV['DATABASE_URL'] %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
Secret Key Base Missing
Problem: Rails requires SECRET_KEY_BASE in production
Solution: Generate and set secret key:
# Generate a secret key locally
rails secret
# Use it in deployment
-e SECRET_KEY_BASE=the-generated-secret-key
Memory Issues During Asset Compilation
Problem: Out of memory during rails assets:precompile
Solution: Increase Node.js heap size:
-e NODE_OPTIONS="--max-old-space-size=2048"
Performance Tips
-
Use Puma: Configure workers and threads appropriately
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count -
Preload App: Enable
preload_app!in Puma config for faster worker spawning -
Database Connection Pooling: Match pool size to thread count
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> -
Dependency Caching: Dependencies are cached based on Gemfile.lock hash - no reinstall if unchanged
-
Asset Pipeline: Use Sprockets or Webpacker efficiently, enable CDN for assets in production
-
Health Checks: Implement
/healthendpoint for faster deployment verification# config/routes.rb
get '/health', to: proc { [200, {}, ['OK']] }
Example Repository Structure
my-rails-app/
├── Gemfile # Ruby dependencies
├── Gemfile.lock # Locked dependency versions
├── .ruby-version # Optional: Pin Ruby version
├── config.ru # Rack configuration
├── pre-deploy.sh # Optional: Run migrations
├── post-deploy.sh # Optional: Cache warming
├── app/
│ ├── controllers/
│ ├── models/
│ └── views/
├── config/
│ ├── database.yml
│ ├── routes.rb
│ └── puma.rb
├── db/
│ └── migrate/
└── public/
└── assets/ # Compiled assets
Common Rails Gems for Production
# Gemfile
source 'https://rubygems.org'
ruby '3.2.0'
# Core
gem 'rails', '~> 7.0'
gem 'puma', '~> 6.0' # Application server
gem 'bootsnap', require: false # Faster boot times
# Database
gem 'pg', '~> 1.5' # PostgreSQL
# gem 'mysql2', '~> 0.5' # MySQL alternative
# Performance
gem 'redis', '~> 5.0' # Caching/sessions
gem 'rack-timeout' # Request timeouts
# Assets
gem 'sprockets-rails' # Asset pipeline
# gem 'webpacker', '~> 5.0' # Alternative: Webpack
# Production
gem 'rack-attack' # Rate limiting
gem 'rack-cors' # CORS for APIs
group :development, :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
end