Liferay 7 Entwicklungsumgebung mit Docker

Im letzten Blogartikel zu Docker („Liferay Development Setup mit Docker„) haben wir einen kleinen Einblick unsere ersten Erfahrungen mit Docker zur Einrichtung von Liferay Entwicklungsumgebungen gegeben. In diesem Follow-Up möchten wir noch mal unser aktuelles Setup vorstellen und auf einige Vor- und Nachteile eingehen.

Um ein Liferayportal für ein mittelgroßes Projekt hier bei empulse vollständig einzurichten müssen in der Regel eine ganze Reihe von Einstellungen vorgenommen werden. Dazu zählen z.B.:
* Installation und Konfiguration des Tomcat Servers
* Anbindung von PostgreSQL & ElasticSearch
* Konfiguration des Liferayportals selbst

Hinzu kommen meist noch individuelle Ressourcen für jedes Projekt, bspw. vom Kunden bereitgestellte Daten oder Bilder, die statisch ausgeliefert werden sollen. Das alles lässt sich gut in ein Dockerimage verpacken und wird so automatisch allen Entwicklern des Projekts bereitgestellt.

Zur Zeit entwicklen wir Liferayprojekte mit 3 getrennten Docker Containern, das sind:
* Liferayportal
* Datenbank
* ElasticSearch

Mit Hilfe von docker-compose kann jeder Entwickler seine lokalen Container verwalten. Dazu gibt es eine projektspezifische docker-compose.yml Datei, hier ein gekürzter Auszug:

docker-compose.ymlExpand source

Hier wird definiert, dass ein Liferayportal Service benötigt wird, der wiederum abhängig von einem Postgres und ElasticSearch Container ist. Dazu kommen verschiedene Konfiguration von z.B. freigegebenen Ports für Netzwerkzugriffe, Umgebungsvariablen, Volumes, die im Hostsystem verfügbar sein sollen und eventuellen Zuteilungen von CPU und Speicher Ressourcen. Jeder Entwickler kann natürlich individuelle docker-compose Konfigurationen lokal anlegen, um die Umgebung, auf seine Arbeitsweise anzupassen. Das wird meistens dazu genutzt um die Auslastung des Entwicklungsrechners zu regulieren oder weitere Pfade aus dem Container über Volumes in das Hostsystem zu mappen. Volumes nutzen wir außerdem dazu, die Ordner für Deployments, Datenbank und Index, sowie Logdateien lokal bereitzustellen. So sind alle wichtigen Daten containerübergreifend gesichert.

Das Dockerfile für den Liferaycontainer (basierend auf einem Basis Ubuntu + JDK-8 Image) ist natürlich das Umfangreichste, denn hier wird das gesamte Portal installiert und konfiguriert. Auch hier ein kurzer Auszug:

Liferayportal DockerfileExpand source

In früheren Versionen unseres Setups wurde das Liferayportal beim Bauen des Images direkt von der Website heruntergeladen und entpackt. Das hat immer eine gewisse Zeit gedauert, weshalb wir dazu übergegangen sind dem Docker Buildcontext alle abhängigen Tools lokal bereitzustellen. Zusätzlich zum Liferayportal selbst installieren wir so z.B. auch jRebel und ElasticSearch. Da sich der Umfang der Tools meist in Grenzen hält, checken wir sie alle einfach mit in das Git-Repository des Projekts ein.

Neben der Installation des Liferayportals, konfigurieren wir dieses auch, soweit möglich, direkt im Docker Image. Die Propertydateien für bspw. portal-ext.properties und portlet-ext.properties liegen ebenfalls mit im Git-Repository und können von jedem Entwickler angepasst werden. Da Liferay für viele integrierte Komponenten die Konfiguration über das Adminpanel ermöglicht, und diese dort als Dateien exportiert werden können, lassen sich auch Änderungen für Liferaymodule schnell exportieren und einfach in den entsprechenden Ordner des Dockersetups kopieren. Beim nächsten Build werden diese dann automatisch mit in den Zielordner kopiert und angewendet. Typische Dinge, die wir so konfigurieren sind die Freemarker und Velocity Engines, Anbindung und Mappings für ElasticSearch, Definition von REST Endpunkten und unsere selbst geschriebenen Module.

Der Container für die Datenbank basiert i.d.R. auf dem offiziellen PostgreSQL Image und ist nicht angepasst. Für den ElasticSearch Container haben wir ein eigenes Image geschrieben, da Liferay hier auf die recht veraltete Version 2.2.0 angewiesen ist. Basis hierfür ist ebenfalls unser Ubuntu + JDK Image.

Im Verlauf eines aktuellen Projekts zeigt sich zunehmend, dass dieses Setup einige Ressourcen in Anspruch nimmt. Das Liferayportal mit allen individuellen Modulen deployed und gestartet, dazu Datenbank und ElasticSearch Container benötigen (völlig ungebremst) bis zu 12GB Arbeitsspeicher und einen nicht unerheblichen Teil der CPU Zeit. Dem kommen wir bereits auf Container Ebene entgegen, indem wir Grenzen für Speicher- und CPU-Zeit definieren. Hierbei darf man allerdings nicht vergessen, dass die Speicherkonfigurationen für alle beteiligten Java-VMs auch angepasst werden müssen. Das betrifft vor allem die richtigen Heap-Größen, plus Metaspace und OffHeap.

Fazit

Mit Docker können Entwicklungsumgebungen für Liferayprojekte schnell und reproduzierbar aufgesetzt werden. Die Konfigurationsdateien für Liferay, Datenbank und ElasticSearch können direkt im Build der einzelnen Images bereitgestellt werden, so dass ohne weitere Schritte ein fertiges Liferayportal mit allen Abhängigkeiten bereit steht. Änderungen, die im Verlauf eines Projekts in der Umgebung entstehen, werden so allen Entwicklern zugänglich gemacht und können häufig ohne weitere Eingriffe automatisch eingespielt werden. Individuelle Konfigurationen können Entwickler über eigene docker-compose Dateien anlegen, was vorallem wichtig ist, um CPU und Arbeitsspeicher auf die eigene Arbeitsweise anzupassen.