Wie man Ruby on Rails dockerisiert und deployed

Wie man Ruby on Rails dockerisiert und deployed

Lukas Mauser - Co-Founder von sliplane.ioLukas Mauser
5 min

Dieses Dockerfile baut deine Rails App mit einem Multi-Stage Setup, das Gems installiert, Assets precompiled und dann nur das in ein schlankes finales Image kopiert, was Production braucht.

Falls du nur zum Kopieren und Einfügen hier bist, hier ist das fertige Dockerfile, das ein Image für deine Rails App erstellt:

Dockerfile
FROM ruby:3.3-slim AS base
WORKDIR /rails
ENV RAILS_ENV=production \
    BUNDLE_DEPLOYMENT=1 \
    BUNDLE_PATH=/usr/local/bundle \
    BUNDLE_WITHOUT=development:test

FROM base AS build
# Build-Tools und Postgres-Header, nur beim Kompilieren der Gems nötig
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential git libpq-dev

# Erst die Gems installieren, damit dieser Layer gecacht bleibt, wenn sich nur der Quellcode ändert
COPY Gemfile Gemfile.lock ./
RUN bundle install && rm -rf "${BUNDLE_PATH}"/ruby/*/cache

# Die App kopieren und Assets precompilen
COPY . .
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile

FROM base AS runtime
# Hier wird nur die Postgres-Runtime-Library gebraucht, nicht die Header
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y libpq5 && \
    rm -rf /var/lib/apt/lists/*

# Die installierten Gems und die gebaute App rüberholen
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails

EXPOSE 3000
CMD ["./bin/rails", "server", "-b", "0.0.0.0"]

Und hier ist die .dockerignore Datei:

.git
log/*
tmp/*
storage/*
node_modules
.env

Um das Image zu bauen und auszuführen, nutze diese Befehle:

docker build -t rails-app .
docker run -p 3000:3000 -e RAILS_MASTER_KEY=your_master_key rails-app

Nicht nur zum Kopieren und Einfügen hier? Dann lass uns durchgehen, was im Dockerfile passiert!

Das Setup

Für dieses Tutorial gehe ich davon aus, dass du eine Rails App hast, die mit Postgres spricht, was das häufigste Setup ist. Lokal führst du bin/rails server aus und alles läuft einfach. Für Production wollen wir ein kleines, self-contained Image, also splitten wir die Arbeit in eine Build-Stage, die alle Compiler hat, und eine Runtime-Stage, die keine davon hat.

Das Dockerfile

Die base Stage setzt gemeinsame Environment-Variablen. RAILS_ENV=production und BUNDLE_WITHOUT=development:test stellen sicher, dass wir keine Test- und Development-Gems ins Image ziehen.

Die build Stage macht die schwere Arbeit:

  1. Build-Dependencies:
  • Installiert build-essential, git und libpq-dev. Die braucht man, um native Gem-Extensions wie pg zu kompilieren, aber du willst sie nicht im finalen Image haben.
  1. Gem-Installation:
  • Kopiert Gemfile und Gemfile.lock einzeln und führt dann bundle install aus. Das vor dem Kopieren des restlichen Codes zu machen heißt, dass Docker deine Gems cacht und sie nur neu installiert, wenn sich das Gemfile ändert.
  1. Asset-Precompilation:
  • Führt assets:precompile mit SECRET_KEY_BASE_DUMMY=1 aus. Rails braucht beim Precompile irgendein Secret, um zu booten, und dieses Flag liefert ein Wegwerf-Secret, damit du deinen echten Key nicht in den Build leaken musst.

Die runtime Stage ist bewusst nackt:

  1. Runtime-Image:
  • Installiert nur libpq5, die Shared-Library, die das pg Gem zur Laufzeit braucht.
  • Kopiert die installierten Gems und die fertige App aus der Build-Stage.
  • Exponiert Port 3000 und startet Puma gebunden an 0.0.0.0, damit es Verbindungen von außerhalb des Containers annimmt.

Zur Laufzeit braucht Rails RAILS_MASTER_KEY (oder SECRET_KEY_BASE), um deine Credentials zu entschlüsseln, also gib es als Environment-Variable weiter, statt es zu committen.

Deployment

Du kannst diesen Docker Container bei jedem Cloud-Anbieter deployen, der Docker unterstützt. Du könntest zum Beispiel Plattformen wie Heroku, DigitalOcean oder AWS ECS nutzen. Da ich Mitgründer von Sliplane bin, zeig ich dir, wie du es dort deployst.

Nach der Anmeldung kannst du einen neuen Service erstellen, indem du dein GitHub Repository auswählst. Behalt dann die Standardeinstellungen bei, füg RAILS_MASTER_KEY und deine DATABASE_URL als Environment-Variablen hinzu und klick auf Deploy.

Sliplane Dashboard

Nach dem Deployment ist deine Rails App unter einer Subdomain von sliplane.app verfügbar, normalerweise ist das einfach dein Service-Name.

Du kannst auch die Logs deiner App sehen, Metriken wie CPU- und Speichernutzung einsehen, persistenten Speicher hinzufügen und vieles mehr. Wann immer du in dein Repository pushst, deployed Sliplane deine App automatisch.

Wenn du Sliplane ausprobieren möchtest, sind die ersten 2 Tage kostenlos! Probier es aus und lass mich wissen, was du davon hältst :)

Deploy Rails in 2 Minuten 🚀

Push dein Repo zu GitHub und lass Sliplane deine Rails App für dich bauen und deployen. Die ersten 2 Tage sind kostenlos.

Nächste Schritte

Beim Deploy willst du normalerweise bin/rails db:migrate ausführen. Ein winziges Entrypoint-Script, das Migrations ausführt und dann Puma startet, erledigt das sauber. Brauchst du Hilfe beim Verdrahten davon oder beim Anbinden einer Managed-Postgres-Datenbank? Melde dich gerne!

Bis dann,

Lukas

Willkommen auf deiner Cloud-Plattform

Sliplane macht es einfach, deine Apps in der Cloud zu deployen und zu skalieren. Starte mit einem Container oder deinem Lieblings-Framework und wachse von da aus. Probier es jetzt aus!