Ruby #
Ruby sering dicap sebagai bahasa yang “berat” di Docker. Image Ruby identik dengan:
- ratusan MB
- banyak OS package
- build lama
Padahal, Ruby bisa dibuat sangat ramping dan production-grade jika diperlakukan dengan disiplin yang sama seperti Java (distroless), Node.js (bundling), Python (build/runtime split), dan Go (static binary mindset).
Artikel ini membahas strategi Docker image Ruby yang kecil, aman, dan siap production, dengan fokus rasional engineering, bukan sekadar trik Docker.
Realita Ukuran Docker Image Ruby #
Tanpa Strategi #
| Setup | Ukuran Image |
|---|---|
| ruby:latest + bundle install | 700–900 MB |
| ruby:slim tanpa optimasi | 400–600 MB |
Dengan Strategi yang Benar #
| Setup | Ukuran Image |
|---|---|
| ruby:slim + multi-stage | 180–250 MB |
| Alpine Ruby | 120–180 MB |
| Distroless Ruby | 80–130 MB ⭐ |
Masalah Utama Ruby di Docker #
1. Ruby Adalah Runtime + Toolchain #
- Ruby interpreter
- Bundler
- Native extension compiler
Tanpa pemisahan, semua ikut ke runtime.
2. Native Gem Membengkakkan Image #
Contoh gem:
nokogiripggrpc
Mereka butuh:
- compiler
- libc
- OS library
3. Rails Membawa Dunia Sendiri #
Rails production sering:
- membawa test
- membawa asset source
- membawa build tools
Prinsip Utama Image Ruby Production #
Runtime image hanya berisi Ruby interpreter + gem production + app code.
Yang harus mati di runtime:
- gcc / make
- header library
- gem documentation
- test & development dependency
Strategi 1: Ruby Slim + Multi-stage Build #
Dockerfile Dasar #
FROM ruby:3.3-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY Gemfile Gemfile.lock ./
RUN bundle config set without 'development test' \
&& bundle config set path 'vendor/bundle' \
&& bundle install
COPY . .
FROM ruby:3.3-slim
WORKDIR /app
COPY --from=builder /app /app
ENV RACK_ENV=production
ENV RAILS_ENV=production
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
Ukuran tipikal: 200–300 MB.
Strategi 2: Alpine Ruby (Lebih Kecil, Lebih Rumit) #
FROM ruby:3.3-alpine AS builder
WORKDIR /app
RUN apk add --no-cache \
build-base \
postgresql-dev
COPY Gemfile Gemfile.lock ./
RUN bundle config set without 'development test' \
&& bundle install
COPY . .
FROM ruby:3.3-alpine
WORKDIR /app
COPY --from=builder /app /app
CMD ["bundle", "exec", "puma"]
Ukuran: 120–180 MB.
Catatan:
- musl libc
- native gem bisa lebih tricky
Strategi 3: Distroless Ruby (Production-Oriented) #
Ruby tidak resmi didukung distroless, tapi bisa:
FROM ruby:3.3-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential libssl-dev libpq-dev
COPY Gemfile Gemfile.lock ./
RUN bundle config set without 'development test' \
&& bundle install
COPY . .
FROM gcr.io/distroless/base-debian12
WORKDIR /app
COPY --from=builder /usr/local /usr/local
COPY --from=builder /app /app
ENV PATH="/usr/local/bin:$PATH"
CMD ["ruby", "app.rb"]
Ukuran realistis: 80–130 MB.
Trade-off:
- debugging sulit
- harus paham dependency runtime
Asset Compilation (Rails) #
Lakukan di build stage:
RAILS_ENV=production bundle exec rails assets:precompile
Runtime tidak boleh:
- nodejs
- yarn
Optimasi Bundler #
bundle config set deployment 'true'
bundle config set without 'development test'
bundle config set clean 'true'
Tambahan:
bundle install --no-cache- disable documentation
gem: --no-document
Security & Production Readiness #
Non-root User #
Tambahkan user manual atau gunakan distroless base.
###** Logging
- STDOUT
- structured logging
###** Healthcheck
Gunakan HTTP endpoint, bukan shell.
Perbandingan Strategi #
| Strategi | Ukuran | Kompleksitas | Rekomendasi |
|---|---|---|---|
| ruby:slim | Sedang | Rendah | Default |
| Alpine | Kecil | Menengah | Berpengalaman |
| Distroless | Sangat kecil | Tinggi | Mature team |
Kapan Strategi Mana Digunakan? #
| Kondisi | Pilihan |
|---|---|
| Rails monolith | ruby:slim |
| Microservice Ruby | Alpine |
| High security env | distroless |
Penutup #
Ruby bukan masalah di Docker. Yang sering jadi masalah adalah:
- toolchain bocor ke runtime
- native dependency tak dikontrol
- build & runtime dicampur
Dengan disiplin build boundary, Ruby bisa:
- image <150 MB
- aman di Kubernetes
- layak untuk sistem besar
Ruby image besar bukan takdir, tapi keputusan engineering.