Image-Pfege

Docker-Images versionieren und verwalten
Kommentare

Die Container-Virtualisierungstechnologie Docker verleitet dazu, rasch eine Vielzahl von Images zu erstellen und daraus wiederum noch mehr Container zu starten. Dabei geht der Überblick jedoch sehr schnell verloren, wenn nicht einige Vorüberlegungen angestellt und Vorgehensweisen berücksichtigt werden.

Dabei geht der Überblick jedoch sehr schnell verloren, wenn nicht einige Vorüberlegungen angestellt und Vorgehensweisen berücksichtigt werden.

Mit Hilfe von Docker können Images einfach und schnell erzeugt werden. Sogenannte Dockerfiles dienen dabei als “Baupläne” und ermöglichen es, für jeden Anwendungsfall leicht das passende Image zu erzeugen. Über ein zentrales Depot – die Docker-Registry – kann es geteilt und dadurch von anderen Benutzern wiederverwendet werden. Auch die Nutzung als Basis für neue Images ist dabei möglich. Ein Oracle JDK Image könnte zum Beispiel auf diese Weise die Basis für ein Apache Tomcat Image bilden. Oder ein Unternehmen nutzt ein auf die Bedürfnisse optimiertes Docker-Image als Basis für sämtliche eigenen Images (siehe Abbildung 1).

DevOps Conference 2015

DevOpsConDie neue Konferenz für Docker, Infrastructure as Code, Continuous Delivery, Cloud und Lean Business startet am 1. bis 3. Juni in Berlin. Erleben Sie spannende Erfahrungsberichte und eine Fülle an wertvollem  Praxiswissen von den bekanntesten deutschsprachigen und internationalen DevOps-Experten. Holen Sie sich jetzt den entscheidenden Wissensvorsprung für die IT Ihres Unternehmens! Alle Infos auf www.devopsconference.de.

Wie man sich leicht vorstellen kann, kommt dadurch schnell eine Vielzahl von Images zusammen. Werden bestehende Images dann auch noch aktualisiert, ist ein Image-Chaos praktisch vorprogrammiert. Dieser Artikel beschreibt die Probleme, die bei der Versionierung und Aktualisierung von Images auftreten können. Ferner werden Lösungsansätze anhand von Beispielen aufgezeigt.

Abb. 1: Beispiel für aufeinander aufbauende Images

Abb. 1: Beispiel für aufeinander aufbauende Images

 

Docker-Tags sinnvoll nutzen

Um bei der Versionierung von Images Transparenz zu schaffen, bietet Docker einen Tagmechanismus, der eine einfache Art und Weise der Kennzeichnung von Images ermöglicht. Doch inwieweit kann dieser Tagmechanismus wirklich genutzt werden, um auch minimale Änderungen eines Docker-Images nachvollziehbar zu machen? Am Beispiel von zwei Images kann dies sehr leicht verdeutlicht werden: 1. Oracle-JDK-Image, 2. Ubuntu-Image. Das JDK-Image stellt keine große Herausforderung dar. Das gewünschte JDK wird in dem Image installiert, und als Tag wird das JDK-Release angegeben. Somit würden dann z. B. die folgenden JDK-Images zur Verfügung stehen:

• oracle-jdk:1.7_60
• oracle-jdk:1.7_67
• oracle-jdk:1.8_20

Hier kann man sehr schön sehen, dass pro Aktualisierung eines JDK-Releases ein neues Image erstellt wird. Wie würde die Aktualisierung bei einem Ubuntu-Image aussehen? Selbstverständlich könnte auch hier das Release des Ubuntu-Images als Tag genutzt werden. Somit ergäbe sich das folgende Szenario:

• ubuntu:13.04
• ubuntu:13.10
• ubuntu:14.04

Der wesentliche Unterschied zum JDK-Image besteht darin, dass das Ubuntu-Image zwischen den Releases weitere Aktualisierungen wie z. B. Security-Patches erhält, die den Nutzern zur Verfügung gestellt werden sollen. Hierbei wird jedoch das Releasetag nicht geändert. Ein Ansatz wäre, das Image zu aktualisieren und wieder mit demselben Tag zu versehen. Doch dadurch geht die Transparenz verloren, weil nicht mehr erkennbar ist, ob ein Image aktualisiert wurde bzw. zu welchem Zeitpunkt die Aktualisierung durchgeführt worden ist. Es muss also ersichtlich sein, um welches Ubuntu-Release es sich handelt und wann die letzte Aktualisierung stattgefunden hat. Dafür bietet sich die folgende Variante an:

• ubuntu-13.04:201401012322
• ubuntu-13.04:201401201244
• ubuntu-13.04:201403250733

Die Releaseinformation wurde hierbei in den Image-Namen verschoben. Das bedeutet, dass für jedes neue Release ein neues Image erstellt wird. Als Tag werden Zeitstempel verwendet, die angeben, wann die letzte Aktualisierung stattgefunden hat. Das latest-Tag sollte in beiden Varianten (JDK, Ubuntu) immer auf das aktuellste Image verweisen.

Docker-Images aktualisieren

Nachdem wir nun eine sinnvolle Methode zur Versionierung gefunden haben, stellt sich die Frage, was bei der Aktualisierung von Images zu beachten ist? Insbesondere bei der Verwendung von Images, die aufeinander aufbauen. Abbildung 2 verdeutlicht diese Problematik.

Abb. 2: Problematik bei der Aktualisierung abgeleiteter Images

Abb. 2: Problematik bei der Aktualisierung abgeleiteter Images

 

Abb. 2.b: Problematik bei der Aktualisierung abgeleiteter Images

Abb. 2.b: Problematik bei der Aktualisierung abgeleiteter Images

 

Im Folgenden werden wir Lösungen für dieses Problem anhand zweier Beispiele genauer erklären:
1. Ein kleines Projekt, das keine Docker-Registry verwendet und alle Images nur im eigenen Projekt benutzt werden.
2. Eine Organisation, die eine private Docker-Registry betreibt und die darin gespeicherten Images von mehreren Projekten genutzt werden.

 

Aufmacherbild: „Containers in the port of Laem Chabang in Thailand“-Foto von Shutterstock / Urheberrecht: nattanan726

[ header = Seite 2: Docker-Images aktualisieren…in kleinen Projekten ]

…in kleinen Projekten

Der folgende Ansatz wird beispielsweise bei der Entwicklung von CenterDevice, einer Cloud-basierten Lösung für kollaborative Dokumentenverwaltung, verfolgt. Docker wird dort genutzt, um die Produktionsumgebung bestmöglich auf den Entwicklungsrechnern abzubilden. Dabei wird für jeden einzelnen Backend-Service, wie z. B. MongoDB, RabbitMQ oder Tomcat ein eigenes Image erstellt.

Abb. 3: Docker-Image-Struktur bei CenterDevice

Abb. 3: Docker-Image-Struktur bei CenterDevice

 

Alle genutzten Services bzw. Tools werden regelmäßig auf den aktuellen Stand gebracht. Das bedeutet, dass z. B das JDK- oder Apache-Tomcat-Image sehr aktualisiert werden muss. Da es sich um aufeinander aufbauende Images handelt, müssen bei deren Aktualisierung einige Dinge beachtet werden. Zunächst ist es notwendig, alle Images zu finden, die von dem zu aktualisierenden Image abhängen. Denn diese müssen ebenfalls aktualisiert werden. Die alten, nicht mehr benötigten Images werden anschließend gelöscht, sodass immer nur ein aktueller Stand auf den Entwicklungsrechnern existiert. Um die Images löschen zu können, müssen auch alle Container, die diese Images nutzen, gestoppt und gelöscht werden. Damit jeder Entwickler diese Schritte auf seinem Entwicklungsrechner durchführen kann, wurde eine Python-Anwendung entwickelt, die diesen Prozess automatisiert durchführt.

Dabei wird zunächst eine zentrale Konfigurationsdatei (YAML) eingelesen, in der alle Services definiert wurden. Anschließend analysiert die Anwendung deren Dockerfiles, um die Abhängigkeiten der Images untereinander herauszufinden. Sobald die Abhängigkeiten bekannt sind, werden alle betroffenen Images und Container in der richtigen Reihenfolge gelöscht und anschließend wieder neu erstellt und gestartet. In GitHub ist ein Beispielprojekt verfügbar, das sofort lokal ausgeführt werden kann.

…in großen Projekten

Der zweite Ansatz gestaltet sich schon etwas aufwändiger und komplexer. Für große Organisationen, die Images projektübergreifend nutzen wollen, bietet sich eine private Docker-Registry an. Im Hinblick auf die Versionierung der Images sollte bei diesem Ansatz Folgendes beachtet werden.

Alle Images müssen mit einem eindeutigen Tag gekennzeichnet werden: Dadurch soll sichergestellt werden, dass eine projektübergreifende Nutzung der Docker-Registry keine unvorhersehbaren Auswirkungen auf bereits veröffentlichte Images hat. Insbesondere bei der Aktualisierung von Images.

Mit einem Tag gekennzeichnete Images sind nicht mehr änderbar: Leider existiert momentan keine Möglichkeit, einmal veröffentlichte Images vor Veränderungen zu schützen. Ein Lösungsansatz wäre, die Docker-Registry hinter einem eigenen Proxy zu betreiben und die entsprechenden API-Services zum Ändern und Löschen von Images zu blockieren.

Das latest-Tag sollte immer auf die aktuellste Version zeigen: Hiermit wird sichergestellt, dass das aktuellste Image eindeutig identifizierbar ist, ohne dass eine bestimmte Versionsnummer bekannt sein muss.

Durch die o. g. Punkte kann nun gewährleistet werden, dass einmal veröffentlichte Images eindeutig identifizierbar sind und sich niemals ändern werden. Aber wie kann sichergestellt werden, dass beim Hochladen von neuen Images – die Aktualisierungen enthalten – Nutzer zeitnah benachrichtigt werden, um ggf. auf die aktuellere Version wechseln zu können?

Search Backend für die Docker-Registry

Damit die Docker-Registry nicht permanent auf Änderungen überprüft werden muss, gibt es die Möglichkeit, ein eigenes Search Backend zu implementieren. Dadurch können zum einen alle Image-Metadaten in einem eigenen Backend, wie z. B. Elasticsearch, abgespeichert werden, und zum anderen können benutzerdefinierte Aktionen ausgeführt werden, sobald z. B. eine neue Version eines Images hochgeladen wird. Hierfür muss lediglich der Konfigurationsparameter search_backend für die Docker-Registry gesetzt werden. Er gibt die Python-Klasse an, die für die Speicherung der Metadaten verantwortlich ist. Bei bestimmten Events werden dann entsprechende Methoden dieser Klasse, die von docker_registry.lib.index abgeleitet werden muss, aufgerufen:

_handle_repository_created 
_handle_repository_updated
_handle_repository_deleted

Auf diese Weise können beliebige Aktionen, wie z. B. Benachrichtigungen via E-Mail, ausgeführt werden. Das folgende GitHub-Projekt dient als Beispiel wie ein solches Search Backend mit Elasticsearch implementiert werden kann.

Der Docker-Hub

Falls weitere Funktionen benötigt werden, die nicht Bestandteil der privaten Docker-Registry sind, lohnt sich ein Blick auf den Docker-Hub. Der Docker-Hub ist eine öffentliche Docker-Registry, die beispielsweise folgende zusätzlichen Funktionen anbietet:

• Benutzerauthentifizierung
• automatisierte Builds durch Webhooks bzw. Build-Trigger
• öffentliche und private Docker Repositories

Nach der Registrierung bei Docker-Hub kann ein privates Repository und beliebig viele öffentliche Repositories kostenlos angelegt werden. Die Nutzung weiterer privater Repositories ist dann kostenpflichtig.

Fazit

Auch Docker-Nutzer sollten sich mit dem Thema Versions- und Abhängigkeitsmanagement beschäftigen. Die einfache Erstellung und Veröffentlichung von Images birgt die Gefahr, ohne genaue Planung und Berücksichtigung der hier vorgestellten Punkte, schnell den Überblick zu verlieren. Insbesondere bei der Aktualisierung von Images können ansonsten sehr schnell Probleme auftreten.


Inside Docker: Wenn Sie mehr über Docker wissen möchten, empfehlen wir Ihnen das Entwickler Magazin Spezial Vol. 2: Docker zum leichten Einstieg in die Container-Virtualisierung.

docker-coverMit Docker feiern Linux-Container momentan ein eindrucksvolles Comeback. Während der Einsatz von virtuellen Maschinen viele Vor-, aber auch zahlreiche Nachteile mit sich bringt, ist Docker eine leichtgewichtige, containerbasierte Alternative, die die System-Level-Virtualisierung auf ein neues Level hebt. Dabei ergänzt Docker das Deployment von Betriebssystemen und Webanwendungen um die Lösungen, die man beim Original schmerzlich vermisst. In diesem Jahr hat Docker eine hohe Dynamik entwickelt und wird in allen aktuellen Linux-Distributionen wie Redhat, SUSE oder Ubuntu ausgeliefert. Firmen wie Spotify, Google, BBC, eBay und seit kurzem auch Zalando setzen Docker bereits produktiv ein. Das Entwickler Magazin Spezial „Docker“ informiert kompetent über diese revolutionäre Technologie, von der viele meinen, dass sie eine neue Ära in der IT einläuten wird. Wir erklären technische Hintergründe, demonstrieren Best Practices und zeigen, wie Docker effektiv eingesetzt werden kann. Das Sonderheft vereint umfangreiches Wissen über die wichtigsten Aspekte von Docker, spannende Ideen für eigene Docker-Projekte und wertvolle Impulse für ihre strategische Planung.
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -