Irgendetwas muss Docker besser machen, als andere bekannte Prinzipien und Methoden der Containerisierung und Isolierung. Im zweiten Teil des Docker-Workshops beleuchten wir daher das Konzept der Images, insbesondere den Unterschied zwischen Images und Containern.
Ein besonders wichtiger Aspekt bei Containern sind die Images. So wird jeder Container aus einem eigenen Image mit eigenem Dateisystem heraus gestartet. Dazu packt der Build-Prozess eines Images alles, was die Applikation zur Laufzeit benötigt (Bibliotheken, Tools, Compiler, Config-Dateien etc.), in das Image hinein und startet daraus den Container. Es ist genau dieser Prozess, der Container besonders portabel macht.
Aber Achtung: Docker unterscheidet zwischen Containern und Images. Daher ist es wichtig, den Unterschied zwischen beiden Konstrukten genau zu kennen. Im Allgemeinen versteht man unter einem Image eine Art Archiv, das Dateien beinhaltet und als geschlossene Einheit betrachtet werden kann.
Zu jedem Docker-Image mit seinen Dateien gehört immer auch eine Beschreibungsdatei, das sogenannte Dockerfile oder auch „Manifest“. Dieses beinhaltet unter anderem spezielle Docker-Konfigurationsanweisungen, etwa zur Netzwerkkonfiguration, sowie eine Beschreibung, wie die einzelnen Image-Layer (dazu später mehr) aufeinander aufbauen. Letztendlich beschreibt die Datei also, wie ein Docker-Container auszusehen hat.
Jedes Docker-Abbild verwendet daher als Basis-Image meist ein Abbild für ein (Linux)-Betriebssystem wie CentOS oder Ubuntu, um den drauf aufbauenden Applikations-Layern die jeweils passende Laufzeitumgebung mitzugeben. Jedes Docker-Image ist – im Gegensatz zu einer Applikation mit ihren Abhängigkeiten vom Host-System – somit portabel; es lässt sich zwischen verschiedenen Systemen (physische/virtuelle Hosts, Cloud) hin und her transportieren oder auf einem Repository hosten.
Image-Hierarchie
Wurde aus einem Basis-Image ein Container initialisiert, kann der Nutzer jederzeit neue „Momentaufnahmen“ in Form von Images ableiten, die den aktuellen Zustand des Systems widerspiegeln. Dieser Vorgang heißt-Build-Prozess, wird durch das docker-build-Kommando gesteuert und kann wahlweise interaktiv bzw. manuell erfolgen oder automatisch, gesteuert durch ein Docker-Manifest-File.
Startet man beispielsweise mit einer CentOS-Basisinstallation und installiert dann etwa Python, ist die neue Version eine CentOS-Version mit Python. Somit ist der Container selbst quasi die „Laufzeit-Reinkarnation“ des aktuellen Images zum Zeitpunkt „t“.
Nehmen wir an, es existiert hat ein Image einer Datenbank. Dieses ist dadurch entstanden, dass man auf Basis eines ursprünglichen CentOS-Images z. B. MariaDB installiert und aus dem laufenden Container das Datenbank-Image gebaut hat. Möchte man einen neuen Container erzeugen, der aus einem MariaDB-Cluster mit mehreren Instanzen besteht, nimmt man dieses neue Image als Grundlage und erzeugt auf dieser Basis die gewünschte Anzahl Instanzen.
Ähnlich gut funktioniert das z. B. für einen Apache Stack mit PHP. Auch hierzu erzeugt man einen Container aus einem Basis-Image, z. B. für Ubuntu, und installiert den Apache Stack. Aus diesem könnte man dann wieder PHP installieren und erzeugt aus diesem Container ein neues Image „Webserver mit PHP“, aus dem man dann später zu jedem Zeitpunkt weitere neuen Container initialisieren kann.
Halten wir also folgende Eigenschaften von Images fest:
- Docker Images sind Read-Only-Templates, um Container zu erzeugen.
- Docker Images bestehen aus einem oder mehreren Dateisystem-Layern, von denen der jeweils obere auf dem unterliegenden aufsetzt.
- Docker verwendet Union Files Systems (UFS) zum Bauen von Images (dazu im Verlauf mehr)
- Jedes Update eines Images fügt einen neuen Layer hinzu, anstatt jedes Mal das gesamte Image neu zu bauen, wobei der oberste Layer (writeable Layer) quasi als Snapshot fungiert.
- Images können über verschiedene Container geshared sein
- Es gilt die Gleichung: Container = Image + writeable Layer
Da man zu jederzeit Momentaufnahmen eines Containers in Form von Images erzeugen kann, bedarf es für einen effizienten Umgang mit dem geschilderten Prozess einiger wichtiger Prinzipien. An erster Stelle steht hier die Versionierung, die zusätzlich zum eigentlichen Tag des Images mitgeführt wird.