Membedah deployment Rails: Kamal untuk deploy sederhana ke VPS, Dockerfile produksi, managed hosting seperti Fly Render dan Heroku, serta praktik deploy Rails 8 ke VPS dengan Kamal

Setelah di episode 22 kalian menguasai Solid Stack untuk produksi, episode 23 membahas langkah yang membuat semua pekerjaan kalian terlihat oleh dunia: deployment. Aplikasi yang tidak pernah di-deploy tidak pernah melayani user — dan cara deploy menentukan seberapa mudah kalian meng-update tanpa drama.
Mengapa episode ini penting? Karena deployment adalah titik pertemuan kode, infrastruktur, dan operasional. Kamal — tool deploy buatan 37signals — membuat deploy Rails ke VPS sesederhana satu perintah, menggunakan Docker dan Traefik di belakang layar. Episode ini juga membedah opsi managed hosting sehingga kalian tahu kapan memilih yang mana.
Semua deploy modern dimulai dari image Docker. rails new Rails 8 sudah menyertakan Dockerfile yang production-ready:
# syntax = docker/dockerfile:1
ARG RUBY_VERSION=3.4.4
FROM ruby:$RUBY_VERSION-slim AS base
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y \
libvips libvips-dev libpq-dev \
build-essential git pkg-config
WORKDIR /rails
FROM base AS build
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
RUN bundle exec bootsnap precompile --gemfile
RUN SECRET_KEY_BASE_DUMMY=1 bin/rails assets:precompile
FROM base AS final
RUN mkdir -p /opt/rails
COPY --from=build /rails /rails
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
EXPOSE 3000
CMD ["bin/rails", "server"]Tiga tahap (stages) penting: base (runtime + library), build (compile asset & precompile), final (image ringan untuk dijalankan). Perhatikan libvips — diingat dari episode 13 bahwa Active Storage membutuhkannya.
Tip
Build image lokal untuk memvalidasi sebelum deploy: docker build -t blog . lalu docker run -p 3000:3000 -e SECRET_KEY_BASE=dev -e DATABASE_URL=... blog. Kebiasaan ini menangkap 90% masalah Docker sebelum Kamal turun tangan.
Kamal adalah tool deploy yang menggunakan Docker + Traefik untuk menjalankan app di VPS biasa — tanpa Kubernetes. Install dan inisialisasi:
gem install kamal
kamal initkamal init membuat config/deploy.yml:
service: blog
image: ghcr.io/yourname/blog
servers:
web:
- 203.0.113.10
env:
secret: true
clear:
RAILS_ENV: production
solid_queue:
- PostNotificationJob
volumes:
- /rails/storage:/rails/storage
builder:
multiarch: falseLalu deploy:
kamal setup # install Docker + dependensi di server
kamal deploy # build image, update kontainer, restart
kamal logs # ikuti log produksi
kamal app exec "bin/rails db:migrate" # jalankan migrationYang dilakukan Kamal: membangun image, meng-upload ke server, menjalankan kontainer dengan Traefik sebagai reverse proxy + Let's Encrypt TLS otomatis, dan melakukan zero-downtime rolling deploy (versi lama tetap melayani sampai versi baru siap). Rollback semudah kamal rollback.
Secret tidak ditulis di deploy.yml yang masuk repo — dikirim saat deploy:
kamal env set RAILS_MASTER_KEY=$(cat config/master.key)
kamal env set DATABASE_URL="postgres://user:pass@db-host/blog_production"kamal env set menyimpan nilai terenkripsi di server. Saat kontainer start, env vars tersedia untuk Rails — sesuai prinsip secrets management episode 16.
Tidak semua orang ingin mengelola VPS. Opsi managed:
| Platform | Kelebihan | Cocok Untuk |
|---|---|---|
| Fly.io | Deploy dari fly.toml, per-repo Docker, scaling cepat | Tim yang suka Docker tanpa infra penuh |
| Render | Deploy dari Git, auto-deploy, disk persisten | Aplikasi yang ingin simple ops |
| Heroku | Legacy ternyaman, add-on ekosistem besar | Prototipe & app klasik |
Kesamaan ketiganya: mereka menjalankan kontainer Ruby, menyediakan PostgreSQL managed, dan menangani TLS. Perbedaannya di model pricing dan kontrol. Untuk kontrol penuh dan biaya terukur di VPS, Kamal menang.
Warning
Prasyarat deploy yang sering dilupakan: database, storage, dan worker. Kamal hanya menjalankan app — PostgreSQL (atau layanan DB managed), volume storage (/rails/storage), dan proses solid_queue harus tersedia. Siapkan ketiganya sebelum kamal setup.
Urutan yang menjaga deploy mulus:
SECRET_KEY_BASE/RAILS_MASTER_KEY diset di Kamal (episode 16).DATABASE_URL benar; jalankan migration./rails/storage persisten (atau S3, episode 13).assets:precompile berhasil (Dockerfile menangani)./up (bawaan Rails 8) di-akses Kamal/Traefik./cable di proxy (episode 14) untuk realtime.kamal app exec "curl -s http://localhost:3000/up"master.key tertinggal di repo / tidak diset — app crash di boot; kamal env set RAILS_MASTER_KEY./rails/storage atau S3.kamal app exec./up hijau.Episode 23 membekali kalian deployment Rails: Dockerfile production tiga-stage, Kamal untuk deploy zero-downtime ke VPS dengan Traefik + Let's Encrypt, pengelolaan secret via kamal env set, perbandingan managed hosting (Fly/Render/Heroku), dan checklist pra-deploy yang lengkap.
Inti yang harus dibawa pulang:
kamal setup → kamal deploy → kamal rollback; zero-downtime via Traefik.kamal env set, bukan di repo./up, dan cable.Di episode 24 selanjutnya kita akan membedah scaling & high availability — aplikasi stateless, shared cache, read replicas, worker terpisah, observability, dan praktik load test & tuning. Sampai jumpa di episode 24!