In den Anfängen der Softwareentwicklung war der Weg des Codes von der Entwicklung bis zur Bereitstellung langwierig und mühsam. Entwickler kämpften mit dem sogenannten “Dependency Hell”, da sich Test- und Produktionsumgebungen in subtilen Punkten unterschieden, was dazu führte, dass Code in einer Umgebung funktionierte, in der anderen jedoch nicht. Im Jahr 2013 kam Docker ins Spiel, ursprünglich als Experiment mit Containertechnologie innerhalb von dotCloud zur Vereinfachung der Bereitstellung entwickelt. Docker wurde im März desselben Jahres als Open-Source-Projekt veröffentlicht und entwickelte sich in den folgenden 15 Monaten zu einer führenden Containerplattform.
In diesem Artikel werden wir uns mit der Geschichte der Containertechnologie befassen, den spezifischen Innovationen, die zu Docker’s kometenhaftem Aufstieg führten, und den Linux-Grundlagen, die seine Magie ermöglichen.
Die Entstehung der Containerisierung
Der Begriff “Container” wurde erstmals in den 1970er Jahren von BSD-Unix eingeführt, um isolierte Umgebungen für Anwendungen bereitzustellen. Diese frühen Container waren jedoch schwergewichtig und nicht sehr portabel. Erst in den 2000er Jahren wurden Container dank der Arbeit von Projekten wie LXC (Linux Containers) und Docker leichter und portabler.
Docker’s Aufstieg zur Prominenz
In den Anfängen der Computertechnik liefen Anwendungen direkt auf physischen Servern, oft auch als “Bare Metal” bezeichnet. Dies erforderte von Teams, dass sie jede neue Maschine kauften, physisch installierten, konfigurierten und in Betrieb nahmen. Dies war ein sowohl zeitaufwändiger als auch ressourcenintensiver Prozess.
Um diese Einschränkungen zu beheben, entstand die Hardwarevirtualisierung, die es ermöglichte, mehrere virtuelle Maschinen (VMs) auf einem einzigen physischen Server auszuführen. Dieser Fortschritt verbesserte die Ressourcennutzung und Effizienz erheblich. Die Bereitstellung und Verwaltung von VMs erforderte jedoch immer noch erheblichen Aufwand und Fachwissen.
Die Einführung von Infrastruktur-as-a-Service (IaaS)-Plattformen wie Amazon EC2 markierte einen weiteren Schritt nach vorne. IaaS eliminierte die Notwendigkeit der Einrichtung physischer Hardware und stellte auf Abruf virtuelle Ressourcen bereit, was den Bereitstellungsprozess vereinfachte. Entwickler mussten jedoch weiterhin VMs manuell mit Bibliotheken, Abhängigkeiten und anderen erforderlichen Komponenten konfigurieren.
Plattform-as-a-Service (PaaS)-Lösungen wie Cloud Foundry und Heroku lösten diese Herausforderung, indem sie eine verwaltete Entwicklungsplattform bereitstellten, die die Bereitstellung von Anwendungen vereinfachte. PaaS-Plattformen vereinfachten den Prozess des Bereitstellens und Ausführens von Anwendungen, aber Inkonsistenzen in verschiedenen Umgebungen führten oft zu den gefürchteten “works on my machine” (WOMM)-Problemen.
Im Jahr 2013 tauchte Docker als Gamechanger auf und baute auf den Fortschritten von PaaS auf und führte zwei wichtige Innovationen ein:
- Containerisierung: Docker führte die Containerisierungstechnologie ein, die es ermöglicht, Anwendungen in selbst enthaltenen, isolierten Umgebungen namens Container zu verpacken und auszuführen. Container bieten eine konsistente und tragbare Umgebung für Anwendungen, die sicherstellt, dass sie unabhängig von der zugrunde liegenden Infrastruktur reibungslos ausgeführt werden.
- Docker-Images: Docker führte auch den Begriff Docker-Images ein, die als leichte, ausführbare Blaupausen für Container dienen. Diese Images kapseln alle Abhängigkeiten und Konfigurationen, die für die Ausführung einer Anwendung erforderlich sind, und erleichtern das Bereitstellen und Verwalten von Anwendungen in verschiedenen Umgebungen.
Mit diesen beiden Innovationen revolutionierte Docker die Art und Weise, wie Anwendungen entwickelt, bereitgestellt und verwaltet werden. Dockers Ansatz der Containerisierung löste das WOMM-Problem und brachte beispiellose Effizienz, Portabilität und Konsistenz in die Anwendungsentwicklung und -bereitstellung.
Lightweight Containerization
Containertechnologie und virtuelle Maschinen werden oft miteinander verglichen, obwohl sie sehr unterschiedliche Ansätze verfolgen.
Ein VM-Hypervisor emuliert die zugrundeliegende Serverhardware wie CPU, Speicher und Festplatte, um es mehreren VMs zu ermöglichen, dieselben physischen Ressourcen zu nutzen. Er installiert Gastbetriebssysteme auf dieser virtualisierten Hardware. Prozesse, die auf dem Gastbetriebssystem ausgeführt werden, können die Hardware-Ressourcen des Hosts oder andere VMs nicht sehen.
Docker-Container hingegen teilen sich den Kernel des Host-Betriebssystems. Die Docker-Engine virtualisiert keine Betriebssystemressourcen. Stattdessen erreichen Container die Isolation durch Linux-Namespaces und Control Groups (cgroups).
Namespaces bieten eine Trennung von Prozessen, Netzwerken, Mounts und anderen Ressourcen. cgroups begrenzen und messen die Ressourcennutzung von Containern wie CPU, Speicher und Festplatten-E/A.
Dieser Ansatz macht Container leichter und portabler als VMs. Mehrere Container können einen Host und seine Ressourcen gemeinsam nutzen. Außerdem starten sie viel schneller, da kein Bootvorgang eines vollständigen VM-Betriebssystems stattfindet.
Docker ist also nicht “lightweight virtualization“, sondern eine Form der Containerisierung, die die Isolation von Prozessen auf Betriebssystemebene ermöglicht.
Application Packaging
Bevor Docker 2013 seine revolutionäre Einführung feierte, war Cloud Foundry eine weit verbreitete Open-Source-Plattform als Dienstleistung (PaaS). Viele Unternehmen griffen auf Cloud Foundry zurück, um ihre eigenen PaaS-Angebote zu erstellen, angezogen von ihrer Fähigkeit, die Bereitstellung und Verwaltung von Anwendungen im Vergleich zu traditionellen Infrastruktur-as-a-Service (IaaS)-Lösungen zu vereinfachen. Cloud Foundry bot in dieser Hinsicht mehrere wesentliche Vorteile:
- Vermeidung von Anbieterbindung: Anwendungen, die auf Cloud Foundry erstellt wurden, waren inhärent portabel für verschiedene PaaS-Implementierungen, was verhinderte, dass Anbieter Benutzer an ihre proprietären Plattformen binden.
- Anpassungsfähigkeit an diverse Umgebungen: Cloud Foundry integrierte sich nahtlos in verschiedene Infrastrukturumgebungen und Skalierungsanforderungen und bot eine breite Palette von Bereitstellungsszenarien.
- Umfassende Unterstützung für Sprachen und Datenbanken: Cloud Foundry bot umfassende Unterstützung für gängige Programmiersprachen wie Java, Ruby und JavaScript sowie beliebte Datenbanken wie MySQL und PostgreSQL.
- Optimierte Verpackungs- und Distributionstools: Cloud Foundry bot eine umfassende Suite von Verpackungs- und Distributionstools, die speziell für die effiziente Bereitstellung von Anwendungen entwickelt wurden.
Trotz seiner Stärken konnte Cloud Foundry das Potenzial von Containern als Entwicklerwerkzeug nicht voll ausschöpfen. Die Kerncontainertechnologie, die Cloud Foundry zugrunde liegt, blieb weitgehend hinter den Kulissen verborgen und diente hauptsächlich als internes Isolationsmechanismus als externes Verpackungsformat. Diese Nachlässigkeit ermöglichte es Docker, als Gamechanger aufzutauchen, indem es mit Container-Images zwei kritische PaaS-Verpackungsprobleme ansprach:
- Unified Application Bundling: Docker-Container-Images revolutionierten die Anwendungsverpackung, indem sie die Anwendung selbst, ihre Konfigurationen, Abhängigkeiten und das zugrundeliegende Betriebssystem in eine einzelne, einsatzbereite Einheit bündelten.
- Umgebungskonsistenz: Dockers Ansatz der Containerisierung gewährleistete konsistente Anwendungsumgebungen, indem sie die Lücke zwischen lokalen Entwicklungsumgebungen und Cloud-Laufzeitumgebungen überbrückte und die gefürchteten “works on my machine” (WOMM)-Probleme beseitigte, die traditionelle Bereitstellungsmethoden oft plagten.