Ruby: Erweiterte Anwendungen

Weiterführende Schritte mit Ihren Ruby-Bereitstellungen

👋 Willkommen bei der Stackhero-Dokumentation!

Stackhero bietet eine einsatzbereite Ruby Cloud Lösung, die zahlreiche Vorteile bietet, darunter:

  • Deployen Sie Ihre Anwendung in Sekundenschnelle mit einem einfachen git push.
  • Verwenden Sie Ihren eigenen Domainnamen und profitieren Sie von der automatischen Konfiguration von HTTPS-Zertifikaten für erhöhte Sicherheit.
  • Genießen Sie beruhigende automatische Backups, Ein-Klick-Updates und eine einfache, transparente und vorhersehbare Preisgestaltung.
  • Erhalten Sie optimale Performance und robuste Sicherheit dank einer privaten und dedizierten VM.

Sparen Sie Zeit und vereinfachen Sie Ihr Leben: Es dauert nur 5 Minuten, um die Ruby Cloud Hosting Lösung von Stackhero auszuprobieren!

Bisher haben wir unsere Ruby-Anwendung bereitgestellt, indem wir den main-Branch mit folgendem Befehl gepusht haben:

git push stackhero main

Wenn Sie einen anderen Branch bereitstellen möchten, können Sie diesen Befehl verwenden. Ersetzen Sie <BRANCH> durch den Namen des Branches, den Sie bereitstellen möchten:

git push stackhero <BRANCH>:main

Zum Beispiel, um einen Branch namens production bereitzustellen, führen Sie aus:

git push stackhero production:main

In einigen Fällen möchten Sie möglicherweise ein Tag anstelle eines Branches bereitstellen. Führen Sie dazu den folgenden Befehl aus. Ersetzen Sie <TAG> durch das Tag, das Sie bereitstellen möchten:

git push stackhero '<TAG>^{}:main'

Zum Beispiel, um das Tag v1.0.0 bereitzustellen, führen Sie aus:

git push stackhero 'v1.0.0^{}:main'

Die Syntax ^{} wird verwendet, um auf den Commit zu verweisen, auf den das Tag zeigt.

Zusätzlich zu Branches oder Tags können Sie einen bestimmten Commit bereitstellen. Ersetzen Sie <COMMIT_HASH> im folgenden Befehl durch den Hash des gewünschten Commits:

git push -f stackhero <COMMIT_HASH>:main

Zum Beispiel, um einen Commit mit dem Hash abcde bereitzustellen, führen Sie aus:

git push -f stackhero abcde:main

Wenn Ihre Produktionsbereitstellung nicht wie erwartet funktioniert, können Sie zurücksetzen, indem Sie einen älteren Commit bereitstellen. Verwenden Sie zuerst den folgenden Befehl, um Ihre Commit-Historie anzuzeigen:

git log

Dieser Befehl zeigt das Datum, den Commit-Hash und die Beschreibung für jeden Commit in Ihrem Repository an. Zum Beispiel könnten Sie eine Ausgabe wie diese sehen:

commit cccc8b3ebdccb9abc1926ef49ee589dae5c5fe06 (HEAD -> main, stackhero/main)
Author: Developer
Date:   Fri Apr 28 09:36:18 +0000

    Break the code

commit bbbb622301772072c3d82f3cc0d91e29e6e84901
Author: Developer
Date:   Wed Apr 26 12:49:28 +0000

    Update the code

commit aaaa1d8b06535b413e0df8298ccf52339dfef3ff
Author: Developer
Date:   Wed Apr 26 12:44:50 +0000

    Improve the code

Wenn der Commit mit der Nachricht "Break the code" (Hash cccc...) in der Produktion läuft und Sie sich entscheiden, zum vorherigen Commit "Update the code" (Hash bbbb...) zurückzukehren, führen Sie aus:

git push -f stackhero bbbb622301772072c3d82f3cc0d91e29e6e84901:main

Um zu verhindern, dass fehlerhafter Code bereitgestellt wird und die Stabilität Ihrer Produktion zu erhöhen, wird dringend empfohlen, eine "Staging"-Umgebung zu haben.

Die "Staging"-Umgebung befindet sich zwischen den "Development"- und "Production"-Umgebungen und bietet eine nahezu exakte Replik der Produktionsumgebung. Dies ermöglicht es Ihnen, Ihren Code zu testen und seine Qualität sicherzustellen, bevor Sie ihn in die Produktion bereitstellen.

Durch die Verwendung einer Staging-Umgebung können Sie sicherer in Bezug auf die Funktionalität und Leistung Ihres Codes sein und eine zuverlässigere und robustere Produktionsbereitstellung gewährleisten.

Dieser Umwelttyp wird später in der Dokumentation behandelt.

Eine Staging-Umgebung ist eine bewährte Methode, die neben Ihren Development- und Production-Umgebungen verwendet werden sollte. Sie repliziert Ihre Produktionsumgebung, sodass Sie Updates und Änderungen testen können, bevor sie live gehen.

Eine Staging-Umgebung muss die Produktionsumgebung genau widerspiegeln.

Stellen Sie jedoch sicher, dass die Staging-Umgebung ein Klon der Produktionsdatenbank verwendet und nicht die tatsächliche Produktionsdatenbank.

Wenn Ihr Ruby-Dienst mit einer Datenbank oder anderen Diensten verbunden ist, erstellen Sie diese im neuen <Project> - Staging-Stack neu.

Um eine Staging-Umgebung auf Stackhero einzurichten, folgen Sie diesen Schritten:

  1. Benennen Sie auf dem Stackhero-Dashboard Ihren vorhandenen Stack von <Project> in <Project> - Production um. Wenn Ihr Projekt beispielsweise Chat Bot heißt, benennen Sie den Stack in Chat Bot - Production um.
  2. Erstellen Sie einen neuen Stack namens <Project> - Staging. In dem vorherigen Beispiel wäre dies Chat Bot - Staging.
  3. Starten Sie einen Ruby-Dienst im Staging-Stack.
  4. Rufen Sie den Wert des git remote-Befehls ab und folgen Sie den Anweisungen im Abschnitt Bereitstellung in der Staging-Umgebung.

Durch das Befolgen dieser Schritte erhalten Sie eine korrekt konfigurierte Staging-Umgebung, um Updates zu testen und zu überprüfen, bevor sie die Produktion erreichen.

Das Verwalten separater Umgebungen wie Staging und Production wird dringend empfohlen. Wie im Abschnitt Einrichten einer Staging-Umgebung erklärt, können Sie in jede Umgebung mit unterschiedlichen Git-Remotes bereitstellen.

Beginnen Sie damit, das aktuelle Remote-Repository umzubenennen. Benennen Sie zum Beispiel das Remote "stackhero" in "stackhero-production" um, indem Sie diesen Befehl verwenden:

git remote rename stackhero stackhero-production

Erstellen Sie als Nächstes einen neuen Ruby-Dienst für die Staging-Umgebung. Verwenden Sie den bereitgestellten "git remote add"-Befehl und ändern Sie ihn wie folgt (ersetzen Sie <XXXXXX> durch die Domain Ihres Dienstes):

  • Originalbefehl:

    git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
    
  • Geänderter Befehl:

    git remote add stackhero-staging ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
    

Sie können jetzt mit folgendem Befehl in die Staging-Umgebung bereitstellen:

git push stackhero-staging main

Oder in die Produktion bereitstellen mit:

git push stackhero-production main

Um den Bereitstellungsprozess weiter zu vereinfachen, sollten Sie die verbesserte Makefile-Version in Betracht ziehen.

Mit diesem verbesserten Makefile kann die Bereitstellung in Produktion oder Staging einfach mit make deploy-production oder make deploy-staging durchgeführt werden.

Nachfolgend finden Sie ein verbessertes Makefile, das mehrere Regeln für häufige Aufgaben unterstützt:

  • make dev (oder einfach make): Startet die Anwendung im Entwicklungsmodus.
  • make deploy: Stellt die Anwendung auf dem Remote namens stackhero bereit (ideal, wenn Sie nur eine Stackhero-Instanz haben).
  • make deploy-production: Stellt die Anwendung auf dem Remote namens stackhero-production bereit.
  • make deploy-staging: Stellt die Anwendung auf dem Remote namens stackhero-staging bereit.

Dieses Makefile ist so konzipiert, dass es Fälle behandelt, in denen der Code bereits bereitgestellt wurde, und vermeidet den Fehler "Everything up-to-date".

Kopieren Sie den folgenden Inhalt in Ihr neues Makefile:

# Standardregel, die ausgeführt wird, wenn "make" ohne Argument aufgerufen wird
.DEFAULT_GOAL := dev


# Stackhero für Ruby wird die Regel "run" auf Ihrer Instanz ausführen.
# Dies ist der Befehl, der sowohl auf Produktions- als auch auf Staging-Plattformen ausgeführt wird.
run:
  rake assets:precompile
  rake db:migrate RAILS_ENV=production
  RAILS_ENV=production bundle exec puma -C config/puma.rb


# Befehl, der in der Entwicklungsumgebung ausgeführt wird
dev:
  RAILS_ENV=development rails server -b 0.0.0.0


# Die Regel "deploy" stellt auf der Instanz "stackhero" bereit.
# Geeignet, wenn Sie nur eine Instanz haben.
deploy:
  @$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero DEPLOY_BRANCH=main


# Die Regel "deploy-*" stellt auf der Instanz "stackhero-*" bereit.
# Zum Beispiel, führen Sie "make deploy-production" aus, um auf "stackhero-production" bereitzustellen,
# oder "make deploy-staging", um auf "stackhero-staging" bereitzustellen.
deploy-%:
  @$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero-$* DEPLOY_BRANCH=main


# Interne Bereitstellungsregel. Nicht ändern.
deploy-script:
  @echo "Bereitstellung des Branches \"${DEPLOY_BRANCH}\" auf \"${DEPLOY_REMOTE}\"..."
  @echo

  @if [ -n "$$(git status --porcelain)" ]; then \
    echo "Kann nicht bereitstellen, da es nicht übergebene Änderungen gibt:"; \
    echo "\e[0m"; \
    git status -s; \
    echo ""; \
    echo "\e[0;31m"; \
    echo "Sie können diesen Befehl verwenden, um die Änderungen zu übergeben:"; \
    echo "git add -A . && git commit -m \"Ihre Nachricht\""; \
    echo "\e[0m"; \
    exit 1; \
  fi

  @git push --dry-run ${DEPLOY_REMOTE} ${DEPLOY_BRANCH} 2>&1 | grep -q -F "Everything up-to-date"; \
  EXIT_CODE=$$?; \
  if [ $$EXIT_CODE -eq 0 ]; then \
    echo -n "Nichts Neues zu bereitstellen... Bereitstellung erzwingen (dies wird einen neuen Commit erstellen)? (y/N) "; \
    read answer && \
    case $$answer in \
      y|Y|yes|YES) \
      git commit --allow-empty -m "Force update for deploy purpose to \"${DEPLOY_REMOTE}\"" ; \
      ;; \
      *) \
      echo "Nichts zu bereitstellen!"; \
      exit 1; \
      ;; \
    esac \
  fi

  git push ${DEPLOY_REMOTE} ${DEPLOY_BRANCH}

Irgendwann müssen Sie Geheimnisse wie Tokens oder Passwörter für Datenbanken und Drittanbieterdienste verwalten. Es ist wichtig, diese Geheimnisse sicher zu speichern. Vermeiden Sie es, Geheimnisse direkt in Ihrem Repository oder Code einzubetten, da dies ein ernstes Sicherheitsrisiko darstellt.

Umgebungsvariablen bieten zwei wesentliche Vorteile:

  1. Ihre Geheimnisse werden nicht in Ihrem Git-Repository gespeichert, was das Risiko verringert, wenn jemand Zugriff auf Ihren Quellcode erhält.
  2. Sie können unterschiedliche Anmeldeinformationen für verschiedene Umgebungen verwenden. Zum Beispiel können Sie sich in der Produktion mit Ihrer Produktionsdatenbank verbinden, während Sie während der Entwicklung eine Entwicklungsdatenbank verwenden.

Erstellen Sie für die Entwicklung eine .env-Datei im Stammverzeichnis Ihres Projekts. Diese Datei wird von Git ausgeschlossen, sodass sie niemals übergeben wird. Verwenden Sie das dotenv-Gem, um die .env-Datei automatisch zu laden.

Fügen Sie zuerst das dotenv-rails-Gem zu Ihrem Gemfile hinzu:

# Gemfile
gem 'dotenv-rails', groups: [:development, :test]

Installieren Sie dann das Gem:

bundle install

Erstellen Sie als Nächstes eine .env-Datei im Stammverzeichnis Ihres Projekts und fügen Sie Ihre Variablen hinzu:

RAILS_ENV="development"
DATABASE_PASSWORD="secretPassword"
THIRD_API_PRIVATE_KEY="secretKey"
# ...

Stellen Sie schließlich sicher, dass die .env-Datei von Git ignoriert wird:

echo '.env*' >> .gitignore

Für Staging und Produktion ist die .env-Datei nicht sicher oder praktisch, da sie nicht in einem Git-Repository gespeichert werden kann. Stattdessen bietet Stackhero eine sichere Lösung zur Verwaltung von Umgebungsvariablen direkt in Ihrer Ruby-Dienstkonfiguration.

Sie können diese Variablen über das Stackhero-Dashboard festlegen, indem Sie Ihren Ruby-Dienst auswählen und auf die Schaltfläche "Konfigurieren" klicken.

In Ruby können Sie einfach auf Umgebungsvariablen mit ENV zugreifen. Zum Beispiel, um DATABASE_PASSWORD abzurufen, verwenden Sie:

ENV['DATABASE_PASSWORD'] # => 'secretPassword'

Hier ist ein Beispiel, wie man sich mit Umgebungsvariablen mit einem RabbitMQ-Server verbindet:

require 'bunny'

class RabbitMQClient
  def initialize
    @connection = Bunny.new(hostname: ENV['RABBITMQ_HOST'],
                            username: ENV['RABBITMQ_USERNAME'],
                            password: ENV['RABBITMQ_PASSWORD'])
    @connection.start
  end

  def publish(queue_name, message)
    channel = @connection.create_channel
    queue = channel.queue(queue_name)
    channel.default_exchange.publish(message, routing_key: queue.name)
  end

  def close
    @connection.close
  end
end

Auf der Entwicklungsplattform könnte Ihre .env-Datei Folgendes enthalten:

RABBITMQ_HOST='127.0.0.1'
RABBITMQ_USERNAME='developmentUser'
RABBITMQ_PASSWORD='developmentPassword'

Für Produktion und Staging definieren Sie Ihre Umgebungsvariablen im Stackhero-Dashboard unter der Ruby-Dienstkonfiguration wie unten gezeigt:

RABBITMQ_HOST='<XXXXXX>.stackhero-network.com'
RABBITMQ_USERNAME='production'
RABBITMQ_PASSWORD='secretProductionPassword'

Ruby-Anwendungen verwenden häufig das HTTP-Protokoll auf den Ports 80 (HTTP) und 443 (HTTPS). Wenn Ihre Anwendung zusätzliche Ports oder andere Protokolle (TCP oder UDP) benötigt, konfigurieren Sie die "Ports Redirections"-Einstellungen in Ihrem Ruby-Dienst über das Stackhero-Dashboard.

Sie müssen den Eingangsport (öffentlich geöffnet), den Zielport (innerhalb Ihres Ruby-Dienstes geöffnet) und das Protokoll (TCP oder UDP) angeben.

Für das Speichern von Dateien wie Benutzerfotos oder Dokumenten wird dringend empfohlen, eine Object-Storage-Lösung zu verwenden. Object Storage ermöglicht es Ihnen, Dateien über mehrere Dienste und Instanzen hinweg zu teilen und entkoppelt die Speicherebene von Ihrem Code. Dies wird als bewährte Methode angesehen.

Wir empfehlen MinIO als einfache, schnelle und leistungsstarke Lösung, die mit dem Amazon S3-Protokoll kompatibel ist.

Wenn Sie sich für die lokale Dateispeicherung entscheiden, können Sie den persistenten Speicher verwenden, der mit Ihrer Ruby-Instanz bereitgestellt wird. Dieser lokale Speicher ist im Verzeichnis /persistent/storage/ verfügbar.

Lokale Dateispeicherung wird jedoch im Allgemeinen nicht empfohlen, da sie möglicherweise nicht die beste Praxis für langfristige Skalierbarkeit und Zuverlässigkeit darstellt.

WARNUNG: Speichern Sie niemals Daten außerhalb des Ordners /persistent/storage/!

Das Speichern von Daten an einem anderen Ort als dem persistenten Speicherordner kann zu Datenverlust führen, wenn Ihre Instanz neu gestartet, aktualisiert oder wenn Sie neuen Code pushen.

Wenn Sie macOS verwenden, finden Sie es möglicherweise umständlich, jedes Mal, wenn Sie Ihren Code pushen, das Passwort Ihres SSH-Privatschlüssels einzugeben. Obwohl Sicherheit wichtig ist, können Sie die Bequemlichkeit verbessern, indem Sie Ihr Passwort sicher im Apple-Schlüsselbund speichern.

Es kann verlockend sein, das Passwort von Ihrem SSH-Privatschlüssel zu entfernen, aber das ist nicht ratsam.

Speichern Sie stattdessen Ihr Schlüsselpaar-Passwort im Schlüsselbund, indem Sie den folgenden Befehl für einen Schlüssel namens id_ed25519 verwenden:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Nachdem Sie diesen Befehl ausgeführt haben, sollten Sie nicht mehr nach Ihrem Schlüsselpasswort gefragt werden. Wenn Sie einen RSA-Schlüssel verwenden, ersetzen Sie id_ed25519 durch id_rsa wie unten gezeigt:

ssh-add --apple-use-keychain ~/.ssh/id_rsa