PHP Entwicklungsumgebung mit Docker, Nginx und PHP-FPM


Es wurde schon einiges über Docker geschrieben. Ich denke, dass dessen Konzept der Isolation von Komponenten in eigene Container gerade für die Entwicklung von PHP Web-Anwendungen hervorragend geeignet ist. Da PHP selbst keinen Server mitbringt (der für Produktionsumgebung geeignet ist), ist mindestens eine zusätzliche Komponente, nämlich der Webserver, zwingend notwendig. In 98% der Fälle kommt dann noch ein Datenbank-Server hinzu. Die "Mindestanforderungen" an die Entwicklungsumgebung, um erst einmal starten zu können, sind also relativ hoch. Es gibt also Verwendung für die verschiedenen Container, aus denen eine Docker-Anwendung sich zusammensetzt.

Dieser Artikel ist kein Tutorial, sondern soll nur die Eignung von Docker als Entwicklungsumgebung für PHP-Entwickler diskutieren. Er ist so geschrieben, dass keine spezifischen Vorkenntnisse zu Docker notwendig sind, um diese Diskussion nachverfolgen zu können. Der Artikel soll natürlich dazu anregen, Docker selbst auszuprobieren, allerdings ist dafür die Materie doch zu komplex, um in einem kurzen Artikel behandelt zu werden. Es gibt im Netz ausreichend Lesestoff dazu.

Die Basisinformationen

Falls du noch nicht mit Docker vertraut bist, versuche ich hier ganz kurz das Konzept vorzustellen:

Die Aufgabe, die Docker übernimmt, ist die Verwaltung von Containern. Dies sind virtuelle Linux-Systeme, von denen mehrere (im Unterschied zu üblichen virtuellen Maschinen sehr viele) auf einem Host-System laufen können. Jeder Container kann individuell konfiguriert werden. In der Praxis hat ein Container meist nur eine Aufgabe, z.B. einen DB-Server bereitzustellen.

Für eine "komplexe" Webanwendung werden also verschiedene Container definiert, und dann miteinander verbunden.

Ansätze für Entwicklungsumgebungen

Wie schon zu Beginn kurz angerissen, sind für eine übliche Webanwendung schon einige Komponenten erforderlich. Mir sind zur Zeit 3 Ansätze bekannt, mit denen Entwickler arbeiten, um diese Komponenten bereitzustellen:

  • Installiere alles auf dem Entwicklungs-Rechner
  • Definiere eine passende VM für jedes Projekt
  • Definiere eine passende Container-Landschaft für jedes Projekt

Ok, vom Prinzip und vom Satzanfang her sind die letzten beiden Ansätze ähnlich. Ich denke, sie sind auch ähnlich gut geeignet, wobei die erste Variante einige Nachteile hat:

  • Der Rechner wird voll-gestopft mit Software, die Verwaltung von Abhängigkeiten wird damit u.U. komplex.
  • Oft ist es nicht oder schwer möglich, passende Software-Versionen zu installieren. Es wird dann z.B. mit PHP 7 entwickelt, wobei das Projekt in Produktion eigentlich noch auf PHP5.6 läuft.

Vorteile des Container-Ansatzes

Aus den genannten Gründen ist die Verwendung von Virtuellen Maschinen für die Entwicklung schon seit einigen Jahren gebräuchlich, auch sehr stark im PHP Umfeld. Ich habe mich immer etwas dagegen gesträubt, da mein Rechner nicht der stärkste war. Ich habe mir die PHP Versionen selbst kompiliert, und hatte so auf dem Host einige verschiedene Versionen parallel zur Auswahl. Solange alle Projekte, an denen man arbeitet, in ungefähr gleiche Komponenten verwenden (z.B. ähnliche PHP Extensions), kommt man mit diesem Ansatz auch zurecht. Dennoch sind der Flexibilität deutliche Grenzen gesetzt. Z. B. hatten wir teilweise Projekte, bei denen ein Varnish Proxy-Server eingesetzt wurde. Auf dem Test-System gab's das nicht, und auch lokal hatte ich mir nicht die Mühe gemacht, so ein Setup einzurichten (es wäre natürlich möglich gewesen).

Mit obigem langen Fließtext wollte ich sagen:

  • Docker-Container sind weniger Ressourcen-Intensiv als VM's
  • Docker-Container sind flexibler als individuell angepasste
  • Entwicklungsrechner (solange man an mehreren Projekten arbeitet).

Ein weiterer Vorteil ist m.E., dass man mit der Konfiguration von Docker-Images (den "Bauplänen" für Container) den Produktions-Server "beschreiben" kann. Mit einigen Textfiles kann man hier schon relativ genau die Gegebenheiten eines beliebigen Linux-Servers nachbilden. Diese Textfiles kann man dann auch versionieren. Wenn man nun auf dem Produktionsserver die PHP-Version aktualisiert, oder von MySQL auf MariaDB wechselt, kann man das im Docker-Setup ebenfalls tun. Das ist dann richtig cool, wenn man auch die Continuous Integration Testumgebung mittels dieser Dateien aufbaut (was wir bisher noch nicht tun...). Weiterer Vorteil ist also:

  • Die Definition der Produktionsumgebung ist definierbar,
  • versionierbar, flexibel erweiterbar, und kann von mehreren Team-Mitgliedern sowie den Testsystemen geteilt werden.

Projekt-Kickstart

Die meisten Projekte starten mit ähnlichen Anforderungen. Da das System oft noch nicht "live" ist, ist außerdem nicht bekannt, wie das Produktiv-System genau aussieht. Oft reicht hier also eine Art "Standard-Umgebung", die allerdings dann relativ einfach anpassbar und erweiterbar sein soll. Eine Suche bei Google oder Github nach "LAMPP Docker", oder "Nginx PHP Docker environment" listet einige brauchbare Optionen, mit denen du direkt starten kannst. Der heute oft verwendete (und auch beste) Ansatz ist es, pro Service einen Container zu definieren, und diese mit Hilfe des Tools docker-compose zu verbinden und zu verwalten. Für eine normale PHP Web-Anwendung benötigen wir mindestens

  • Apache mit PHP und mod_php eine Datenbank

Ich bevorzuge, den Webserver und PHP zu trennen, wobei wir dann folgende Services hätten:

  • einen Webserver PHP-FPM eine DB

Der Webserver und der PHP Container müssen vermutlich auf die gleichen Daten zugreifen. Man kann hier entweder ein Verzeichnis auf dem Host in beide Container einbinden, oder einen Data-Only Container einführen. Dieser wäre dann nur für die Daten zuständig. Die anderen Container binden dann die vom Daten-Container definierten Volumes ein.

  • Data Container (definiert die Projektdateien als Volume) Webserver
  • (bindet die Volumes des Data Containers ein) PHP-FPM (bindet die
  • Volumes des Data Containers ein) DB-Container

Eine detaillierteres Tutorial für das minimale Setup gibt es hier in Englisch zu lesen.

Ich habe mir selbst eine Startumgebung zusammengestellt, und auf Github zur Verfügung gestellt. Sehr gerne kannst du auch diese als Basisvorlage für dein Projekt verwenden. Sie verwendet das Konzept von einem Data-Only Container, nutzt Nginx und php7 (das lässt sich aber leicht ändern). Als zusätzliche Komponente habe ich noch einen SMTP Mailcatcher eingebunden, der das Arbeiten mit E-Mails erleichtert.

Meine Erfahrungen mit Docker (diesmal ehrlich)

  • Es ist komplex. Komplexer als sich XAMPP zu installieren. Ohne Linux-Kenntnisse, und ohne zu wissen, wie man den Webserver konfiguriert, sollte man keine großen Sprünge erwarten
  • Aus sicherheitstechnischer Sicht ist das ganze Konzept nochmal komplexer. Ich nutze Docker zur Zeit nur für die Entwicklung. Für einen Einsatz auf Produktivsystemen sollte man m.E. die Dienstleistung eines Experten in Anspruch nehmen (mit oder ohne Docker) oder eine Service-Plattform wählen, die ein Deployment von Docker-Containern offiziell anbietet und dort auch Support leistet. Bei meinem Fedora Entwicklungssystem hatte ich auch hin und wieder Konflikte zwischen Docker und SELinux.
  • Die Performance auf Linux Systemen ist tatsächlich top. Auf Windowssystemen muss man (bis anhin zumindest) eine minimale VM für das Docker-Hostsystem starten. Damit ist das Performance Argument vermutlich hinfällig, wenn man auf Windows entwickeln möchte (Das ist nur Vermutung..).
  • Mir hat es geholfen, ein besseres Verständnis für die Web-Anwendung als Gesamtsystem zu entwickeln. Ich denke es ist von Vorteil, wenn man als Entwickler dieses Gesamtsystem und damit die Abhängigkeiten des eigenen Codes besser versteht.

Fazit: Empfehlenswert?

Ich würde eine Projektspezifische Virtualisierung jedem Team empfehlen, und auch jedem "Solo-Entwickler", der an mehr als einem oder zwei Projekten arbeitet. Ob eine "klassische" virtuelle Maschine, oder Docker zum Einsatz kommen soll, muss abgewägt werden. Ich denke beide Ansätze können die jeweils besser geeigneten sein.

Author: Claudio Kressibucher
Tags: PHP, Webentwicklung, Docker, Nginx