This document outlines the complete end-to-end process of developing, building, containerizing, and deploying a Ruby on Rails 8 application using Docker and Kamal on an Amazon Lightsail instance.
rails new spec_driven_app --database=sqlite3
cd spec_driven_app- Ruby version: 3.3.6
- Rails version: 8.x
- Database: SQLite (for testing)
- Environment: Production-ready Docker setup
bundle installgit init
git add .
git commit -m "Initial Rails 8 app"git remote add origin https://github.com/apperph/github-actions-test.git
git branch -M main
git push -u origin mainImportant:
Never commit .kamal/secrets or .env
Add to .gitignore:
.kamal/secrets
.env- OS: Ubuntu
- Region: Singapore (ap-southeast-1)
- Instance Type: Upgraded (to avoid memory issues)
- Static IP: 13.213.250.166
| Port | Purpose |
|---|---|
| 22 | SSH |
| 80 | HTTP |
| 443 | HTTPS |
Download the .pem key and configure:
chmod 400 ~/Downloads/rails-test-key.pemAdd to SSH config:
nano ~/.ssh/configHost rails-test-lightsail
HostName 13.213.250.166
User ubuntu
IdentityFile ~/Downloads/rails-test-key.pemTest connection:
ssh rails-test-lightsailEnsure Docker is running locally:
docker infoIf Docker is not running:
open -a Dockergem install kamalkamal initservice: spec_driven_app
image: ghcr.io/apperph/github-actions-test
servers:
web:
- 13.213.250.166
registry:
server: ghcr.io
username: YOUR_USERNAME
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
RAILS_ENV: production
PORT: 80bin/kamal setupbin/kamal deployError:
Authentication failed for user ubuntu
Fix:
- Ensure correct
.pempath - Check permissions:
chmod 400 key.pem
Error:
Cannot connect to Docker daemon
Fix:
open -a DockerError:
Operation timed out
Fix:
- Start instance in AWS console
- Verify port 22 is open
Error:
Deploy lock already in place
Fix:
bin/kamal lock releaseError:
target failed to become healthy
Cause: Low memory (512 MB instance)
Fix:
- Upgrade Lightsail instance
- Redeploy
Error:
context deadline exceeded
Fix:
docker login ghcr.ioError:
Push blocked due to exposed token
Fix:
- Remove
.kamal/secretsfrom Git - Rotate GitHub token
- Amend commit
- Public IP: 13.213.250.166
- SSH Host: rails-test-lightsail
- Registry: ghcr.io/apperph/github-actions-test
-
Deploy:
bin/kamal deploy
-
Logs:
bin/kamal app logs
-
SSH:
ssh rails-test-lightsail
-
Docker Logs:
docker logs <container_id>
- Double
ghcr.ioin image path - Docker not running locally
- Secrets committed to repo
- Instance too small (memory)
- Use at least 1GB+ RAM for Rails apps
- Always attach a static IP
- Never commit:
.env.kamal/secrets
- Rotate tokens immediately if exposed
- Always run
docker login ghcr.ioon the server before deploy - Check container health:
docker ps
- If deploy hangs → check logs immediately
- If SSH fails → check instance + firewall
- If container unhealthy → inspect logs
Future improvement:
PM edits business spec → GitHub commit → GitHub Actions builds image → Kamal deploys automatically
- ✅ Rails 8 App Running
- ✅ Dockerized
- ✅ Deployed via Kamal
- ✅ Hosted on AWS Lightsail
- ✅ Zero-downtime deployment working
This is the full file — no broken parts.
Just copy from `# Spec-Driven Rails App Deployment...` to the end and save it.
If you're still having trouble copying, tell me your device (Windows/Mac/Android) and I'll give you the easiest method for your device.