18.4 Deployment mit Capistrano
Im folgenden Abschnitt erläutern wir, wie leicht man eine Rails-Applikation mit Capistrano veröffentlichen kann. Wir zeigen zunächst Schritt für Schritt, welche Befehle auszuführen sind. Erst am Ende des Kapitels werden wir uns die Funktionsweise von Capistrano näher anschauen.
Projekt in Subversion überführen
Wie bereits mehrfach angesprochen, muss das Railsprojekt spätestens vor der Veröffentlichung mit Capistrano in ein Subversion-Repository überführt werden. Am besten ist es natürlich, wenn dies direkt nach der Generierung des Railsprojekts durchgeführt wird.
Im Abschnitt »Ein Rails-Projekt in Subversion überführen« in Kapitel 7 wird ausführlich erläutert, wie Sie Ihre Applikation in ein Repository importieren. Verwenden Sie die Subversion-Repository-URL
svn+ssh://deploy@railsair.com/srv/svn/railsair
Konfiguration der Datenbank
database.yml
Im Abschnitt 7.13 haben wir für das Projekt eine leere Datenbank mit Usernamen und Passwort angelegt, für die wir in der Konfigurationsdatei config/database.yml in der Umgebung production folgende Einstellungen vornehmen:
Listing config/database.yml
...
production:
adapter: mysql
encoding: utf8
database: railsair_production
username: railsair
password: geheim
socket: /var/run/mysqld/mysqld.sock
...
commit
Die anderen Umgebungen (wie development und test) werden ohne Änderungen übernommen. Es spielt auch keine Rolle, wenn in den anderen Umgebungen eine andere Datenbank (z. B. SQLite3) konfiguriert ist.
Wir dürfen anschließend nicht vergessen, die Änderungen in das Repository zu übertragen:
svn commit -m 'Datenbank fuer production-Umgebung konfiguriert'
Installation
Capistrano muss nur auf dem Entwicklungsrechner installiert werden:
Listing Installation von Capistrano
sudo gem install capistrano
Damit Capistrano in einem Projekt verwendet werden kann, müssen folgende Schritte durchgeführt werden.
Capistrano in Rails-Applikation konfigurieren
Mit dem Befehl capify pfad_zum_projekt werden alle erforderlichen Konfigurationsdateien automatisch erstellt.
Wechseln Sie am besten in das Verzeichnis der Rails-Applikation, und führen Sie folgenden Befehl aus:
capify .
[add] writing `./Capfile'
[add] writing `./config/deploy.rb'
[done] capified!
deploy.rb
Die Datei Capfile gibt u. a. an, wo sich die eigentliche Konfigurationsdatei befindet. Dies ist im Falle von Rails die Datei deploy.rb im Verzeichnis config.
Die Datei deploy.rb passen wir wie folgt an:
Listing /etc/apache2/sites-available/railsair.conf
require 'mongrel_cluster/recipes' # ============================= # = Allgemeine Einstellungen = # ============================= set :application, "railsair" set :domain, "railsair.com" set :repository, "svn+ssh://deploy@railsair/srv/svn/railsair/trunk" set :deploy_to, "/srv/www/#{application}" set :scm, :subversion set :deploy_via, :export # default ist :checkout set :user, "deploy" # default ist der aktuelle User set :use_sudo, false # Verwende kein sudo # ========= # = Roles = # ========= role :app, "#{domain}" role :web, "#{domain}" role :db, "#{domain}", :primary => true # =========== # = Mongrel = # =========== # Anzahl Mongrel-Servers set :mongrel_servers, 3 # Erste Port-Nummer, die verwendet wird. # Bei drei Servern werden 8020, 8021 und 8022 verwendet. set :mongrel_port, 8020 # Path to conf file. # Defaults to /etc/mongrel_cluster/app_name.conf set :mongrel_conf, "/etc/mongrel_cluster/#{application}.yml" # Rails-Umgebung (Environment) in der die Rails-Applikation # ausgeführt wird set :mongrel_environment, 'production'
Verzeichnisse auf dem Server erstellen
Mit dem Capistrano-Task cap deploy:setup werden Verzeichnisse zur
Vorbereitung auf den Server erstellt. Im Abschnitt 18.4.10 werden die Verzeichnisse näher erläutert.
Während des Setup-Vorgangs werden Sie nach dem Passwort des Users
deploy gefragt.
Mongrel-Cluster-Konfigurationsdatei auf dem Server generieren
Mit dem Capistrano-Taskcap mongrel:cluster:configure
Übertragen und Starten der Rails-Applikation
cap deploy:cold
Beim allerersten Übertragen der Applikation auf den Server wird der Capistrano-Task
cap deploy:cold
verwendet.
Der Task cap deploy:cold führt folgende Schritte aus:
- Dateien aus dem Repository auf den Server übertragen
- Alle Migrations ausführen
- Applikation (Mongrel-Server) starten
Beachten Sie, dass nur die Dateien auf den Server übertragen werden, die Sie im Repository eingecheckt haben.
Aufruf im Browser
Wenn der erste deploy erfolgreich war, können Sie Ihre Web-Applikation unter der entsprechenden Domain im Webbrowser aufrufen.
Hinweis |
Wenn sich in Ihrem Projekt noch die von Rails erzeugte index.html -Datei im Public-Verzeichnis befindet und diese Seite angezeigt wird, so ist das noch kein Beweis dafür, dass Rails auf dem Server ausgeführt wird. Irritierend wirkt die Fehlermeldung (»The Page ... doesn't exist«), wenn man auf den About-Link klickt. |
Abbildung Aufruf der Original-Index-Seite
Aus Sicherheitsgründen werden in der Produktionsumgebung keine Statusinformationen, wie z. B. der Name der Datenbank, angezeigt. Um zu prüfen, ob die Rails-Applikation läuft, rufen Sie eine URL auf, die von einem Controller verarbeitet werden muss (z. B. http://domain/countries ).
cap deploy:"=migrations
Wenn die Rails-Applikation bereits läuft, verwenden wir für das Deployment den Befehl cap deploy:migrations oder cap deploy . Der Task cap deploy:migrations führt folgende Aktionen auf dem Server durch:
- Übertragung der Applikation
- alle Migrations, die neu hinzugekommen sind, werden ausgeführt
- Restart der Mongrel-Server
cap deploy
Der Task cap deploy führt die gleichen Schritte wie der Task cap deploy:migrations aus, nur werden keine Migrations ausgeführt.
Gelegentlich ist es sinnvoll, die Applikation ohne Übertragung der Dateien, zu starten (cap deploy:start), anzuhalten (cap deploy:stop) oder neu zu starten (cap deploy:restart).
Die letzte Übertragung rückgängig machen
cap deploy:"=rollback
In der Praxis trifft man gelegentlich auf folgendes Ereignis: Sie haben eine neue Funktion implementiert und lokal getestet. Nach dem Deployment auf den Server (z. B. mit dem Befehl cap deploy) stellen Sie fest, dass es zu einem Applikation-Error kommt. Was tun?
Nach dem Fehler zu suchen, dauert in der Regel zu lange. Abhilfe schafft der Task
cap deploy:rollback
Neue Releases
Bei jedem Deployment werden die alten Dateien nicht gelöscht, sondern jeweils ein neues Verzeichnis ( Release ) erstellt. Bei einem Rollback wird einfach das Verzeichnis der vorherigen Übertragung verwendet und dann die Server-Applikation neu gestartet.
Dies wird im Abschnitt 18.4.10 näher erläutert.
cap deploy:clean
Gelegentlich ist es sinnvoll, den Task cap deploy:clean aufzurufen, der bis auf die letzten fünf alle älteren Releases löscht.
Anzeigen einer Wartungsseite
Wenn Sie auf Ihrem Server ein Problem haben oder aus sonstigen Gründen die Rails-Applikation deaktivieren möchten, ist es naheliegend, den Capistrano-Task cap deploy:stop auszuführen. Dies hat jedoch folgende Nachteile:
- Dem Besucher Ihrer Website wird die Fehlermeldung »Service Temporarily Unavailable« angezeigt.
- Seiten, für die Sie Page-Caching aktiviert haben, werden dennoch angezeigt (siehe Abschnitt 16.2).
Abbildung Fehlermeldung
Wartungsseite
Capistrano bietet jedoch eine hervorragende Lösung für das Problem.
cap deploy:web:disable
Der Task überträgt eine Wartungsseite auf den Server, die den Kunden darauf hinweist, dass die Applikation »down« ist und in Kürze wieder verfügbar sein wird.
Abbildung Anzeige der Wartungsseite
REASON, UNTIL
Sie haben die Möglichkeit, den anzuzeigenden Text mit den Optionen REASON und UNTIL zu beeinflussen:
cap deploy:web:disable \ REASON="hardware upgrade" \ UNTIL="18:00"
Abbildung Anzeige der Wartungsseite
Nachteil
Der Nachteil der Wartungsseite ist, dass die Seite auf Englisch erscheint und dass wir das Design nicht beeinflussen können. Wir können jedoch einen eigenen Capistrano-Task schreiben, der eine von uns gestaltete Wartungsseite anzeigt.
Lösung
Dazu fügen wir am Ende der Datei config/deploy.rb folgenden Task hinzu:
Listing config/deploy.rb
namespace :deploy do namespace :web do desc <<-DESC Es wird die Wartungsseite maintenance.html im Verzeichniss public angezeigt. DESC task :disable, :roles => :web, :except => { :no_release => true } do on_rollback { run "rm #{shared_path}/system/maintenance.html" } run "ln -s #{current_path}/public/maintenance.html #{shared_path}/system/maintenance.html" end end end
Damit der Task funktioniert, muss die Wartungsseite maintenance.html im Verzeichnis public abgespeichert und dem Repository hinzugefügt werden:
svn add public/maintenance.html svn commit public/maintenance.html -m 'Wartungsseite'
Wenn Sie Bilder auf der Wartungsseite verwenden, sollten diese Bilder auf einer anderen Website liegen, damit sie angezeigt werden.
Da wir den Task disable überschrieben haben, können wir mit dem gleichen Befehl cap deploy:web:disable die von uns erstellte Wartungsseite einblenden lassen:
Abbildung Anzeige der individuellen Wartungsseite
Wartungsseite entfernen
Mit dem Capistrano-Task cap deploy:web:enable wird die Wartungsseite wieder entfernt. Die Website ist dann wieder erreichbar.
Übertragung einzelner Dateien
Je nach Größe der Applikation kann ein deploy schon ein paar Minuten laufen. Wenn Sie nur einzelne Bilder oder CSS-Dateien auf die Schnelle austauschen wollen, können Sie sie mit dem Task cap deploy:upload einzeln hochladen, ohne dass die Dateien vorher ins SVN-Repository übertragen werden müssen.
Mit der Option FILES können Sie die zu übertragenden Dateien bzw. Verzeichnisse angeben:
- Übertragung einer einzelnen Datei:
cap deploy:upload FILES=public/stylesheets/global.css
- Übertragung von mehreren Dateien:
cap deploy:upload \ FILES=public/images/bild-1.jpg,public/images/bild-2.jpg
- Übertragen von ganzen Verzeichnissen:
cap deploy:upload FILES=public/stylesheets
Wenn Sie jedoch Dateien aus dem app -Verzeichnis, wie z. B. Template-Dateien, hochladen, müssen Sie nach dem Upload die Rails-Applikation mit cap deploy:restart neu starten, damit die Änderungen wirksam werden.
Wie Capistrano einen Deploy durchführt
Nachdem wir erfolgreich mit Capistrano unsere Applikation veröffentlicht haben, wird es Zeit, hinter die Kulissen von Capistrano zu schauen.
Capistrano geht sehr clever bei der Veröffentlichung auf dem Server vor. Wir zeigen im Folgenden, wie Capistrano die Deploys auf dem Server verwaltet.
Unterverzeichnisse
Vor dem ersten Deployment wird der Task cap deploy:setup ausgeführt. Im Verzeichnis, das in der Variablen deploy_to in der Datei config/deploy.rb festgelegt ist, werden folgende Unterverzeichnisse erstellt:
Abbildung Verzeichnisstruktur nach einem cap deploy:setup
- releases
In diesem Verzeichnis werden die übertragenen Dateien (Deploy-Dateien) jeweils in einem eigenen Unterverzeichnis gespeichert. Jeder Deploy wird als Release bezeichnet.
- shared
Das shared-Verzeichnis enthält Verzeichnisse und Dateien, die für alle Releases verfügbar sein sollen.
- shared/log
Im log-Verzeichnis werden die Protokollierungs-Dateien abgelegt, wie z. B. die production.log-Datei.
- shared/pid
Im pids-Verzeichnis werden Prozess-IDs verwaltet.
- shared/system
Beim Aufruf des Tasks cap deploy:web:disable wird die maintenance.html in das system-Verzeichnis hochgeladen.
Bei Ausführung eines Deploy-Tasks, z. B. mit dem Befehl cap deploy:cold, cap deploy:migrations oder cap deploy, wird immer der Task cap deploy:update ausgeführt.
Capistrano-Task
Der Capistrano-Task cap deploy:update führt folgende Schritte aus (wir gehen im Folgenden davon aus, dass schon mehrere Übertragungen durchgeführt wurden):
- Neues Verzeichnis im »releases«-Verzeichnis erstellen
Es wird im Verzeichnis releases ein neues Verzeichnis erstellt, in das die Projektdateien aus dem Repository, das in der Variablen repository in der Datei config/deploy.rb festgelegt wurde, übertragen werden. Der Verzeichnisname setzt sich aus dem aktuellen Datum und der aktuellen Uhrzeit zusammen. Die älteren Veröffentlichungen werden nicht gelöscht.
Abbildung releases-Verzeichnis (Schritt 1)
- Verzeichnisse »log« und »pids« im neuen Release-Verzeichnis löschen
Abbildung releases-Verzeichnis (Schritt 2)
- Symbolischen Link von »shared/log«, »shared/pids« und »shared/system« setzen
Im Verzeichnis log werden Protokollierungsdateien gespeichert. Die Prozess-IDs werden im pids -Verzeichnis abgelegt und im Verzeichnissystem wird die Wartungsseite gespeichert.
Abbildung releases-Verzeichnis (Schritt 3)
- Symbolischen Link vom letzten Release-Verzeichnis auf »current« setzen
Symlink
Das Verzeichnis current enthält die aktuelle Version der Rails-Applikation. Dies wird durch Setzen eines symbolischen Links auf das letzte Release-Verzeichnis erreicht.
Abbildung releases-Verzeichnis (Schritt 4)
Die Technik, einfach symbolische Links einzusetzen, wird auch von dem Capistrano-Task cap deploy:rollback eingesetzt. Wenn dieser Task aufgerufen wird, wird u. a. einfach der symbolische Link von current auf das vorletzte Release-Verzeichnis gesetzt.
Abbildung releases-Verzeichnis (Schritt 5)
Verzeichnisse, die nicht im Repository sind, verwalten
Bei jedem Deploy-Vorgang werden sämtliche Dateien aus dem Repository in ein neues Release-Verzeichnis kopiert. Es ist aber nicht sinnvoll, jede Datei ins Repository zu überführen. Angenommen, Sie haben Hunderte von PDF-Dokumenten, die per (S)FTP aktualisiert werden sollen.
Wir gehen dann wie folgt vor:
- Verzeichnis »pdfs« erstellen
Legen Sie das Verzeichnis pdfs im Verzeichnis shared auf dem Server an.
Abbildung shared-Verzeichnis
- Neuen Task in »config/deploy.rb« hinzufügen
Am Ende der Datei config/deploy.rb fügen wir einen neuen Task hinzu, der automatisch einen symbolischen Link von shared/pdfs nach public/pdfs innerhalb des aktuellen Links setzt.
Listing config/deploy.rb ergänzen
... after 'deploy:update_code', 'symlink_pdf' desc "PDF " task :symlink_pdf do run "ln -nsf #{shared_path}/pdfs #{release_path}/public/pdfs" end
- Upload der PDFs
Die Dateien können nun ins Verzeichnis /srv/www/railsair/shared/pdfs/ hochgeladen werden. Bei jedem Deploy werden automatisch die symbolischen Links korrekt gesetzt.
Abbildung Symbolischer Link
Weitere Capistrano-Tasks
cap -T
Die Capistrano-Tasks haben große Ähnlichkeit mit den Rake-Tasks. Mit dem Befehl cap -T können Sie die Liste aller Capistrano-Tasks aufrufen:
cap -T cap deploy # Deploys your project. cap deploy:check # Test deployment dependencies. cap deploy:cleanup # Clean up old releases. cap deploy:cold # Deploys and starts a `cold' # application. cap deploy:migrate # Run the migrate rake task. cap deploy:migrations # Deploy and run pending # migrations. cap deploy:pending # Displays the commits since # your last deploy. cap deploy:pending:diff # Displays the `diff' since your # last deploy. cap deploy:restart # Restart the Mongrel processes # on the app server cap deploy:rollback # Rolls back to a previous # version and restarts. cap deploy:rollback_code # Rolls back to the previously # deployed version. cap deploy:setup # Prepares one or more servers # for deployment. cap deploy:start # Start the Mongrel processes # on the app server... cap deploy:stop # Stop the Mongrel processes on # the app server ... cap deploy:symlink # Updates the symlink to the most # recently depl... cap deploy:update # Copies your project and updates # the symlink. cap deploy:update_code # Copies your project to the # remote servers. cap deploy:upload # Copy files to the currently # deployed version. cap deploy:web:disable # Present a maintenance page to # visitors cap deploy:web:enable # Makes the application # web-accessible again. cap invoke # Invoke a single command on the # remote servers. cap mongrel:cluster:configure # Configure Mongrel processes on # the app server. cap mongrel:cluster:restart # Restart the Mongrel processes # on the app serv... cap mongrel:cluster:start # Start Mongrel processes on the # app server. cap mongrel:cluster:status # Check the status of the Mongrel # processes on ... cap mongrel:cluster:stop # Stop the Mongrel processes on # the app server. cap shell # Begin an interactive Capistrano # session.
Mit dem Befehl cap -e name-des-tasks können detailliertere Informationen angezeigt werden:
Deploy ohne Passwortabfrage |
Wenn Sie häufig Capistrano verwenden, ist es praktisch, wenn Sie nicht
jedes Mal das Passwort eingeben müssen. Um das einzurichten, müssen Sie
einen privaten und einen öffentlichen SSH-Schlüssel generieren und den
öffentlichen Schlüssel auf dem Server ablegen. Führen Sie dazu folgende
Schritte auf Ihrem lokalen Rechner durch:
Um zu vermeiden, dass Sie nach dem Passwort des SVN-Repository gefragt werden, sollten Sie sich mit dem User deploy an dem Server anmelden und einen SVN-Befehl, wie z. B. den List-Befehl, ausführen: ssh deploy@ihr-server "svn list \ =svn+ssh://ihr-server/srv/svn/railsair"= |
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.