0

Deploy Rails 8 với Kamal 2

Chào các bạn! Rails 8 ra mắt mang theo triết lý "No-PaaS" mạnh mẽ. Với sự kết hợp của SQLite (Solid Stack)Kamal 2, bạn có thể tự vận hành một hệ thống chuyên nghiệp, Zero-downtime trên máy ảo cá nhân mà không cần đến các dịch vụ Cloud đắt đỏ.


Bước 1: Khởi tạo dự án Rails 8 (Local)

  1. Tạo dự án mới:
rails new rails_deploy
cd rails_deploy

  1. Tạo trang chủ: Để tránh lỗi 404 khi truy cập IP, hãy tạo một Controller đơn giản.
bin/rails generate controller Home index

Mở config/routes.rb và thêm: root "home#index".


Bước 2: Chuẩn bị Server Multipass

Chúng ta dùng Multipass để giả lập một server Ubuntu ngay tại máy local, vì mình không có IP của cloud như AWS, Heroku,... nên setup tạm ở local cho tiện sử dụng, vì mục đích bài này chỉ là việc setup deploy với kamal nhé.

  1. Tạo máy ảo (Cấp 20GB ổ đĩa để Docker thoải mái build):
multipass launch --name rails-server --disk 20G --memory 2G

  1. Lấy IP máy ảo:
multipass list

👉 Ghi lại IPv4 (Ví dụ: 10.106.158.38).


Bước 3: Thiết lập Server (Docker & SSH)

3.1 Cài đặt Docker & Phân quyền

multipass exec rails-server -- curl -fsSL https://get.docker.com | sh
multipass exec rails-server -- sudo usermod -aG docker ubuntu
multipass restart rails-server

3.2 Cấu hình SSH Passwordless

Để Kamal tự động đăng nhập, bạn cần gửi Public Key vào máy ảo. Thay 'id_ed25519.pub' bằng tên file key của bạn (ví dụ id_rsa.pub)

  • Trên macOS hoặc Linux (Bash/Zsh/Fish):
cat ~/.ssh/id_rsa.pub | multipass exec rails-server -- bash -c "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"


Bước 4: Chuẩn bị Docker Hub (Chi tiết Username & Repo)

Đây là bước quan trọng nhất để Kamal có chỗ cất giữ "gói hàng" (Image) của bạn.

4.1 Xác định Username và Tạo Repo

  1. Lấy Username: Truy cập Docker Hub. Tên đăng nhập của bạn (ID) chính là your_username.
  • Ví dụ: Nếu URL trang cá nhân là hub.docker.com/u/travv07 thì username là travv07.
  1. Tạo Repo: Vào mục Repositories > Create Repository.
  • Đặt tên là rails_deploy.
  • Lúc này, địa chỉ Image đầy đủ của bạn sẽ là: travv07/rails_deploy.
  1. Tạo Access Token: Vào Settings > Security > Personal Access Tokens -> Tạo Token mới (Quyền: Read & Write). Lưu mã này lại làm biến KAMAL_REGISTRY_PASSWORD.

4.2 Kiểm tra Image thủ công

Đừng bỏ qua bước này để chắc chắn quyền Push đã thông suốt:

# Đăng nhập bằng Token (Thay 'travv07' bằng username thật của bạn)
docker login -u travv07

# Build và Push thử bản 'latest' 
docker build -t travv07/rails_deploy .
docker push travv07/rails_deploy


Bước 5: Cấu hình mã nguồn (Production Ready)

5.1 Cấu hình Database SQLite chuẩn Rails 8

Mở config/database.yml, đảm bảo phần production sử dụng thư mục storage/ để dữ liệu không bị mất khi container khởi động lại:

production:
  primary:
    adapter: sqlite3
    database: storage/production.sqlite3
  cache:
    adapter: sqlite3
    database: storage/cache.sqlite3
    migrations_paths: db/cache_migrate
  queue:
    adapter: sqlite3
    database: storage/queue.sqlite3
    migrations_paths: db/queue_migrate
  cable:
    adapter: sqlite3
    database: storage/cable.sqlite3
    migrations_paths: db/cable_migrate

5.2 Mở khóa bảo mật

Mở config/environments/production.rb và chỉnh sửa:

config.hosts.clear        # Cho phép Kamal Proxy truy cập để Healthcheck
config.assume_ssl = false # Tạm tắt nếu chưa có HTTPS/SSL
config.force_ssl = false


Bước 6: Soạn thảo Manifest config/deploy.yml

Thay your_usernameIP thật của bạn vào đây: Lưu ý phần volumesbuilder là cực kỳ quan trọng.

service: rails-deploy
image: your_username/rails_deploy 

servers:
  web:
    - 10.106.158.38 # IP từ Multipass list

ssh:
  user: ubuntu # User mặc định của máy ảo Multipass

registry:
  server: index.docker.io
  username: your_username
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  secret:
    - RAILS_MASTER_KEY

proxy:
  ssl: false
  host: 10.106.158.38
  app_port: 3000

# QUAN TRỌNG: Lưu giữ dữ liệu SQLite khi deploy lại
volumes:
  - "/var/lib/rails-deploy/storage:/rails/storage"

# Dành cho máy Mac chip M1/M2/M3 build cho máy ảo Linux AMD64
builder:
  arch: amd64

Bước 7: Kích hoạt Deploy tự động với Kamal

7.1 Commit code

git add . && git commit -m "Final deploy config"

7.2 Thiết lập biến môi trường (Environment Variables)

Chọn lệnh tương ứng với Shell bạn đang dùng:

  • Nếu dùng Bash hoặc Zsh (Mặc định Ubuntu/macOS):
export KAMAL_REGISTRY_PASSWORD="your_docker_token"
export RAILS_MASTER_KEY=$(cat config/master.key)

  • Nếu dùng Fish Shell:
set -x KAMAL_REGISTRY_PASSWORD "your_docker_token"
set -x RAILS_MASTER_KEY (cat config/master.key)

7.3 Chạy Setup

kamal setup


7.4 Chạy Deploy (Từ lần thứ hai hoặc khi sửa code)

Dùng lệnh này khi bạn thay đổi code, cập nhật tính năng. Kamal sẽ build bản mới và thay thế bản cũ (Zero-downtime).

kamal deploy


Bước 8: Bảng tổng hợp lỗi & Giải pháp

Lỗi gặp phải Nguyên nhân Cách xử lý
Auth Failed (SSH) Sai user SSH Kiểm tra user: ubuntu trong deploy.yml.
Permission Denied Docker User chưa vào group docker Chạy lệnh usermod ở Bước 3 và restart VM.
denied: access forbidden Sai Token/Username Kiểm tra lại Bước 4 và docker login lại.
Unhealthy (30s timeout) Rails chặn Proxy Host Thêm config.hosts.clear vào production.rb.
No space left on device Ổ đĩa máy ảo đầy Chạy docker system prune -f hoặc tạo VM 20GB.

Bước 9: Kiểm tra thành quả

  • Trạng thái: kamal details
  • Xem Log: kamal app logs -f
  • Truy cập: Mở trình duyệt tại http://<IP_MÁY_ẢO>.

Lời kết:

Chúc mừng bạn đã làm chủ quy trình deploy Rails 8! Việc kết hợp SQLite và Kamal mang lại sự đơn giản tối đa nhưng vẫn đảm bảo tính chuyên nghiệp cao.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.