Rails Deployment with Kamal
Deploy Rails 8 applications to production using Kamal for zero-downtime Docker deployments. Covers Kamal configuration, Docker setup, environment secrets, database migrations, SSL certificates, and production best practices.
Kamal Overview
Kamal (formerly MRSK) is a deployment tool for Rails 8 that uses Docker and SSH to deploy applications to any server. No Kubernetes, no complex orchestration - just simple, reliable deployments.
Key Features:
-
Zero-downtime deployments with health checks
-
Automatic SSL with Let's Encrypt
-
Multi-server deployments
-
Rolling restarts
-
Easy rollbacks
-
Built-in load balancing with Traefik
Quick Start
- Install Kamal
Kamal comes with Rails 8
gem install kamal
Verify installation
kamal version
- Initialize Kamal
Generate Kamal configuration files
kamal init
Creates:
- config/deploy.yml # Main configuration
- .env.erb # Environment template
- .kamal/ # Kamal directory
- Configure Server
config/deploy.yml
service: my-blog-app image: your-username/my-blog-app
servers:
web:
hosts:
- 192.168.1.100 # Your server IP
labels:
traefik.http.routers.my-blog-app.rule: Host(example.com)
traefik.http.routers.my-blog-app-secure.entrypoints: websecure
traefik.http.routers.my-blog-app-secure.rule: Host(example.com)
traefik.http.routers.my-blog-app-secure.tls: true
traefik.http.routers.my-blog-app-secure.tls.certresolver: letsencrypt
registry: username: your-username password: - KAMAL_REGISTRY_PASSWORD
env: secret: - RAILS_MASTER_KEY clear: RAILS_ENV: production RAILS_LOG_TO_STDOUT: true
builder: multiarch: false
- Setup Server
Install Docker on remote server
kamal server bootstrap
Verify setup
kamal setup
- Deploy
First deployment
kamal deploy
Subsequent deployments
kamal deploy
Code Examples & Patterns
For detailed deployment patterns and examples, see examples.md.
Pattern Categories
examples.md contains:
-
Kamal Configuration - Complete deploy.yml examples for various setups
-
Docker Configuration - Multi-stage Dockerfile optimization
-
Environment Management - Secrets, credentials, environment variables
-
Database Migrations - Safe migration strategies in production
-
SSL/TLS Setup - Let's Encrypt and custom certificates
-
Multi-Server Deployment - Load balancing across servers
-
Background Jobs - Deploying Solid Queue workers
-
Health Checks - Endpoint configuration for zero-downtime
-
Rollback Procedures - Recovering from failed deployments
-
Monitoring & Logging - Production observability setup
-
CI/CD Integration - GitHub Actions deployment workflows
Refer to examples.md for complete code examples.
Kamal Commands
Deployment Commands
Initial setup (first time only)
kamal setup
Deploy application
kamal deploy
Deploy without building new image
kamal deploy --skip-push
Run migrations before deployment
kamal deploy --skip-push kamal app exec "bin/rails db:migrate"
Application Management
Restart application
kamal app restart
Stop application
kamal app stop
Start application
kamal app start
View application logs
kamal app logs -f
Execute command in container
kamal app exec "bin/rails console" kamal app exec "bin/rails db:migrate:status"
Rollback
List versions
kamal app version
Rollback to previous version
kamal rollback [VERSION]
Server Management
SSH into server
kamal app exec --interactive bash
View Docker containers
kamal app containers
View server details
kamal server details
Dockerfile for Rails
Multi-Stage Dockerfile
Rails 8 includes an optimized Dockerfile by default:
Dockerfile (Rails 8 default, optimized)
ARG RUBY_VERSION=3.4.7 FROM ruby:$RUBY_VERSION-slim AS base
WORKDIR /rails
RUN apt-get update -qq &&
apt-get install --no-install-recommends -y
curl libjemalloc2 libvips sqlite3 &&
rm -rf /var/lib/apt/lists /var/cache/apt/archives
ENV RAILS_ENV="production"
BUNDLE_DEPLOYMENT="1"
BUNDLE_PATH="/usr/local/bundle"
BUNDLE_WITHOUT="development:test"
FROM base AS build
RUN apt-get update -qq &&
apt-get install --no-install-recommends -y
build-essential git pkg-config &&
rm -rf /var/lib/apt/lists /var/cache/apt/archives
COPY Gemfile Gemfile.lock ./
RUN bundle install &&
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby//cache "${BUNDLE_PATH}"/ruby//bundler/gems/*/.git
COPY . .
RUN bundle exec bootsnap precompile --gemfile app/ lib/ RUN ./bin/rails assets:precompile
FROM base
COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" COPY --from=build /rails /rails
RUN groupadd --system --gid 1000 rails &&
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash &&
chown -R 1000:1000 db log storage tmp
USER 1000:1000
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
EXPOSE 3000 CMD ["./bin/thrust", "./bin/rails", "server"]
Environment Management
Rails Credentials
Edit production credentials
EDITOR=nano rails credentials:edit --environment production
Generates config/credentials/production.yml.enc
and config/credentials/production.key
config/credentials/production.yml.enc (encrypted)
secret_key_base: <generated> database: password: <db_password> smtp: username: <smtp_user> password: <smtp_pass>
Environment Variables
.env (not committed to git, for local deployment)
KAMAL_REGISTRY_PASSWORD=<docker_hub_password> RAILS_MASTER_KEY=<from config/credentials/production.key> DATABASE_URL=postgresql://user:pass@host:5432/dbname
Database Migrations
Safe Migration Strategy
1. Deploy without running migrations
kamal deploy --skip-push
2. Run migrations separately
kamal app exec "bin/rails db:migrate"
3. Restart application
kamal app restart
Pre-Deployment Checks
Check migration status before deploying
kamal app exec "bin/rails db:migrate:status"
Run migrations in a transaction
kamal app exec "bin/rails db:migrate"
Verify migration success
kamal app exec "bin/rails db:version"
Testing Deployment
Local Docker Testing
Build Docker image locally
docker build -t my-app .
Run container locally
docker run -p 3000:3000
-e RAILS_MASTER_KEY=<key>
-e DATABASE_URL=<url>
my-app
Test in browser
Staging Environment
config/deploy.staging.yml
service: my-blog-app-staging image: your-username/my-blog-app
servers: web: hosts: - staging.example.com
env: secret: - RAILS_MASTER_KEY clear: RAILS_ENV: staging
Deploy to staging
kamal deploy -c config/deploy.staging.yml
Official Documentation:
-
Kamal Documentation - Official Kamal guide
-
Docker Documentation - Docker reference
-
Rails Deployment Guide - Rails production config
Deployment Platforms:
-
DigitalOcean - Simple VPS hosting
-
Hetzner - Cost-effective VPS
-
AWS EC2 - Scalable cloud hosting
Monitoring & Logging:
-
AppSignal - Rails monitoring
-
Sentry - Error tracking
-
Lograge - Structured logging
CI/CD:
-
GitHub Actions - CI/CD automation
-
Kamal GitHub Action - Official action