Eine Rails-App bereitstellen
Rails 7.1 und neuer generieren ein Dockerfile für die Produktion, und Lizard (lizard.build) baut es unverändert: Das Image installiert die Gems, kompiliert die Assets vor und führt bei jedem Serverstart bin/rails db:prepare aus. Setze RAILS_MASTER_KEY und die Datenbank-URLs und führe dann für Rails 8 lizard up --port 8080 aus (mit HTTP_PORT=8080 für Thruster) oder für Rails 7.1 und 7.2 lizard up --port 3000. Ohne Dockerfile baut lizardpack ein einfaches Ruby-Image auf Port 3000.
Teststatus: Wir haben das Dockerfile, bin/docker-entrypoint, config/puma.rb und database.yml geprüft, die Rails generiert, außerdem die Build- und Port-Regeln von Lizard und den Plan von lizardpack für eine Rails-App ohne Dockerfile. Eine Rails-App haben wir mit dieser Anleitung noch nicht vollständig bereitgestellt.
Bevor du beginnst
- Eine App ab Rails 7.1, die PostgreSQL nutzt (das Gem
pg) und noch das generierteDockerfileundbin/docker-entrypointhat. Eine ältere App bekommt beides über das Gem dockerfile-rails:bundle add dockerfile-rails --group development, danachbin/rails generate dockerfile. config/master.keyauf deinem Rechner oder denSECRET_KEY_BASEder App.- Eine
Gemfile.lock, die die Plattformx86_64-linuxenthält. Füge sie mitbundle lock --add-platform x86_64-linuxhinzu und committe die Datei. - Lizard CLI, angemeldet mit
lizard login, auf Pro oder in der 7-tägigen Pro-Testphase (Karte erforderlich). Siehe Preise.
Wie Lizard eine Rails-App baut
| Deine App hat | Lizard baut | Service-Port |
|---|---|---|
Das Dockerfile von Rails 8 (EXPOSE 80, CMD ["./bin/thrust", "./bin/rails", "server"]) | Dein Dockerfile, unverändert | 8080, mit HTTP_PORT=8080 |
Das Dockerfile von Rails 7.1 oder 7.2 (EXPOSE 3000) | Dein Dockerfile, unverändert | 3000 |
| Kein Dockerfile | Das Ruby-Image von lizardpack; siehe unten | 3000 |
Lass Build- und Startbefehl des Service leer. Ist einer davon gesetzt, schreibt Lizard aus den Befehlen ein eigenes Dockerfile, statt deines zu nutzen, und dieses Image enthält Node.js, nicht Ruby. Ein Startbefehl ersetzt außerdem den Entrypoint des Images, sodass db:prepare nicht laufen würde. Siehe die Reihenfolge der Build-Entscheidung.
Rails 8 startet Thruster, das auf Port 80 lauscht und dahinter Puma auf Port 3000 betreibt. Das Image läuft als Nicht-Root-Benutzer (USER 1000:1000), und einem Nicht-Root-Prozess kann die Berechtigung fehlen, einen Port unter 1024 zu öffnen. HTTP_PORT=8080 verlegt Thruster auf einen Port, den es immer öffnen kann.
Projekt und Datenbank anlegen
Im Stammverzeichnis der App:
lizard init --name rails-app
lizard add --service web
lizard add postgresManaged Postgres verbindet sich als Superuser postgres, daher kann db:prepare die Datenbanken anlegen, die Rails anfordert.
Secrets setzen und bereitstellen (Rails 8)
Die Produktions-database.yml von Rails 8 definiert vier Datenbanken: primary, cache, queue und cable. DATABASE_URL ersetzt nur primary. Für die anderen liest Rails CACHE_DATABASE_URL, QUEUE_DATABASE_URL und CABLE_DATABASE_URL. Lass alle vier auf dieselbe Postgres-Instanz zeigen, jeweils mit einem anderen Datenbanknamen:
PG='postgresql://postgres:${{postgres.PGPASSWORD}}@${{postgres.LIZARD_PRIVATE_DOMAIN}}:5432'
lizard secrets set \
RAILS_MASTER_KEY="$(cat config/master.key)" \
DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' \
CACHE_DATABASE_URL="$PG/rails_cache" \
QUEUE_DATABASE_URL="$PG/rails_queue" \
CABLE_DATABASE_URL="$PG/rails_cable" \
HTTP_PORT=8080 \
SOLID_QUEUE_IN_PUMA=true \
--service web
lizard up --service web --port 8080- Die einfachen Anführungszeichen verhindern, dass deine Shell
${{…}}auswertet. Lizard löst diese Referenzen beim Deployment auf und nutzt das private Netzwerk des Projekts. SOLID_QUEUE_IN_PUMA=truelässt Puma den Solid-Queue-Worker ausführen, sodass Active-Job-Jobs im Web-Service laufen. Ohne diese Variable bleiben Jobs in der Warteschlange liegen.- Nutze
SECRET_KEY_BASEstattRAILS_MASTER_KEYnur, wenn die App keine anderen verschlüsselten Credentials liest.
Secrets setzen und bereitstellen (Rails 7.1 und 7.2)
Diese Versionen nutzen eine Datenbank:
lizard secrets set \
RAILS_MASTER_KEY="$(cat config/master.key)" \
DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' \
--service web
lizard up --service web --port 3000Was bei jedem Deployment passiert
lizard up lädt das Verzeichnis hoch. Innerhalb eines Git-Repositorys überspringt es alles, was in .gitignore steht, und sowohl .gitignore als auch .dockerignore von Rails schließen config/master.key und .env*-Dateien aus. Der Build kompiliert die Assets mit SECRET_KEY_BASE_DUMMY=1 vor, weil Lizard einem Dockerfile-Build außer COMMIT_SHA keine Variablen übergibt.
Beim Start führt bin/docker-entrypoint den Befehl ./bin/rails db:prepare aus: Er legt fehlende Datenbanken an, lädt das Schema in neue Datenbanken und führt ausstehende Migrationen aus. Das passiert bei jedem Containerstart, auch bei Neustarts. Schreibe Migrationen so, dass sie sowohl mit dem alten als auch mit dem neuen Code sicher laufen.
Für git push to deploy pushe die App zu GitHub und verbinde das Repository, statt lizard up auszuführen. Setze dieselben Secrets und denselben Port (lizard port 8080 --service web). Das generierte Dockerfile hat einen Schritt bundle install, daher nutzt Lizard es unverändert.
Prüfen, ob es funktioniert
lizard logs --build --service web
lizard logs --service web --tail 100
lizard domain --service webRails 7.1 und neuer antworten auf /up mit HTTP 200, sobald die App hochgefahren ist. Öffne https://<your-domain>/up und danach eine Seite, die aus der Datenbank liest. Das Laufzeit-Log sollte die Ausgabe von db:prepare zeigen und danach den Start von Puma.
Ohne Dockerfile
lizardpack baut eine Ruby-App, wenn es ein Gemfile findet:
- Ruby-Version:
.ruby-version, sonst dieruby-Zeile imGemfile, sonst3.4. Es zählen nur Haupt- und Nebenversion:3.4.1baut aufruby:3.4-slim. - Es installiert
build-essentialundlibpq-devund führt dannbundle installaus. - Start: die
web:-Zeile im Procfile, sonstbundle exec rails server -b 0.0.0.0, wennconfig.ruundRakefilevorhanden sind. Port3000.
Dieses Image setzt kein RAILS_ENV, kompiliert keine Assets vor und bereitet die Datenbank nicht vor. Es eignet sich daher eher für kleine Apps und APIs als für eine vollständige Rails-Website. Schreib .ruby-version als reine Zahl wie 3.4.1. rails new schreibt ruby-3.4.1, und lizardpack macht daraus einen Image-Namen, den es nicht gibt. Siehe Laufzeitversionen.
Häufige Probleme
| Symptom | Lösung |
|---|---|
bundle install schlägt fehl: Das Bundle unterstützt nur andere Plattformen | Führe bundle lock --add-platform x86_64-linux aus und committe Gemfile.lock. |
Missing secret_key_base, oder die Credentials lassen sich nicht entschlüsseln | Setze RAILS_MASTER_KEY aus config/master.key auf dem Service web. |
Die Verbindung für Cache, Queue oder Cable geht an einen lokalen Socket wie /var/run/postgresql | Setze CACHE_DATABASE_URL, QUEUE_DATABASE_URL und CABLE_DATABASE_URL. |
Die Logs zeigen bind: permission denied für Port 80 | Setze HTTP_PORT=8080 und den Service-Port auf 8080. |
| Das Deployment wird nie healthy | Prüfe, ob der Service-Port zur Tabelle oben passt: lizard port --service web. Siehe Service wird nie healthy. |
| Jobs bleiben in der Warteschlange | Setze SOLID_QUEUE_IN_PUMA=true. Um Jobs getrennt vom Web-Prozess auszuführen, füge einen zweiten Service im Worker-Modus mit dockerfilePath=Dockerfile und startCommand=./bin/jobs hinzu. |
| Hochgeladene Dateien verschwinden nach einem Deployment | Der Active-Storage-Service local schreibt in den Container. Nutze Managed Object Storage, das S3-kompatibel ist, mit dem Service amazon. |
Wenn die App Sidekiq oder einen Redis-Adapter für Action Cable nutzt, füge Managed Redis hinzu und setze REDIS_URL='${{redis.REDIS_PRIVATE_URL}}' auf jedem Service, der es braucht.
Siehe auch
- Einen Docker-Container aus einem Dockerfile deployen
- Variablen und Secrets
- Managed Postgres
- Build-Pipeline
- Storage und Wiederherstellung
Aktualisiert