Vagrant ist ein Tool, das portable virtuelle Entwicklungsumgebungen ermöglicht. Wenn an verschiedenen Rechnern und/oder von verschiedenen Team-Mitgliedern an einem Projekt gearbeitet wird, ist somit eine einheitliche Umgebung sichergestellt. Die Einrichtung muss nur ein einziges Mal erfolgen und kann beliebig oft reproduziert werden.

Aber es ist auch für einzelne Entwickler interessant, die an unterschiedlichen Projekten arbeiten. Häufig sind z.B. auf den Produktivsystemen unterschiedliche PHP-Versionen installiert, es werden bestimmte Extensions benötigt oder unterschiedliche Systemkonfigurationen. Gerade bei der Entwicklung mit PHP, dessen Verhalten an vielen Stellen von globaler Konfiguration abhängt, gibt es so oft Fehler aufgrund unterschiedlicher Systeme.

Mit Vagrant lässt sich die gesamte Umgebung für jedes Projekt einzeln definieren und auch versionieren (Konfigurationsdateien im Git-Repository). Auch wird das eigene System weniger „vollgemüllt“, mit Software die man für irgendein Projekt mal benötigt hat. Im Idealfall spiegelt die Umgebung das Produktivsystem 1:1 wieder.

Say goodbye to „works on my machine“ bugs. – http://docs.vagrantup.com/v2/why-vagrant/

Diese Artikelserie soll insbesondere Magento-Entwickler Schritt für Schritt an Vagrant heranführen, am Ende steht ein Basis-Setup für Magento-Projekte.

Benötigte Software

Vagrant

Vagrant kann hier heruntergeladen werden: https://www.vagrantup.com/downloads.html

Virtualbox

Vagrant verwaltet virtuelle Maschinen, benötigt dazu aber eine Virtualisierungsplattform. Oracle Virtualbox ist eine kostenlose Anwendung dazu. Zum Download geht es hier: https://www.virtualbox.org/wiki/Downloads

Wir benötigen die VirtualBox platform packages für unser Betriebssystem und das VirtualBox Extension Pack. Der Dateityp .vbox-extpack ist mit VirtualBox verknüpft, beim Öffnen installiert sich das Extension Pack selbst.

Achtung, auf manchen Rechnern muss 64 Bit Virtualisierung erst im BIOS aktiviert werden (CPU virtualization features). Bei Lenovo-Rechnern findet man die Einstellung z.B. unter Security > Virtualization, bei anderen in der CPU-Sektion). Wenn die Box sehr lange zum booten braucht und am Ende nach mehreren „Connection timeout. Retrying…“ Meldungen abbricht, kann dies die Ursache sein.

Unter Windows: Cygwin

Wir benötigen außerdem eine Shell mit rsync-Unterstützung, die besten Erfahrungen habe ich hier mit Cygwin gemacht, andere nutzen die Git Bash oder auch die Windows-Kommandozeile mit rsync.exe (z.B. von DeltaCopy: http://www.chip.de/downloads/DeltaCopy_33633791.html)

Zum Download von Cygwin. Achtung, Cygwin kann Probleme bei Windows-Dateinamen mit Leerzeichen haben, installiere es also am besten in C:\Cygwin (C:\Programme heißt ja intern C:\Program Files).

Bei der Installation von Cygwin müssen zu installierende Pakete ausgewählt werden, suche hier nach „rsync“ und „openssh“ und klicke in den Ergebnissen auf „Skip“ um die Pakete zur Installation auszuwählen. Weitere Pakete sind für unsere Zwecke nicht notwendig, können aber nach Belieben hinzugefügt werden, auch im Nachhinein. Dazu einfach das Installationsprogramm erneut aufrufen.

Es kann auch sinnvoll sein, das HOME-Verzeichnis von Cygwin zu ändern, siehe dazu die folgenden Links:

Für schnellen Zugriff auf meine Projekte habe ich einen Mountpoint im Cygwin HOME-Verzeichnis erstellt, dazu habe ich die Datei /etc/fstab.d/fs angelegt („fs“ muss durch den jeweiligen Benutzernamen ersetzt werden!) und folgende Zeile hinzugefügt:

C:/Users/fs/Projekte ist mein Projekt-Verzeichnis unter Windows. Die Vorwärts-Slashes im Windows-Verzeichnisnamen sind wichtig! Nun noch in Cygwin „/home/fs/projekte“  als leeres Verzeichnis anlegen und beim nächsten Start ist das Verzeichnis direkt zur Hand. Es können beliebig viele solcher Mountpoints erstellt werden, falls Projekte von unterschiedlichen Orten verwendet werden sollen.

Für PHPStorm-Nutzer interessant: Wenn man unter Default Settings > Terminal > Shell Path den Pfad zu Cygwin.bat einträgt, wird Cygwin für das integrierte Terminal verwendet und wir können alles bequem von dort steuern:

Terminal - Vagrant-Einführung

Terminal

Erste Schritte

Wer direkt etwas experimentieren will, sollte jetzt einen Blick in die Vagrant Dokumentation unter Getting Started werfen. Um eine einfache Ubuntu-Box mit Standard-Einstellungen aufzusetzen, genügen folgende Befehle in dem Verzeichnis, in dem die Vagrantbox erstellt werden soll:

Und per SSH einloggen geht so:

Es ist auch mit Putty möglich, die nötigen Parameter werden nach dem Start mit vagrant up angezeigt. Da die Cygwin-Konsole genauso komfortabel ist, bevorzuge ich aber die obige Variante.

Der init-Befehl hat eine VirtualBox VM erstellt und ein Ruby-Script namens Vagrantfile, das die Konfiguration der VM steuert. In der Datei selbst ist bereits vieles in Kommentaren dokumentiert, ansonsten ist die Dokumentation auf http://docs.vagrantup.com/ sehr hilfreich.

Rsync vs. Shared Folders

Irgendwie müssen die Projekt-Dateien vom Host auf der Vagrantbox zur Verfügung gestellt werden. Vagrant bietet verschiedene Strategien dazu an. Aktuell (Stand: Vagrant 1.6.3) sind dies NFS, Rsync, SMB und VirtualBox Shared Folders. Link zur Dokumentation: http://docs.vagrantup.com/v2/synced-folders/index.html

Da die Performance des Dateisystems für Magento Entwicklung essentiell ist, lohnt sich hier ein näherer Vergleich. Vorab: Der Standard, Virtualbox Shared Folders, ist grausam langsam und keine brauchbare Option. Der Vagrant-Entwickler selbst, Mitchell Hashimoto hat die Performance von NFS, VirtualBox Shared Folders und VMware Shared Folders den jeweiligen nativen Dateisystemen gegenübergestellt und kommt zu dem Schluss, dass NFS die zweitbeste Wahl ist.

Der Haken: NFS steht bei Windows Hosts nicht zur Verfügung. SMB als Alternative für Windows schneidet in anderen Erfahrungsberichten auch nur mäßig besser als VirtualBox Shared Folders ab. Nutzt man SMB um ein Verzeichnis auf dem nativen Dateisystem der Vagrantbox dem Windows Host freizugeben anstatt umgekehrt, ist die Performance auf der Box natürlich top, aber z.B. Suche in Dateien auf dem Host sehr langsam. Und mir persönlich ist bei der Entwicklung mit Magento wichtig, schnell mal mehrere Tausend Dateien zu durchsuchen. Da jedes Mal minutenlang zu warten, kommt nicht in Frage.

Aber ich schrieb ja vorhin „zweitbeste“. Die mit Abstand beste Wahl ist, überhaupt kein geteiltes Dateisystem zu verwenden, weshalb auch Alternativen wie automatische Synchronisation mit Rsync in Entwicklung sind.

Diese hat noch Ecken und Kanten aber ist durchaus brauchbar. Die Idee ist, statt einer Form von geteiltem Dateisystem zu nutzen, Verzeichnisse synchronisiert werden, so dass auf beiden Systemen das jeweils native Dateisystem genutzt wird. Achtung, die Synchronisation erfolgt nur vom Host zur Vagrantbox, nicht umgekehrt. Änderungen auf der Box werden bei der nächsten Synchronisation wieder überschrieben. Es können allerdings Unterverzeichnisse und Dateien von der Synchronisation ausgenommen werden.

Rsync ist ein Unix Tool, das genau diesen Job effizient übernimmt. Die Rsync-Parameter werden im Vagrantfile konfiguriert, analog zu shared folders. Der Synchronisierungs-Prozess kann dann auf dem Host wie folgt getriggert werden:

Der Clou, und hier wird es wirklich nützlich: es gibt zusätzlich ein Kommando, das das Verzeichnis auf Änderungen überwacht und dann direkt synchronisiert. Die Latenz zwischen Speichern auf dem Host und Aktualisierung der Box beträgt damit nur wenige Sekunden:

Achtung: Der rsync-auto Prozess hängt sich gelegentlich auf, z.B. wenn der Host in den Ruhezustand wechselt. Dann muss er mit Strg-C abgebrochen werden (oder wenn er im Hintergrund läuft, der entsprechende Ruby-Prozess gekillt werden) und neu gestartet werden.

Ich hielt es anfangs für eine gute Idee, rsync-auto im Hintergrund laufen zu lassen und die Ausgaben in ein Logfile zu schreiben:

Aber weil auf diese Weise nicht direkt sichtbar ist, ob der Prozess noch läuft und wann die gerade aktuellen Änderungen synchronisiert sind, bin ich wieder dazu übergegangen, die Ausgaben direkt anzuzeigen. Im Hintergrund kann der Prozess trotzdem laufen, gut auch in der selben Konsole, die man für SSH nutzt. Mein aktuelles Startup-Skript dazu sieht so aus:

Provisioner: automatisierte Einrichtung

Vagrant wird häufig in einem Atemzug mit Puppet genannt, einem Tool zur Automatisierung von Infrastruktur, mit dem z.B. Entwicklungs-, Test- und Produktiv-Umgebungen synchron konfiguriert werden können. Puppet kommt mit einer eigenen deklarativen Sprache zur Definition des gewünschten Zustands der Systeme. Weitere Alternativen zu Puppet sind Chef und Ansible.

Wer sich aber nicht in noch ein weiteres Tool einarbeiten will und ohnehin nur die Entwicklungsumgebung in Vagrant konfigurieren will, für den gibt es eine schnelle Alternative: Shell Scripts als Provisioner. Im Vagrantfile sieht das z.B. wie folgt aus:

Das Script unter bin/vagrant-bootstrap.sh wird so beim Provisionieren ausgeführt (das heißt, beim ersten Start der Box und ab dann bei expliziten Aufrufen von vagrant provision)

oder auch so:

Mit dieser Zeile wird der Befehl zum Neustarten von Apache (service apache2 restart) bei jedem Start der Box ausgeführt.

In meinem vagrant-bootstrap.sh Skript installiere ich dann alle benötigten Pakete und konfiguriere das System. Jedes Mal wenn ich Anpassungen vornehme, stelle ich sicher dass die entsprechenden Befehle auch in das Skript aufgenommen werden. Ein vollständiges Beispiel als Basis-Setup für Magento-Installationen inklusive Provisioning-Skripten zeige ich im zweiten und dritten Teil der Artikelserie.

Im vierten Teil werden wir das Setup dann auf Puppet umstellen. Eins vorweg: Mit Hilfe von PuPHPet geht das komfortabler als erwartet!

Fabian Schmengler

Author: Fabian Schmengler

Fabian Schmengler ist Diplom-Informatiker und Magento Entwickler bei integer_net. Seine Schwerpunkte sind Backend-Entwicklung, Konzeptionierung und Test-Automatisierung. Seit 2011 ist er Magento Certified Developer, seit 2014 Magento Certified Solution Specialist.