Versuch 4: Docker
1 Docker: Die Revolution der Containerisierung
Die Containerisierung stellt einen Paradigmenwechsel in der Anwendungsbereitstellung dar und bietet eine ressourcenschonende Alternative zur traditionellen Virtualisierung. Docker, das 2013 als Open-Source-Projekt ins Leben gerufen wurde, ist heute die führende Plattform für Containerisierung, da es einen standardisierten Ansatz für das Verpacken von Anwendungen mitsamt ihren Abhängigkeiten bereitstellt [1]. Die Hauptmotivation für die Entwicklung von Docker war die Lösung des berüchtigten “It works on my machine”-Problems, um portable und konsistente Umgebungen zu schaffen, die auf Entwicklungs-, Test- und Produktionssystemen identisch funktionieren [2].
Seit seiner Einführung im Jahr 2013 hat die Docker-Plattform die Softwarebereitstellung und -entwicklung grundlegend verändert und sich mit einem Marktanteil von über 33 % als dominierende Containerisierungstechnologie etabliert (siehe Abb. 1) [4]. Diese Analyse untersucht, wie die Architektur von Docker leichtgewichtige, portable Anwendungsumgebungen ermöglicht, was zu 318 Milliarden Container-Pulls (ein Wachstum von 145 % gegenüber dem Vorjahr) und 7,3 Millionen Benutzerkonten (45 % Wachstum) auf Docker Hub geführt hat [5].
2 Historische Entwicklung und Vergleich: Docker vs. Virtuelle Maschinen
Die Ursprünge der Containerisierungstechnologie reichen Jahrzehnte zurück, doch erst mit Docker wurde diese Technologie für breite Anwendungen zugänglich und praktikabel. Während virtuelle Maschinen seit den frühen 2000er Jahren den Virtualisierungsmarkt dominierten, gewinnen Container aufgrund ihrer Effizienz immer mehr an Bedeutung [6]. Die Markteinführung von Docker im Jahr 2013 markierte einen Wendepunkt, da Containerisierung zur Industrie-Norm wurde – insbesondere im Zuge des Booms von Cloud Computing und Microservices-Architekturen [7].
2.1 Technologischer Vergleich: Containerisierung und Virtualisierung
Docker-Container unterscheiden sich grundlegend von klassischen virtuellen Maschinen in Bezug auf ihre Architektur:
Virtuelle Maschinen beinhalten ein vollständiges Betriebssystem und benötigen einen Hypervisor zur Hardware-Virtualisierung. Dies sorgt zwar für vollständige Isolierung, geht aber mit erheblichem Ressourcenverbrauch einher. Eine einzelne VM benötigt meist mehrere Gigabyte Arbeitsspeicher und Speicherplatz und startet oft erst nach Minuten [8].
Docker-Container hingegen teilen sich den Kernel des Host-Betriebssystems und virtualisieren lediglich auf Anwendungsebene. Sie benötigen oft nur Megabyte an Arbeitsspeicher, starten in Sekunden und nutzen die Ressourcen des Hosts wesentlich effizienter [9]. Diese Unterschiede machen Docker besonders attraktiv für Microservices-Architekturen, in denen viele kleine Services parallel laufen [7].
+-----------------------------------+ +-------------------------------+
| Physical Hardware | | Physical Hardware |
+-----------------------------------+ +-------------------------------+
| Host OS | | Host OS |
+-----------------------------------+ +-------------------------------+
| Hypervisor | | Container Engine |
+-----------------------------------+ | (Docker, etc.) |
| Guest OS (Linux)| Guest OS (Win) | +-------------------------------+
+------------- +--------------------+ | Container | Container |
| App | Bins/Libs | App | Bins/Libs | | (App + Libs) | (App + Libs) |
+-----+-----------+-----+-----------+ +---------------+---------------+
Abbildung 2: Architektonischer Vergleich zwischen Virtuellen Maschinen und Containern. Virtuelle Maschinen (VMs) basieren auf einer Virtualisierung auf Hardware-Ebene. Dabei läuft in jeder VM ein eigenes Gastbetriebssystem, zusammen mit den jeweils benötigten Bibliotheken und Abhängigkeiten. Ein Hypervisor verwaltet und orchestriert mehrere vollständig isolierte VMs, was zu einem erhöhten Ressourcenverbrauch (RAM, CPU und Speicherplatz) führt, jedoch eine besonders starke Sicherheitsisolation gewährleistet. Container hingegen nutzen eine Virtualisierung auf Betriebssystem-Ebene: Sie teilen sich den Kernel des Host-Betriebssystems und führen isolierte Prozesse aus. Die Container-Engine verwaltet diese Container und ermöglicht eine besonders ressourcenschonende Bereitstellung, minimalen Overhead und einen schnellen Start der Anwendungen. Die Isolierung der Container erfolgt durch Linux-Namespaces und Kontrollgruppen (cgroups).
Ressourcen-Effizienz und Performance:
Docker-Container teilen sich den Kernel des Host-Systems, wodurch keine mehrfachen Betriebssystem-Instanzen benötigt werden und der Speicherbedarf sinkt. Dadurch können Anwendungen mit 5- bis 10-fach höherer Dichte auf derselben Hardware betrieben werden wie mit VMs [9]. Zudem ist die Startzeit deutlich schneller, typischerweise innerhalb von Sekunden im Vergleich zu Minuten bei VMs [8].
Portabilität und Konsistenz von Anwendungen:
Das Docker-Prinzip „Build once, run anywhere“ löst eines der größten Probleme in der Softwareentwicklung: Die Gewährleistung, dass Anwendungen in verschiedenen Umgebungen identisch funktionieren. Durch die Kapselung von Anwendungen samt ihrer Abhängigkeiten stellt Docker konsistentes Verhalten in Entwicklungs-, Test- und Produktionsumgebungen sicher [1]. Diese Portabilität erstreckt sich über unterschiedliche Betriebssysteme (mit Einschränkungen unter Windows), Cloud-Anbieter und On-Premises-Infrastrukturen [10].
Skalierbarkeit und Orchestrierung moderner Anwendungen:
Die Architektur von Docker ermöglicht horizontale Skalierung durch Container-Orchestrierungslösungen. Während Docker Swarm native Orchestrierungsfunktionen bietet, hat sich Kubernetes als De-facto-Standard für das Management containerisierter Anwendungen durchgesetzt 1. Diese Plattformen ermöglichen automatische Skalierung, Lastverteilung, Service-Discovery und Self-Healing – allesamt essenziell für moderne verteilte Anwendungen [11].
Integration in DevOps- und CI/CD-Prozesse:
Docker spielt eine zentrale Rolle in DevOps-Methoden, da es den Übergang von Entwicklung zu Produktion standardisiert. Die Integration mit Continuous Integration/Continuous Deployment (CI/CD)-Tools ermöglicht automatisierte Test- und Deployment-Workflows, wodurch Ausfallzeiten und Fehler bei Deployments reduziert werden [2]. Das Container-Prinzip passt optimal zu Microservices-Architekturen, da einzelne Komponenten unabhängig voneinander bereitgestellt und skaliert werden können [7].
Versionskontrolle und Reproduzierbarkeit:
Docker-Images sind unveränderlich und versioniert, was eine zuverlässige Nachverfolgung von Anwendungsänderungen sowie einfache Rollbacks ermöglicht. Diese Reproduzierbarkeit ist auch für wissenschaftliche Anwendungen und Datenanalysen entscheidend: Ganze Rechenumgebungen lassen sich in Containern kapseln, wodurch Analysen langfristig nachvollziehbar und wiederholbar bleiben [10] [2].
3 Kernkonzepte & Architektur
3.1 Kernkomponenten
Docker besteht aus mehreren Komponenten:
- Docker Engine: Hauptlaufzeitumgebung für Container (Daemon + CLI).
- Docker Daemon (dockerd): Verwaltet Images, Container, Netzwerke, Volumes.
- Docker CLI: Textbasiertes Interface zur Kommunikation mit dem Daemon.
- Docker Registry: Ort zum Speichern und Verteilen von Images (z. B. Docker Hub).
3.2 Image
Images sind eine schreibgeschützte Vorlage mit allem, was eine Anwendung zum Laufen braucht - Code, Bibliotheken, Abhängigkeiten, je nachdem was man in dem Container zur verfügung haben möchte. Sie können von einer reqistry geholt werden und es können eigene Images auf Basis von anderen Images gebaut werden.
docker image list
3.3 Container
Eine Container ist eine laufende Instanz eines Images – leichtgewichtig, schnell startend, er benutzt den Kernel des Hosts mit. Es können mehrere laufende Container, die auf dem gleichen Image basieren, existieren.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
61867276f412 python:3.10 "python3" 45 minutes ago Exited (0) 45 minutes ago ecstatic_wiles
# lädt das offizielle python 3.10 docker image von docker hub herunter und führt es anschließend aus
docker run python:3.10
3.4 Dockerfile, Volumes, Netzwerke
3.4.1 Dockerfile
In Dockerfiles kann man selbst definieren, was die images enthalten und diese anschlißend bauen. Ein Dockerfile ist im Endeffekte eine Liste aus Befehlen die nacheinander ausgeführt werden, um ein image zu erstellen.
FROM python:3.10 #gibt an auf Welchem Basisimage das Image aufbaut
WORKDIR /app # setzt das aktuelle arbeitsverzeichnis fest
COPY requirements.txt . # Kopiert die requirements für die Python app ins aktuelle Arbeitsverzeichnis
RUN pip install -r requirements.txt # führt das installationskommando aus
CMD ["python3", "app.py"]
3.4.2 Volumes
Ein Volume ist ein von Docker verwalteter Speicherbereich auf dem Host-System, den ein oder mehrere Container nutzen können, um Daten dauerhaft zu speichern.
Standardmäßig sind Daten in einem Container flüchtig: Wenn der Container gelöscht wird, sind sie weg.
Ein Volume überlebt das Stoppen, Entfernen und Neubauen von Containern.
Volumes werden außerhalb des Container-Dateisystems gespeichert – also auf dem Host.
docker volume create myvolume
docker run -v myvolume:/app/data myapp
3.4.3 Netzwerke
- Container im gleichen Netzwerk können sich mit Namen ansprechen.
docker network create mynetwork
docker run --network=mynetwork --name=myapp myapp:current
4 Praxisbeispiel
In diesem Praxisbeispiel zeigen wir, wie man Vaultwarden (eine leichtgewichtige Alternative zu Bitwarden) mithilfe von Docker und Docker Compose hostet. Zusätzlich integrieren wir eine MariaDB-Datenbank, um den Umgang mit mehreren Containern und die Verwendung eines externen Datenbanksystems zu demonstrieren.
4.1 docker-compose.yml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
ports:
- "8080:80"
environment:
DATABASE_URL: "mysql://vaultwarden:secret@db/vaultwarden"
ADMIN_TOKEN: '$$argon2id$$v=19$$m=65540,t=3,p=4$$12+t5hWqzNO17mQqIgEJjsrKTBh6bfQoWBHe0UwWEU4$$gSyz06LhcFIm/2P8xvUwdhGGpZBC4beKCFsJ3RCTTcI'
volumes:
- ./data:/data
depends_on:
- db
db:
image: mariadb:10.11
container_name: mariadb
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=supersecret
- MYSQL_DATABASE=vaultwarden
- MYSQL_USER=vaultwarden
- MYSQL_PASSWORD=secret
volumes:
- ./config/mariadb:/var/lib/mysql
4.2 Live Demo :D
5 Anwendungen und Ausblick
5.1 Typische Einsatzbereiche
Docker findet in verschiedenen Bereichen Anwendung.
5.1.1 Microservice Architektur
Einer der häufigsten Einsatzbereiche ist die Microservice-Architektur, bei der Anwendungen in kleine, unabhängige Dienste aufgeteilt werden. Dadurch können hoch ausgelastete Anwendungen einzeln skaliert werden.
5.1.2 CI/CD
Ein weiterer wichtiger Bereich ist Continuous Integration/Continuous Deployment (CI/CD), insbesondere durch den Einsatz von Pipeline Runnern, die den Entwicklungsprozess automatisieren und beschleunigen. So können z.B. Github Actions Runner je nach Bedarf als Container deployed werden und individuell skaliert werden.
5.1.3 DevOps
Docker wird auch häufig in DevOps-Praktiken verwendet, um die Zusammenarbeit zwischen Entwicklung und Production zu verbessern. Zudem eignet sich Docker hervorragend für die Erstellung und Verwaltung von Testumgebungen, was die Konsistenz und Effizienz von Tests erhöht. So kann zum Beispiel in einem separaten Container die Testumgebung aufgesetzt werden und in einem weiteren Container die Prod Umgebung.
5.1.4 Datenbanken und Selfhosting
Datenbanken können ebenfalls in Docker-Containern verpackt und verwaltet werden, was die Bereitstellung und Skalierung erleichtert. Schließlich ermöglicht Docker das einfache Self-hosting von (Web-)Anwendungen, was die Kontrolle und Flexibilität über die Bereitstellung von Anwendungen erhöht.
5.2 Grenzen & Herausforderungen
Trotz seiner vielen Vorteile gibt es auch einige Grenzen und Herausforderungen bei der Verwendung von Docker.
- Die Isolierung von Containern ist nicht so streng wie bei virtuellen Maschinen, was potenzielle Sicherheitsrisiken hervorbringen kann.
- Die Performance kann durch den erzeugten Overhead in den Containern eingeschränkt sein, insbesondere bei intensiver Nutzung.
- Ein weiteres Problem ist die fehlende Datenpersistenz bei Stopp des Containers, was zusätzliche Maßnahmen zur permantenten Speicherung erfordert.
- Zudem kann es zu erhöhter Netzwerklatenz kommen, insbesondere wenn Container über mehrere Hosts verteilt sind.
- Schließlich kann die Verwaltung und Skalierung vieler Container komplex sein, was den Einsatz von Tools wie Kubernetes notwendig macht.
6 Sicherheit von Containern
6.1 Aspekte der Container-Sicherheit
6.1.1 Isolation
Wurde bereits erwähnt; die Isolation von Docker ist nicht komplett wie bei Virtuellen Maschinen garantiert, da kein eigenes Betriebssystem simuliert wird, sondern der Betriebssystem/ Kernel vom Host verwendet wird. Docker nutzt sogenannte Namespaces, um Container voneinander und vom Hostsystem zu isolieren. Diese Mechanismen sorgen dafür, dass Prozesse innerhalb eines Containers nur ihre eigene Umgebung „sehen“ und keinen Zugriff auf andere Container oder den Host haben.
Wichtige Namespace-Typen:
PID-Namespace: Prozesse in einem Container können keine anderen Prozesse außerhalb ihres Containers sehen.
Network-Namespace: Jeder Container erhält ein eigenes Netzwerkinterface, wodurch IP-Adressen und Ports isoliert bleiben.
Mount-Namespace: Container erhalten eine eigene Sicht auf das Dateisystem, unabhängig vom Host.
Man muss jedoch beachten, dass die Isolation durch Schwachstellen oder Fehlern umgangen werden kann und eine vollständige Trennung nicht garantiert ist.
6.1.2 Beschränkung der Hardware
Mit Control Groups (cgroups) lassen sich Ressourcen wie CPU, RAM, Block-I/O oder Netzwerkbandbreite für Container beschränken. Dadurch kann man etwa verhindern, dass ein Container durch hohe Last (z.B. bei einem Denial-of-Service-Angriff) den Host oder andere Container überlastet
6.1.3 Entfernen von Rechten
Manchen Containern kann man die Write-Berechtigung entziehen
6.2 Potentielle Gefahren
6.2.1 unbenutzte Ports
Oft werden in der docker-compose File die unbenutzten Ports nciht entfernt - sie könnten ein Sicherheitsrisiko sein
6.2.2 Privilligierte Ports
Wenn man einem Container den Flag –privileged gibt, erhält er erweiterte Rechte, etwa Zugriff auf Geräte im Host-Verzeichnis /dev/. Ein Angreifer kann sich dadurch bei einem erfolgreichen Angriff Zugang zum Host-System verschaffen. Der –privileged-Modus sollte nur dann verwendet werden, wenn es unbedingt erforderlich ist.
6.2.3 Root im Container
Container laufen standartmäßig als root, was bei einem Kompromiss riskant ist.-> Besser ist es, Container mit nicht-root User zu betreiben, denn wenn ein Angreifer aus dem Container ausbricht und der Root Container der selbe ist wie fürs Host, verschafft er sich automatisch die Rechte für den Host.
7 References:
- Islavath, N. (2020). The Power of Docker: Containerization for Efficient Software Development and Deployment. International Journal of Science and Research (IJSR).
- (2015) ACM SIGOPS Operating Systems Review, Special Issue on Repeatability and Sharing of Experimental Artifacts. 49(1), 71-79; doi:10.1145/2723872.2723882
- Datanyze. “Leading Containerization Technologies Market Share Worldwide in 2024.” Statista, Statista Inc., 22 Jan 2025
- Market share of leading containerization technologies worldwide 2024
- Docker Index Shows Continued Massive Developer Adoption and Activity to Build and Share Apps with Docker
- Allison Randal. 2020. The Ideal Versus the Real: Revisiting the History of Virtual Machines and Containers. ACM Comput. Surv. 53, 1, Article 5 (January 2021), 31 pages.
- Muzumdar, P., Bhosale, A., Basyal, G.P., & Kurian, G. (2024). Navigating the Docker Ecosystem: A Comprehensive Taxonomy and Survey. ArXiv, abs/2403.17940.
- Baresi, L., Quattrocchi, G., & Rasi, N. (2023). A Qualitative and Quantitative Analysis of Container Engines. ArXiv, abs/2303.04080.
- Verma, M., & Dhawan, M. (2017). Towards a More Reliable and Available Docker-based Container Cloud. ArXiv, abs/1708.08399.
- Boettiger, C., & Eddelbuettel, D. (2017). An Introduction to Rocker: Docker Containers for R. ArXiv, abs/1710.03675.
- Shah, J., & Dubaria, D. (2019). Building Modern Clouds: Using Docker, Kubernetes & Google Cloud Platform. 2019 IEEE 9th Annual Computing and Communication Workshop and Conference (CCWC), 0184-0189.