Willhöft IT-Beratung
  • Zur Startseite
  • Zum Blog-Archiv
Docker
16. Feb 2016

Dienste mit Docker-Containern betreiben

Betreiber von IT-Services haben meist zwei Ziele im Auge: Eine hohe Verfügbarkeit und ein geringes Risiko beim Einspielen von neuen Funktionen und Sicherheitsaktualisierungen. Infrastruktur als Code und Immutable Deployment sind Vorgehensmuster für Entwicklung und Betrieb, mit denen sich diese Ziele in unserer Erfahrung sehr gut erreichen lassen. Um diese Muster bei unseren firmeneigenen Diensten anzuwenden, haben wir uns für Docker entschieden und teilen in diesem Beitrag die Erkenntnisse aus der Umstellung von vollständig virtualisierten Servern auf schlanke Docker-Container.

Anforderungen an eine solche DevOps-Umgebung sind im Einzelnen:

  • Server-Konfigurationen sollen (wie jede Software) dokumentiert, getestet und im 4-Augen-Prinzip prüfbar sein.
  • Die Einrichtung soll weitestgehend automatisiert passieren.
  • Sowohl der aktuelle Stand als auch historische Stände sollen sich einfach und schnell automatisiert wieder herstellen lassen.
  • Dienste sollen unabhängig voneinander sein.
  • Es soll möglichst wenige Maschinen/VMs mit einer “langen Geschichte von menschlicher Zuwendung” geben (also nur wenige Schoßtiere auf der Achse “pets-VS-cattle”).

Sicher gibt es mit Puppet, Chef, Ansible, chroot, Bash-Script-Sammlungen, KVM, XEN, Linux containers (LXC), VMWare vSphere etc. pp. schon länger Technologien, die hiervon Teilaspekte abdecken. Aber erst das Gespann Git, Debian GNU/Linux und eben Docker machen das Entwickeln und Betreiben eines Dienstes so leichtgewichtig und komfortabel, wie wir es von “normaler” Software-Entwicklung gewöhnt sind.

Warum Docker?

Docker umgibt schon seit längerer Zeit ein Hype, den man in seinem Ausmaß nicht immer nachvollziehen konnte. Beispielsweise ätzte @hipsterhacker:

Best features of Docker:

  • Easy to get a project to the top of HackerNews
  • New Github stars for old ideas
  • Has lots of Twitter followers

Also, was ist dran am Hype? Aus unserer Sicht gibt es drei Schlüsseleigenschaften, die es vor Docker so nicht gab:

  • Die Macht von Linux wird besser verfügbar gemacht: Die Frage, ob Werkzeug X auch auf MacOS oder Windows läuft, ist schlicht obsolet! Wenn X für eine Linux Distribution Y paketiert ist, reicht folgende Zeile um X auf jedem System von Entwickler-Notebook bis Produktionsserver zu nutzen: docker run -it Y apt-get install X
  • An diesem Beispiel zeigt sich auch gleich der zweite Punkt: Docker bringt einen Satz sehr kompakter aber hilfreicher Kommandozeilen-Befehle mit
  • Und schließlich ist es mit Docker sehr einfach, Images bzw. deren nachvollziehbare Konfiguration, Ressourcen sparend zu archivieren und zu bewegen: Sowohl von einem Entwickler zum anderen als auch zwischen Entwicklungs- und Produktions-Stages, als auch zwischen Image-Entwicklern und -Nutzern.

Diese drei Merkmale, insbesondere das dritte, haben zu einem Ökosystem geführt, in dem es geprüfte, stets aktuelle Images für alle Lebenslagen gibt.

Mit Docker ist es also praktisch ohne weitere Infrastruktur-Tools möglich den von der Software-Entwicklung gewohnten Continuous-Delivery-Arbeitsfluss auf den Betrieb von Diensten auszudehnen. Alle Schritte von einem Linux Standard-Image bis zum fertig konfiguriertem Dienst können im Dockerfile bzw. in Hilfsskripten in einem für diesen Dienst speziellen Git-Repository verwaltet werden. Wie bei Git üblich nutzen wir dazu einen Entwicklungs-Branch (development) und einen Produktionsbranch (master). Vom Master-Branch lässt sich immer und überall eine produktive Instanz des Dienstes erzeugen und starten durch:

docker build --tag myService . && docker run -it myService

Statt Software wie Jira, oder Gitlab inkl. Abhängigkeiten wie Datenbank und Mailserver manuell zu installieren und zu konfigurieren, entwickelt man Dockerfiles und Hilfsskripte. Zum Teil scheint das komplizierter, bei genauerem Betrachten stellt sich aber heraus: Je komplizierter eine solche Einrichtung ist – desto mehr lohnt es sich solche Dienste mit Docker zu automatisieren, denn die Komplexität ist jetzt besser dokumentiert, langfristig pflegbar und in Betrieb zu nehmen.

Lebenszyklus eines Dienstes:

Zunächst sehen die Phasen eines Dienstes bei Verwendung von Docker wie folgt aus:

Docker Zustände

Aus dem versionkontrollierten Quellcode entsteht mit docker build ein Image, vergleichbar mit einem Festplatten-Abbild einer virtuellen Maschine. docker images listet lokal bekannt Images auf. docker create erzeugt einen Container, das entspricht einer Instanz der Virtuellen Maschine basierend auf einem bestimmten Image – docker ps zeigt lokale Container an. docker start startet einen einzelnen Container. create und start lassen sich durch docker run zusammenfassen; nutzt man ein Image des Docker Hubs entfällt sogar der build-Schritt.

Sobald der Hauptprozess eines Containers beendet ist, beendet sich der Container – er existiert jedoch weiterhin einschließlich der Daten, die seit dem Start im virtuellen Dateisystem des Container geändert wurden. Container sind aber konzeptionell flüchtig, d.h. es ist zwar möglich einen gestoppten Container mit docker ps --all anzuzeigen oder erneut zu starten, üblicher ist aber eine der beiden folgenden Aktionen:

  • docker rm löscht einen Container einschließlich der angefallen Daten
  • docker commit erzeugt ein permanentes Image, von dem aus weitere Container abgeleitet werden können.

Aus Entwicklersicht wirkt dieser Ablauf nachvollziehbar und umfassend. Aus der Betriebssicht fällt sofort auf, dass im produktiven Betrieb das Persistieren von Daten unbedingt nötig aber hier so noch nicht berücksichtigt ist.

Umgang mit Daten

Um persistente Daten mit flüchtigen, unveränderbaren Containern zu vereinen, nutzt man bei Docker in der Regel sogenannte Data-Only-Container. Das sind Container, die mit dem Parameter --volume <MyPath> erzeugt wurden – sie müssen nie gestartet oder geändert werden. Daher spielt auch keine Rolle auf welchem Image ein Data-Container basiert. Der eigentlich Service-Container kann mit -volumes-from <MyDataContainer> angewiesen werden, den oben genannten MyPath zu mounten und somit Betriebsdaten in den Datencontainer zu schreiben.

Docker Data Container

Die Idee an diesem Vorgehen ist, dass so der Service-Container jederzeit verworfen und neu erzeugt werden kann, aber immer auf die aktuellen Daten zugreift. Diese frühe und deutlich Trennung von Dienst-Software und Dienst-Daten hat außerdem den Vorteil, dass Entwicklung und Betrieb sich von Anfang an darüber klar sind, wo die Daten liegen, und wie sie aus einem Docker-Dienst gesichert und wieder hergestellt werden: Typischerweise sind diese Sicherungen feingranularer und bessert testbar als z.B. VM-Snapshots.

Zusammenfassung

Mit Docker wird das Einrichten und Betreiben eines Dienstes zum versionskontrollierten Software-Entwicklungsprojekt. Schon das Migrieren einer herkömmlichen Webanwendung mit Datenbank zu einer Container-Gruppe inklusive Data-Only-Container bietet allerdings schon einige Fallstricke, auf die wir in unserem nächsten Post anhand eines konkreten Beispiels eingehen werden.

Impressum



Telefon:
Telefax:
E-Mail:

Vertreten durch

Registereintrag

Registergericht:
Registernummer:

Umsatzsteuer-ID
USt.-Identifikationsnummer 
gemäß §27a USt.-Gesetz:

Angaben zur Berufshaftpflichtversicherung
Name und Sitz der Gesellschaft:


Geltungsraum der Versicherung: