Einfluss von Docker auf Entwicklungsprozesse

Philippe Hässig Feb 27, 2018
Einfluss von Docker auf Entwicklungsprozesse

Die Komplexität von (Web-)Applikationen ist in den letzten Jahren stark gewachsen. Während viele Applikationsumgebungen früher aus einem Webserver und einer Datenbank bestanden, werden heute oft viele weitere Dienste benötigt:

  • eine Javascript Runtime für das Kompilieren von Javascript und CSS
  • ein Key-/Value Store (z.B. Redis)
  • eine Bibliothek zur Verarbeitung von Bildern (z.B. ImageMagick)
  • eine Message Queue (z.B. RabbitMQ)
  • weitere selbst geschriebene (Micro-)Services

In vielen Fällen haben die Dienste selbst wieder Abhängigkeiten. Um effizient entwickeln zu können, müssen all diese Dienste auf dem Rechner des Software-Entwicklers laufen.

Schnell haben viele Entwicklungsteams den Bedarf nach einem automatisierten Setup der Entwicklungsumgebung erkannt und oft auch umgesetzt. Möglich machten dies Virtualisierungslösungen wie Vagrant. Damit ist es relativ einfach, eine standardisierte virtuelle Umgebung aufzubauen, in der alle Abhängigkeiten vorhanden sind und mit der man innert vernünftiger Zeit eine Entwicklungsumgebung starten kann.

Der Kampf mit den Abhängigkeiten

Ein Beispiel: Für das Management unserer auf KVM basierenden Virtualisierungsumgebung haben wir eine eigene Ruby on Rails Applikation geschrieben. Möchte ein Entwickler nun ein neues Feature einbauen oder einen Bug fixen, werden bis zu 15 weitere Dienste und Applikationen benötigt. Früher mussten diese Dienste alle lokal laufen. Das hat schon deshalb nicht funktioniert, weil MacOS kein KVM unterstützt. Wir erstellten deshalb mit Vagrant eine virtuelle Linux-Maschine, in der einige dieser Services liefen. Einmal aufgesetzt hat das auch recht gut funktioniert und die Umgebung konnte automatisiert wiederhergestellt werden.

Soweit die Theorie. Da sich irgendwelche Abhängigkeiten mittlerweile geändert haben, hat das Aufsetzen dieser Umgebung in der Praxis selten beim ersten Mal funktioniert. Unter oft stundenlangem Debuggen musste die Umgebung wieder zum Laufen gebracht werden. Dazu kam, dass noch immer ein grosser Teil der Applikation auf dem Rechner des Entwicklers lief und auch dort haben sich von Version zu Version des Betriebssystems Änderungen eingeschlichen, die ein sofortiges Funktionieren der Applikation verunmöglichten.

Auftritt Docker!

Vor etwa 18 Monaten haben wir angefangen, die ersten Applikationen in Docker Container zu stecken und in unserem täglichen Workflow zu benutzen. Unser Entwickler-Leben hat sich damit drastisch vereinfacht. Alle Abhängigkeiten einer Applikation sind nun in ihrem "Dockerfile" beschrieben. Alle benötigten Dienste (Datenbank, Redis, andere Microservices) sind in einer "docker-compose.yml" Datei definiert und konfiguriert. Es reicht nun ein einziger Befehl ("docker-compose up"), um die gesamte Umgebung zu starten und sofort mit dem Entwickeln zu beginnen. Ausser Docker selbst müssen keinerlei weitere Abhängigkeiten auf dem Rechner des Entwicklers installiert werden.

Die gleichen Konfigurationen können genauso auf unserem CI Server verwendet werden. Auch dort sind, ausser Docker, keine weiteren Dienste zu installieren. "It just works."

Der Weg zum produktiven Einsatz

Die Erfahrungen, die wir beim Aufsetzen und Pflegen dieser Struktur gewonnen haben, helfen uns nun beim verschieben unserer Applikationen vom klassischen Linux Server auf unsere Container Plattform. Die meisten Vorarbeiten sind bereits gemacht, damit eine Applikation einwandfrei in einem Docker Container betrieben werden kann. Durch das Vereinfachen unseres Entwicklungsprozesses haben wir gleichzeitig eine solide Grundlage für die Verbesserung unserer Deployment- und Betriebs-Prozesse geschaffen. Diese Prozesse werden wir nun weiter verfeinern.

Seit kurzem nutzen wir Gitlab mit seinen Pipelines. Diese erlauben es uns, den Prozess vom Sourcecode-Checkin bis zum Deployment komplett zu automatisieren. Gitlab führt unsere Unit- und Integrationstests aus, baut das Docker-Image und stellt dieses in der Registry zur Verfügung. Auf einen Klick wird das fertige Image dann in der produktiven Umgebung deployed.

Dynamische Testumgebungen

Eine weitere tolle Möglichkeit, die uns der Einsatz von Containern bietet, sind dynamische Staging-Umgebungen. Im Rahmen eines Prototyps haben wir eine Applikation erstellt, die auf Github (oder Gitlab) Webhooks hört und dann für den spezifischen Branch eine komplette Umgebung hochzieht. Konkret wird ein zuvor spezifiziertes OpenShift Template angewendet. Die URL zur neuen Umgebung wird dann direkt als Kommentar zum Pull-Request gepostet. Nach dem Merge wird die komplette Umgebung wieder entfernt. Die Prototyp Applikation "Actuator" ist Open Source und ist hier dokumentiert.

Fazit

Container krempeln bekannte Prozesse von der Entwicklung bis zum Betrieb komplett um. Nicht unterschätzen sollte man, dass einiges an neuem Know-how erforderlich ist. Das Investment hat sich für uns aber definitiv gelohnt. Vieles ist damit einfacher geworden und einiges an mühsamer Handarbeit ist weggefallen.



Würden Sie Ihre Applikation gerne mit Docker betreiben?

Beim TechTalkThursday im März 2018 sprach David über «Docker for Developers» und gab einen Überblick über den Einsatz und die Verwendung von Docker in der Container-Technologie. Die Video-Präsentation stellen wir Ihnen inklusive der Abschriften unter folgendem Link zur Verfügung. 

Jetzt Video-Präsentation anschauen