Ruby Applikationen betreiben
Dieser Artikel erklärt, wie man Ruby-Anwendungen auf Nines Managed Servern betreibt.
Wenn Sie Ihre Anwendung in einem Container ausführen möchten, finden Sie in unserem Artikel zu Podman die wichtigsten Informationen.
Container ermöglichen Ihnen, Ihre Anwendung in unterschiedlichen Umgebungen betreiben zu können, ohne dabei wesentliche Anpassungen an der Applikation selbst vornehmen zu müssen. Container erleichtern zudem die Verwaltung von Abhängigkeiten und helfen Ihnen, Ihre Anwendung zu skalieren, indem sie sie von anderen Prozessen im System isolieren.
Anforderungen
Für das folgende Beispiel nehmen wir an, dass Ihre Anwendung einen Ruby Webserver wie puma, thin, etc. unterstützt. Rails wird standardmässig mit puma
ausgeliefert, weshalb wir diesen in unserem Beispiel verwenden.
1. Installieren Sie den Ruby Version-Manager
Um verschiedene Ruby-Versionen unabhängig des eingesetzten Betriebssystems zu verwenden, empfehlen wir die Nutzung eines Versionsmanagers wie rbenv
.
So installieren Sie rbenv
:
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
2. Ruby-Version installieren
Die gewünschte Ruby-Version kann nun installiert werden:
rbenv install --list # installierbare Versionen auflisten
rbenv install 3.2.0
Aktualisieren Sie anschliessend "Bundler" auf die neueste Version:
rbenv exec bundle update --bundler
3. Anwendung deployen
Das Deployment Ihrer Anwendung ist für jedes Projekt unterschiedlich. Mit Rails müssen Sie Assets kompilieren, sie und den Code auf den Server hochladen und Ruby-Abhängigkeiten installieren:
Führen Sie diese Befehle auf Ihrem lokalen Rechner aus
Assets kompilieren:
RAILS_ENV=production bundle exec rake assets:precompile
Dateien auf den Server kopieren:
rsync -a -v --delete --exclude='node_modules/*' --exclude='tmp/*' --exclude='vendor/*' --exclude='.git/*' ./ www-data@server.nine.ch:app/current
Sicherstellen, dass die Abhängigkeiten aktuell sind:
ssh www-data@server.nine.ch 'cd ~/app/current && BUNDLER_WITHOUT="development test" rbenv exec bundle install'
4. systemd-Service einrichten
Um sicherzustellen, dass ein Dienst weiterläuft, z.B. neu gestartet wird wenn er ausfällt oder nach einem Neustart des Servers wieder startet, empfehlen wir die Verwendung eines Systemd-Benutzerdienstes.
Dieses Beispiel lädt Umgebungsvariablen von ~/app/env
und führt dann rails server -b localhost --log-to-stdout
im Verzeichnis ~/app/current
aus.
Die Konfiguration für eine solchen Systemd-Service hängt von Ihrer Anwendung ab. Das obige Beispiel geht davon aus, dass Sie eine Rails-Anwendung ausführen.
Erstellen Sie die Servicedatei in ~/.config/systemd/user/rails-app.service
.
[Unit]
Description=Anwendung
[Service]
Type=simple
WorkingDirectory=%h/app/current
Environment=RAILS_ENV=production
Environment=PORT=3000
EnvironmentFile=%h/app/env
ExecStart=%h/.rbenv/bin/rbenv exec bundle exec rails server -b localhost --log-to-stdout
TimeoutSec=15
Restart=on-failure
PrivateTmp=yes
ProtectSystem=full
[Install]
WantedBy=default.target
Im nächsten Schritt wird der Dienst aktiviert und gestartet:
touch ~/app/env # sicherstellen, dass die Umgebungsdatei existiert
systemctl --user daemon-reload
systemctl --user enable rails-app.service
systemctl --user start rails-app.service
Ihre Anwendung sollte nun als Dienst registriert und bereits gestartet sein:
$ systemctl --user status rails-app.service
● rails-app.service - Anwendung
Loaded: loaded (/home/www-data/.config/systemd/user/rails-app.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-07-16 10:13:36 CEST; 5s ago
Main PID: 3615317 (ruby)
CGroup: /user.slice/user-33.slice/user@33.service/rails-app.service
└─3615317 puma 5.3.2 (tcp://localhost:3000) [current]
Jul 16 10:13:37 server rbenv[3615317]: => Run `bin/rails server --help` for more startup options
Jul 16 10:13:37 server rbenv[3615317]: Puma starting in single mode...
Jul 16 10:13:37 server rbenv[3615317]: * Puma version: 5.3.2 (ruby 3.0.2-p107) ("Sweetnighter")
Jul 16 10:13:37 server rbenv[3615317]: * Min threads: 5
Jul 16 10:13:37 server rbenv[3615317]: * Max threads: 5
Jul 16 10:13:37 server rbenv[3615317]: * Environment: production
Jul 16 10:13:37 server rbenv[3615317]: * PID: 3615317
Jul 16 10:13:37 server rbenv[3615317]: * Listening on http://127.0.0.1:3000
Jul 16 10:13:37 server rbenv[3615317]: * Listening on http://[::1]:3000
Jul 16 10:13:38 server rbenv[3615317]: Use Ctrl-C to stop
Fehlerbehebung
- Stellen Sie sicher, dass die
.bashrc
korrekt geladen wird - Überprüfen Sie, ob der Dienst korrekt gestartet wurde:
systemctl --user status app.service
- Überprüfen Sie die Log-Ausgabe:
journalctl --user -f
Weitere Informationen zur Verwendung von Systemd finden Sie im folgendem Support-Artikel.
5. Webserver konfigurieren
Dadurch sollte Ihre Anwendung über http
zugänglich sein. Um https
-Unterstützung hinzuzufügen, verwenden Sie bitte proxy_letsencrypt_https
, wie in nine-manage-vhosts mit Let's Encrypt dokumentiert.
Die Anwendung läuft jetzt auf einem lokalen Port. Um die Anwendung über http
und https
zu erreichen, muss der Webserver diese Anfragen an den lokalen Port weiterleiten.
Auf Ihrem Managed Server sind bereits zwei nine-manage-vhost Vorlagen für diesen Anwendungsfall vorinstalliert: proxy
und proxy_letsencrypt
.
Erstellen Sie einen neuen vHost und geben den lokalen Port der Anwendung über die Variable PROXYPORT
an:
$ sudo nine-manage-vhosts virtual-host create example.com --template proxy --template-variable PROXYPORT=3000 --webroot ~/exampleapp/static
Virtual Host created: example.com
example.com
===========
DOMAIN: example.com
USER: www-data
WEBROOT: /home/www-data/exampleapp/static
TEMPLATE: proxy
TEMPLATE VARIABLES: PROXYPORT
3000
ALIASES: www.example.com
example.com.server.nine.ch
Bei Aufruf der URL http://example.com.server.nine.ch
wird nun Ihre Applikation angesprochen.
Automatisierung des Deployments
Um das Deployment Ihrer Ruby-Anwendung zu automatisieren, können Sie Capistrano verwenden, ein Automatisierungstool für Remote-Server. Nachfolgend sind die Schritte zur Einrichtung und Verwendung von Capistrano aufgeführt:
Capistrano installieren
Fügen Sie Capistrano zu Ihrem Gemfile
hinzu:
group :deployment do
gem 'capistrano', require: false
gem 'capistrano-rbenv', require: false
gem 'capistrano-rbenv-install', require: false
gem 'capistrano-rails', require: false
gem 'capistrano-systemd-multiservice', require: false
end
Führen Sie anschliessend die folgenden Befehle aus:
bundle install
cap install
Dies erstellt mehrere Standardkonfigurationsdateien für Capistrano in Ihrem Projekt.
Capistrano konfigurieren
Bearbeiten Sie die Datei Capfile
, um die erforderlichen Capistrano-Plugins einzuschliessen:
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git
require 'capistrano/rbenv'
require 'capistrano/rbenv_install'
require 'capistrano/bundler'
require 'capistrano/rails'
require "capistrano/systemd/multiservice"
install_plugin Capistrano::Systemd::MultiService.new_service("app", service_type: "user")
# Laden Sie benutzerdefinierte Aufgaben aus `lib/capistrano/tasks`, falls vorhanden
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
Bearbeiten Sie die Datei config/deploy.rb
, um die Deployment-Einstellungen zu definieren:
lock "~> 3.16"
set :application, "your_app_name"
set :repo_url, "git@example.com:me/my_repo.git"
set :branch, ENV.fetch("CI_COMMIT_REF_NAME", "main")
set :deploy_to, "/home/#{fetch :user}/#{fetch :application}"
set :keep_releases, 5
set :rbenv_type, :user
set :rbenv_ruby, File.read(".ruby-version").strip
set :rbenv_path, "/home/#{fetch :user}/.rbenv"
append :linked_files, "env"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle", "public/system"
before "systemd:app:validate", "systemd:app:setup"
after "deploy:publishing", "systemd:app:restart"
Hinterlegen Sie die Serverdetails in der Datei config/deploy/production.rb
:
server 'server.nine.ch', user: 'www-data', roles: %w{app db web}
Definieren Sie die Ruby-Version in einer .ruby-version
Datei:
3.2.0
Erstellen Sie anschliessend ein Template für den Systemd-Service in config/systemd/app.service.erb
:
[Unit]
Description=<%= fetch :application %> Rails-Anwendung
[Service]
Type=simple
WorkingDirectory=<%= current_path %>
Environment=RAILS_SERVE_STATIC_FILES=true
EnvironmentFile=<%= shared_path %>/env
ExecStart=%h/.rbenv/bin/rbenv exec bundle exec rails server -b localhost --log-to-stdout
TimeoutSec=15
Restart=on-failure
PrivateTmp=yes
ProtectSystem=full
[Install]
WantedBy=default.target
Deployment mit Capistrano
Nun können Sie Ihre Anwendung mit Capistrano mit dem folgenden Befehl deployen:
bundle exec cap production deploy
Capistrano kümmert sich um die Details des Deployments, einschliesslich der Verwaltung der Ruby-Version, Abhängigkeiten, Asset-Kompilierung, Dateiübertragung und Verwaltung des systemd-Dienstes.
Dieses Vorgehen stellt sicher, dass Ihr Deployment optimiert und weniger fehleranfällig ist, wodurch effizientere und zuverlässigere Veröffentlichungen ermöglicht werden.