Portable und reproduzierbare Arbeitsumgebungen Vagrant

Was ist Vagrant?

Kurz gesagt ist Vagrant eine Anwendung zum Erstellen, Verwalten und Wiederherstellen von virtuellen Maschinen. Mit Vagrant sind keine Lizenzkosten oder Anschaffungskosten verbunden, da es sich um eine freie Open-Source Anwendung handelt. Vagrant wurde mit Ruby entwickelt und ist für Windows, MAC OS, Debian und CENTOS jeweils für die 32 und 64Bit Version verfügbar. Die einzelnen Downloads sind unter folgendem Link verfügbar: https://www.vagrantup.com/downloads.html

Welchen Vorteil bringt Vagrant?

Webinare

Mit Vagrant kann jeder innerhalb kürzester Zeit Konfigurationen für virtuelle Maschinen erstellen und auf unterschiedlichen Systemen wiederherstellen. Durch die einmalige Definition des Basissystems, der Abhängigkeiten und der Konfiguration in einem Vagrantfile benötigt der eigentliche Endnutzer nur noch einen Befehl, um seine Arbeitsumgebung in Betrieb zu nehmen. Alle benötigten Programme und Bibliotheken werden in der virtuellen Umgebung installiert. Das System des Endnutzers bleibt dadurch Großteils (siehe Voraussetzungen) unberührt. Außerdem werden lokale Projektverzeichnisse automatisch mit der virtuellen Umgebung synchronisiert.

Wer sollte Vagrant nutzen?

ScriptEin wenig platt ausgedrückt: Jeder, der eine portable, reproduzierbare Arbeitsumgebung benötigt. Und Nutzer, die ihr eigentliches System frei von Software für spezifische Projekte halten möchten.

Wenn man es etwas spezifischer ausdrücken möchte, sind es in erster Linie Softwareentwickler, Webdesigner und Administratoren. Administratoren oder Entwickler erstellen mit Hilfe von Vagrant eine reproduzierbare virtuelle Maschine für aktuelle Bedürfnisse. Diese virtuelle Maschine wird dann von Webdesignern oder anderen Entwicklern verwendet. Somit haben alle Entwickler eine identisch konfigurierte Arbeitsumgebung. Der Initialaufwand rentiert sich mit jedem Einsatz bei einem weiteren Entwickler oder in einem ähnlichen Projekt.

Ein gutes Beispiel für das Vagrant hervorragend geeignet ist, sind PHP Projekte. Ohne Vagrant müsste auf der Entwicklungsumgebung jedes beteiligten Entwicklers ein Datenbankserver, ein Webserver, PHP und eventuell ein Composer oder andere Paketmanager installiert werden. Man müsste bei jedem Entwickler sicher gehen, dass die gleichen Versionen der einzelnen Komponenten installiert werden und identische Einstellungen verwendet werden, damit der entwickelte Code bei allen Beteiligten funktioniert.

Mit Vagrant wird diese Arbeitsumgebung einmal beschrieben und dann verteilt. Alle arbeiten unter den gleichen Bedingungen.

Voraussetzungen

Vagrant selbst setzt eigentlich nur einen Provider für die virtuelle Maschine voraus. Als Provider kommen unter anderem „VirtualBox“, „VMWare Workstation“ und „Parallels Desktop“ in Frage. Die Installation des Providers sollte vor der Installation von Vagrant abgeschlossen sein.

Links zu den Downloadseiten der Provider:

Weitere unterstützte Provider werden auf der Vagrant Website unter Provider (https://www.vagrantup.com/docs/providers/) vorgestellt.

Prinzipiell reicht das. Wer aber per SSH auf seine virtuelle Maschine zugreifen möchte, benötigt zusätzlich einen SSH Client wie zum Beispiel Putty oder WinSCP.

Definition einer Vagrant Maschine

Eine Vagrant Maschine wird in einem Vagrantfile definiert. Das Vagrantfile kann über den Befehl vagrant init erzeugt werden. Es enthält anschließend auskommentierte Beispielkonfigurationen. Mit dem Befehl vagrant box add NameDerBox wird der Konfiguration eine „Box“ (ein Basisimage) zugeordnet. Wenn das Vagrantfile direkt mit einer „Box“ versehen werden soll, kann der vagrant init-Befehl um den Namen der Box erweitert werden.

Eine Liste der von der Community zur Verfügung gestellten „Boxen“ kann unter der Adresse https://atlas.hashicorp.com/boxes/search durchsucht werden. Alternativ können auch selbst konfigurierte Images als „Boxen“ gewählt werden. Dies ist aber in der Regel nicht notwendig, da die verfügbaren Images kaum Wünsche offen lassen.

In einem kleinen Beispiel wird im Folgenden die Definition einer Vagrant Maschine für ein PHP Projekt beschrieben. Es wird dabei von einem Windows 8 System mit VirtualBox als Provider und Vagrant ausgegangen.

Schritt 1: Erstellen des Vagrantfiles

Für dieses Beispiel wird das Vagrantfile mit einer 64bit Ubuntu-Box initialisiert.

vagrant init ubuntu/trusty64

Die entstandene Datei enthält, wie zuvor beschrieben, bereits grundlegende Befehle, die einzeln einkommentiert und angepasst werden können. Die einzige Zeile, die nicht auskommentiert ist, bestimmt die zuvor festgelegte Box.

config.vm.box = "ubuntu/trusty64"

Schritt 2: Definition der Verzeichnissynchronisierung

Wenn im Vagrantfile keine Definition zur Verzeichnissynchronisierung angegeben ist, wird automatisch das Verzeichnis, in dem sich das Vagrantfile befindet, mit dem Verzeichnis „/var/Vagrant“ auf der virtuellen Maschine synchronisiert.

Um diese automatische Synchronisierung zu deaktivieren, kann folgender Befehl verwendet werden:

config.vm.synced_folder ".", "/vagrant", disabled: true

Da eine virtuelle Maschine für ein PHP-Projekt verwendet werden soll, wird stattdessen das Verzeichnis „/var/www/projektname“ als Zielverzeichnis verwendet:

config.vm.synced_folder ".", "/var/www/projektname"

Schritt 3: Installation von benötigten Paketen

Am Ende des Vagrantfiles befindet sich bereits ein Abschnitt („provision“), in dem auf der Vagrant Maschine Shell-Befehle ausgeführt werden. Auskommentiert befinden sich hier schon die Befehle zum Abrufen des aktuellen Katalogs und dem Installieren des Webservers. Beides wird für dieses Beispiel benötigt und daher einkommentiert. Zusätzlich werden weitere benötigte Komponenten hinzugefügt.

config.vm.provision "shell", inline: <<-SHELL
 apt-get update
 apt-get -y install vim curl build-essential #Basispakete
 apt-get -y install mysql-server-5.5 phpmyadmin #MySQL spezifische Pakete
 apt-get -y install php5 apache2 libapache2-mod-php5 php5-curl php5-gd php5-mcrypt php5-mysql php-apc #PHP spezifische Pakete
 curl --silent https://getcomposer.org/installer | php #Paketmanager Composer
SHELL

Schritt 4: Erweiterte Konfiguration

Zusätzlich zu den Paketen werden Konfigurationen für MySQL-Server und dem Apache Server benötigt. Diese werden mit den gängigen Unix Befehlen im Provision-Bereich des Vagrantfiles vorgenommen.

Der folgende Quellcode enthält alle Änderungen am „Provision“-Bereich:

config.vm.provision "shell", inline: <<-SHELL
 APPENV=local
 DBHOST=localhost
 DBNAME=dbname
 DBUSER=dbuser
 DBPASSWD=test123

 echo -e "n--- MySQL specific settings ---n"
 echo "mysql-server mysql-server/root_password password $DBPASSWD" | debconf-set-selections
 echo "phpmyadmin phpmyadmin/dbconfig-install boolean true" | debconf-set-selections
 echo "phpmyadmin phpmyadmin/app-password-confirm password $DBPASSWD" | debconf-set-selections
 echo "phpmyadmin phpmyadmin/mysql/admin-pass password $DBPASSWD" | debconf-set-selections
 echo "phpmyadmin phpmyadmin/mysql/app-pass password $DBPASSWD" | debconf-set-selections
 echo "phpmyadmin phpmyadmin/reconfigure-webserver multiselect none" | debconf-set-selections

 echo -e "n--- Installing required Packages ---n"
 apt-get update >> install.log
 apt-get -y install vim curl build-essential >> install.log
 apt-get -y install mysql-server-5.5 phpmyadmin  >> install.log
 apt-get -y install php5 apache2 libapache2-mod-php5 php5-curl php5-gd php5-mcrypt php5-mysql php-apc >> install.log
 curl --silent https://getcomposer.org/installer | php  >> install.log
 echo -e "n--- Setting up our MySQL user and db ---n"
 mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME"
 mysql -uroot -p$DBPASSWD -e "grant all privileges on $DBNAME.* to '$DBUSER'@'localhost' identified by '$DBPASSWD'"
 echo -e "n--- Enabling mod-rewrite ---n"
 a2enmod rewrite
 echo -e "n--- Allowing Apache override to all ---n"
 sed -i "s/AllowOverride None/AllowOverride All/g" /etc/apache2/apache2.conf
 echo -e "n--- Settings for PHP errors ---n"
 sed -i "s/error_reporting = .*/error_reporting = E_ALL/" /etc/php5/apache2/php.ini
 sed -i "s/display_errors = .*/display_errors = On/" /etc/php5/apache2/php.ini
 echo -e "n--- Configure Apache to use phpmyadmin ---n"
 echo -e "nnListen 81n" >> /etc/apache2/ports.conf
 cat > /etc/apache2/conf-available/phpmyadmin.conf << EOF
 <VirtualHost *:81>
  ServerAdmin webmaster@localhost
  DocumentRoot /usr/share/phpmyadmin
  DirectoryIndex index.php
  ErrorLog ${APACHE_LOG_DIR}/phpmyadmin-error.log
  CustomLog ${APACHE_LOG_DIR}/phpmyadmin-access.log combined
 </VirtualHost>
EOF

 echo -e "n--- Add environment variables to Apache ---n"
 cat > /etc/apache2/sites-enabled/000-default.conf << EOF
 <VirtualHost *:80>
  DocumentRoot /var/www
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
  SetEnv APP_ENV $APPENV
  SetEnv DB_HOST $DBHOST
  SetEnv DB_NAME $DBNAME
  SetEnv DB_USER $DBUSER
  SetEnv DB_PASS $DBPASSWD
 </VirtualHost>
EOF

 echo -e "n--- Trigger Changes ---n"
 a2enconf phpmyadmin
 service apache2 restart

SHELL

 

Schrit 5: Starten und Testen des Vagrantfile

Um das erstellte Vagrantfile zu testen, wird bei inaktiver virtueller Maschine folgender Befehl benötigt:

vagrant up

Er sorgt dafür, dass die  Box initial heruntergeladen wird, alle benötigten Pakete heruntergeladen sowie die vorgegebenen Konfigurationen durchgeführt werden.

Sollte die virtuelle Maschine bereits aktiv sein, kann sie beendet und anschließend wieder neu gestartet werden:

vagrant halt
vagrant up

Die Alternative in einem Befehl sieht wie folgt aus:

vagrant reload

Der vagrant reload-Befehl sorgt nicht dafür, dass automatisch ein „provision“ (Installation von Paketen und Laden von Konfigurationen) durchgeführt wird. Dies erfordert bei aktiver virtueller Maschine folgenden Befehl:

vagrant provision

Alternativ kann das „provision“ beim „reload“ erzwungen werden:

vagrant reload –provision

Schritt 6: Optimierung

Nun gibt es im Vagrantfile im Provision-Bereich viele „Shell“-Schnipsel und weitere Unix-Befehle, durch die das Konfigurationsfile unübersichtlich wird. Dies kann durch Auslagern in einzelne Dateien und anschließendem Einbinden behoben werden:

config.vm.provision :shell, path: "bootstrap.sh"

Der angegebene Pfad des Scriptes bezieht sich auf das lokale System relativ zum Vagrantfile. Das Script wird beim Provisioning in die virtuelle Maschine übertragen und dann mit dem hinterlegten „vagrant“-User ausgeführt.

Zusätzlich kann beim Einbinden von Shell-Scripten angegeben werden, ob diese bei jedem Start der virtuellen Maschine ausgeführt werden sollen. Ist diese Einstellung nicht gesetzt, wird das Provisioning standardmäßig nur beim ersten Start, oder wenn es explizit angegeben wird, durchgeführt.

Der komplette Befehl, um ein ausgelagertes Script bei jedem Start auszuführen, lautet wie folgt:

config.vm.provision :shell, path: "bootstrap.sh", run: "always"

Fazit

Die Definition eines einfachen Vagrantfiles geht leicht von der Hand. Es werden nützliche Beispiele generiert und gut beschrieben. Zusätzlich gibt es auf der Vagrant-Webseite einen hervorragenden Guide und gute Dokumentationen zu den einzelnen Schaltern. Die Community versorgt sich gegenseitig mit den aktuellsten Boxen.

Leider gab es während meiner Versuche Probleme mit der Synchronisierung von Verzeichnissen auf Windows Systemen. Beim vagrant up erschien während des Anlegens des synchronisierten Verzeichnisses der Fehler „..: Not a Directory“. Das Problem lag nicht an der Kombination von Windows 8.1 und Vagrant – es war eher ein Bug in VirtualBox, der sich mit der Version 5 eingeschlichen hatte. Mit der Version 4 und ab der Version 5.0.16-10 funktioniert wieder alles wie es soll.

Abgesehen von dieser kleinen Hürde lässt sich das verschwindend kleine Vagrantfile hervorragend im Projekt integrieren und mit dem Projekt versionieren, wodurch alle Projektbeteiligten immer auf dem gleichen Stand entwickeln. Zumindest in größeren PHP-Projekten ist an Vagrant kein Vorbeikommen.

Quellen

https://www.vagrantup.com/

https://www.vagrantup.com/docs/provisioning/shell.html

https://gist.github.com/rrosiek/8190550

https://atlas.hashicorp.com/boxes/search

https://github.com/mitchellh/vagrant/issues/5933

http://www.tutorialspoint.com/unix/unix-useful-commands.htm

Sie möchten noch mehr über die aktuellsten IT-Technologien erfahren? Dann schauen Sie doch in unserem Developer Blog vorbei.