Sie können Docker monatelang in der Produktion betreiben, ohne ein sichtbares Problem zu bemerken. Container starten, Anwendungen antworten, nichts bricht. Dann schafft ein offen zugänglicher Port oder eine falsch gesetzte Berechtigung einen Einstiegspunkt, den ein Angreifer sich nicht erst erarbeiten musste. Die meisten Docker-Sicherheitsfehler sehen erst dann wie Fehler aus, wenn etwas schiefläuft.
Dieser Artikel behandelt die konkreten Konfigurationen, die Container-Umgebungen gefährden, erklärt, was sie einem Angreifer ermöglichen, und schließt mit einer Checkliste, die Sie noch heute gegen Ihr eigenes Setup prüfen können.
Warum Docker-Sicherheit schwieriger ist als sie aussieht
Container wirken isoliert. Sie starten einen, er läuft in seinem eigenen Prozessraum, und von innen existiert der nächste Container nicht. Diese Isolation ist real, aber nur partiell. Container teilen sich den Kernel des Hosts. Das bedeutet: Ein Prozess innerhalb eines Containers kann unter bestimmten Bedingungen vollständig auf das Host-System zugreifen.
Docker ist standardmäßig auf Entwicklerkomfort ausgelegt, nicht auf Produktionshärtung. Root-Zugriff aktiviert. Alle Ports an alle Interfaces bindbar. Kein Laufzeit-Monitoring. Die meisten Entwickler übernehmen diese Einstellungen, deployen den Container und gehen weiter. Das ist ein vernünftiger Ansatz für den Einstieg, aber kein fertiger Sicherheitsstatus.
Laut Red Hat's 2024 State of Kubernetes Security report, 67 % der Unternehmen haben Application-Deployments aufgrund von Container- oder Kubernetes-Sicherheitsbedenken verzögert oder verlangsamt. Diese Reibung entsteht meistens nicht durch Angriffe, sondern dadurch, dass Teams feststellen, dass ihre Container-Setups eine Härtung benötigten, die nie eingebaut wurde.
Wir sehen häufig Container in der Produktion, die dieselbe Konfiguration haben wie auf dem lokalen Rechner eines Entwicklers. Genau dort häufen sich Docker-Sicherheitsfehler still an, ohne sichtbare Symptome, bis ein Audit stattfindet oder etwas ausfällt.
Die Fehler, die diese Lücken verursachen, sind konkret, vorhersehbar und größtenteils vermeidbar, beginnend auf der Konfigurationsebene.
Häufige Docker-Konfigurationsfehler
Die meisten Container-Sicherheitsvorfälle beginnen nicht mit einem Zero-Day-Exploit. Sie beginnen mit einer Konfiguration, die am ersten Tag gesetzt wurde, ohne viel Nachdenken über Netzwerkexposition oder Rechtebereiche.
Die Docker-Standardeinstellungen sind darauf ausgelegt zu funktionieren. Die Lücke zwischen funktional und sicher ist der Bereich, in dem sich Docker-Container-Sicherheitsrisiken ansammeln, besonders in selbst gehosteten Setups, die einmal deployed und nie wieder angefasst werden.
Dieses Muster begegnet uns oft: Container auf Servern mit öffentlicher IP, mit Port-Bindings, Benutzereinstellungen und Netzwerkkonfigurationen genau so, wie sie beim initialen Deployment waren.
Container als Root betreiben
Wenn du einen Docker-Container ohne Angabe eines Benutzers startest, läuft er als root. Das bedeutet: Jeder Prozess im Container – einschließlich deiner Anwendung – hat root-Rechte innerhalb des Container-Namespaces.

Root innerhalb eines Containers entspricht nicht Root auf dem Host – aber die Trennung ist nicht absolut. Privilege-Escalation-Exploits, die auf die Runtime abzielen, wie das bekannte runc CVE-2019-5736 und ähnliche Runtime-Schwachstellen, setzen häufig einen Root-Prozess im Container voraus.
Nicht-root-Container beseitigen die Abhängigkeit von Root-Prozessen, auf die solche Angriffe angewiesen sind, und reduzieren die Angriffsfläche für diese Klasse von Schwachstellen erheblich. Das Container-Escape-Risiko lässt sich damit jedoch nicht vollständig ausschließen.
Das Hinzufügen einer USER-Direktive in dein Dockerfile behebt dieses Problem. Einige offizielle Images liefern bereits einen unprivilegierten Benutzer mit, den du per USER-Direktive aktivieren kannst. Viele Images laufen jedoch standardmäßig als root, ohne einen vorgefertigten App-Benutzer. In diesen Fällen legst du den Benutzer im Dockerfile an, bevor du zu ihm wechselst. Für die meisten selbst gehosteten Setups beseitigt diese eine Änderung eine ganze Klasse von Privilege-Escalation-Risiken.
Zu viele Ports öffentlich zugänglich machen
Wenn du einen Port mit Docker veröffentlichst, schreibt Docker seine eigenen iptables-Regeln direkt. Diese Regeln werden vor den Firewall-Regeln auf Host-Ebene ausgeführt. Das ist ein bekanntes, von der Community gemeldetes Verhalten und dokumentiert im Paketfilter-Leitfaden von Docker, keine Fehlkonfiguration. Das bedeutet: UFW und ähnliche Tools blockieren nicht, was Docker bereits geöffnet hat.

Docker schreibt direkt in iptables und umgeht dabei die UFW- und firewalld-Standardregeln auf vielen Linux-Hosts. Ein Port, der an 0.0.0.0 gebunden ist, kann dadurch öffentlich erreichbar sein, auch wenn die Firewall korrekt konfiguriert scheint. Cloud-Security-Groups und Regeln in der DOCKER-USER-Chain können diesen Traffic dennoch blockieren – die tatsächliche Angriffsfläche hängt also von deiner konkreten Netzwerkkonfiguration ab.
Binden Sie Dienste möglichst an 127.0.0.1, leiten Sie öffentlichen Traffic über einen Reverse-Proxy und veröffentlichen Sie nur, was tatsächlich von außen erreichbar sein muss. Ein Reverse-Proxy ist der zuverlässigste Weg, um zu kontrollieren, was vom Host nach außen sichtbar ist.
Fehlende Netzwerkisolierung zwischen Containern ignorieren
Jeder Container im selben Netzwerk kann jeden anderen Container darin uneingeschränkt erreichen. Die Standard-Bridge filtert keinen Traffic zwischen Containern, die sie gemeinsam nutzen, und die meisten Setups ändern diese Konfiguration nie.

Wird ein Container kompromittiert, wird diese offene Kommunikation zum Einfallstor für laterale Bewegungen. Ein Frontend-Container kann eine Datenbank, einen internen API oder alles andere im selben Standard-Bridge-Netzwerk erreichen – selbst wenn dieser Zugriff nie vorgesehen war.
Benutzerdefinierte Netzwerke geben dir genaue Kontrolle darüber, welche Container miteinander kommunizieren können. Aber ein einziges gemeinsam genutztes Netzwerk für alle Services erlaubt weiterhin freien Datenverkehr zwischen allen Containern. Echte Isolation erfordert, dass Services, die nicht miteinander kommunizieren sollen, in getrennten Netzwerken laufen. Die Standard-Bridge zu deaktivieren ist der Anfang, nicht das Ziel.
Den Docker-Sockel im Überblick
Der Socket unter /var/run/docker.sock ist die Steuerschnittstelle für die gesamte Docker-Engine. Wird er in einen Container eingebunden, erhält dieser Container direkten Root-Zugriff auf den Daemon des Hosts.

Mit diesem Zugriff kann ein Container neue Container starten, Host-Verzeichnisse einbinden, laufende Container inspizieren und verändern und letztlich die Host-Maschine kontrollieren. Die Angriffsfläche entspricht der von root auf dem Host. Jedes Tool, das Socket-Zugriff benötigt, sollte daher sorgfältig geprüft werden.
Für die meisten Anwendungsfälle gibt es sicherere Alternativen: bereichsbegrenzte APIs oder Docker-Verwaltungstools die keinen Socket-Zugriff benötigen. Docker-in-Docker bringt eigene Sicherheits- und Betriebskompromisse mit sich und ist kein direkter Ersatz.
Konfigurationsfehler schaffen die erste Angriffsfläche. Die Wahl von Images und Abhängigkeiten bestimmt, wie stark sich diese Angriffsfläche im Laufe der Zeit vergrößert.
Image- und Secrets-Fehler, die länger bestehen als der Container
Wenn ein Container gestoppt wird, verschwinden die darin enthaltenen Konfigurationsfehler mit ihm. Wenn man jedoch aus einem Image neu baut, das eine Schwachstelle oder fest einprogrammierte Zugangsdaten enthält, kehrt das Problem mit dem Container zurück. Fehler auf Image-Ebene werden zwischen Deployments nicht zurückgesetzt.
Sie reisen mit dem Image in jede Umgebung, die es lädt, in jede Registry, die es speichert, und zu jedem Teammitglied, das es ausführt. Diese Persistenz macht das Management von Images und Secrets zu einer eigenen Risikokategorie, die getrennt von der Konfiguration auditiert werden sollte.
Dieses Muster begegnet uns häufig: Ein Image, das zu Projektbeginn sorgfältig ausgewählt und seitdem nie neu gebaut wurde, entfernt sich langsam von dem Sicherheitsstand, den es ursprünglich repräsentierte.
Nicht vertrauenswürdige oder veraltete Images verwenden
Öffentliche Registries stehen jedem offen. Über Docker Hub wurden bereits bösartige Images verbreitet, die Crypto-Miner und Backdoors enthielten - eingebettet in den Layer-Verlauf und über Container-Neustarts hinaus bestehend. Vor dem Pullen zu prüfen ist wichtig, besonders bei Images von inoffiziellen oder unbekannten Herausgebern.

Ein weiteres Problem ist die Veralterung. Ein offizielles Image, das vor sechs Monaten gepullt und seitdem nie neu gebaut wurde, hat mit jedem gegen seine Pakete veröffentlichten CVE ungepatchte Docker-Schwachstellen angesammelt. Das Image ist nicht defekt. Es entspricht nur nicht mehr dem aktuellen Stand.
Sonatype's 2024 State of the Software Supply Chain report ergab, dass in 95 % der Fälle, in denen eine verwundbare Komponente eingesetzt wird, bereits eine gefixte Version verfügbar ist, und dass 80 % der Anwendungsabhängigkeiten länger als ein Jahr nicht aktualisiert werden. Dieses Muster gilt auch für Docker-Base-Images, da sie auf denselben Open-Source-Paketen basieren.
Nutze offizielle Images von verifizierten Herausgebern und pinne spezifische Versions-Tags, statt dich auf "latest" zu verlassen. Lege einen regelmäßigen Rebuild-Rhythmus fest, um Images aktuell zu halten.
Secrets fest in Dockerfiles und Compose-Dateien einprogrammieren
Zugangsdaten, die in eine Dockerfile-Anweisung ENV oder ARG geschrieben, fest in einen Compose-Environment-Block eingetragen, als Build-Argumente übergeben oder in einer .env-Datei gespeichert werden, die ins Versionsverwaltungssystem eingecheckt ist, verschwinden nicht, wenn der Container gestoppt wird. Sie verbleiben im Image-Layer-Verlauf oder in der Versionsverwaltung und sind für jeden zugänglich, der darauf Zugriff hat.

Dies ist einer der am häufigsten übersehenen Docker-Sicherheitsfehler, weil er während der Entwicklung keine sichtbaren Probleme verursacht. Ein API-Schlüssel in einer ENV-Anweisung funktioniert einwandfrei. Er steckt aber auch im Repository, ist ins Image eingebrannt und wird überall hin verteilt, wohin das Image gelangt.
Modernes Docker Compose unterstützt einen nativen Secrets-Mechanismus, der Zugangsdaten zur Laufzeit einbindet, ohne sie ins Image einzubauen. Docker's Secrets API und externe Secrets-Manager folgen demselben Prinzip. Diese Optionen halten Zugangsdaten vollständig aus Build-Artefakten und eingecheckten Dateien heraus.
Laufzeit-Umgebungsvariablen sind eine Verbesserung gegenüber fest einprogrammierten Zugangsdaten, sind aber weiterhin über Docker-Inspect-Output, Logs und Crash-Dumps einsehbar. Sie sind ein Schritt nach vorn gegenüber eingebrannten Secrets, aber keine fertige Lösung.
Container-Images nicht regelmäßig aktualisieren
Monatelang dasselbe Image zu betreiben ist weit verbreitet. Mit jedem Tag, der nach der Bekanntgabe einer neuen Schwachstelle vergeht, ohne dass ein Rebuild stattfindet, wächst das Expositionsfenster der Container - ohne dass sich äußerlich etwas verändert.
Lege einen festen Rebuild-Zeitplan fest. Automatisiere diesen Prozess wo möglich und führe regelmäßig einen Schwachstellenscanner gegen aktuelle Images aus. Das Ziel ist nicht Perfektion. Es geht darum, die Zeit zwischen der Veröffentlichung eines Patches und seinem Deployment zu verkürzen.
Zugriffskontrolle und Monitoring werden bei schnellen Deployments oft nachrangig behandelt. Gleichzeitig sind das die Bereiche, in denen Vorfälle am längsten unentdeckt bleiben.
Zugriffskontrolle und fehlende Transparenz
Wenn ein Container mit einer soliden Konfiguration und aktuellen Images läuft, bleiben zwei Fehlerkategorien bestehen. Beide sind von Natur aus unsichtbar: Ein schwaches Zugriffssteuerungsproblem fällt erst auf, wenn jemand es ausnutzt, und eine Monitoring-Lücke bemerkt man erst, wenn man Aktivitäten untersuchen muss, die nie protokolliert wurden.
Dasselbe Red Hat 2024 Forschung ergab, dass 42 % der Teams nicht über ausreichende Fähigkeiten verfügten, um Container-Sicherheitsrisiken und damit verbundene Bedrohungen zu bewältigen.
Überwachungslücken fallen in der Regel erst bei der Analyse von Vorfällen auf, nicht davor. Wenn Transparenz zur Priorität wird, geht es meistens schon darum, auf etwas zu reagieren, nicht mehr darum, es zu verhindern.
Schwache Authentifizierung und ungeschützte Management-Dashboards
Ein Container-Management-Dashboard auf einer öffentlichen IP ohne Authentifizierung erfordert keinen besonders versierten Angreifer. Er muss nur die Adresse kennen. Die Hürde ist niedriger, als die meisten Teams ahnen.

Self-hosted-Monitoring- und Management-Tools werden standardmäßig mit einem Web-Interface ausgeliefert, das auf allen Netzwerk-Interfaces erreichbar ist. Diese auf einer öffentlichen IP ohne vorgelagerte Authentifizierung zu betreiben, ist das Container-Äquivalent eines offen stehenden Admin-Panels.
Authentifizierung, ein Reverse-Proxy und die Platzierung im privaten Netzwerk sind das Minimum. Zugriffskontrolle ist ein Konfigurationsschritt, den man jedem Management-Interface hinzufügt, und kein Feature, das von Haus aus aktiv ist.
Dasselbe gilt für Docker CLI und GUI-Verwaltung; Admin-Zugriff auf den Daemon birgt dasselbe Risiko, unabhängig vom verwendeten Interface.
Fehlende Überwachung des Container-Verhaltens
Wird ein Container kompromittiert, hinterlässt die Aktivität des Angreifers Spuren: veränderte Prozessverhalten, ungewöhnliche Netzwerkverbindungen und unerwartete Dateiänderungen. Ohne Log-Erfassung existieren diese Spuren in keiner Form, mit der man arbeiten kann.
Zentralisierte Log-Erfassung, Container-Audit-Logging und Runtime-Monitoring-Tools liefern die Daten, um ungewöhnliche Aktivitäten zu erkennen, bevor sie sich ausweiten. Das Ziel ist nicht, jede Zeile zu analysieren, sondern die Daten verfügbar zu haben, wenn eine Untersuchung nötig wird.
Container-Setups, die in der Produktion ohne Log-Pipeline und ohne Alerts still laufen, sind nicht wartungsarm. Sie sind unkontrolliert. Das sind zwei grundlegend verschiedene Betriebszustände.
Warum die Infrastrukturumgebung ebenfalls eine Rolle spielt
Container-Sicherheit beginnt mit der Konfiguration, aber Konfiguration läuft auf Infrastruktur. Ein Host mit falsch konfiguriertem Netzwerk, gemeinsam genutzten Ressourcen oder fehlendem Netzwerk-Filtering schafft Bedingungen, die jeden darauf laufenden Container betreffen. Den Container-Stack richtig aufzusetzen und die Server-Konfiguration richtig zu machen, sind zwei getrennte Aufgaben.
Viele Docker-Sicherheitslücken werden durch Bedingungen verstärkt, die die Container von ihrer Umgebung erben:
- Ein Shared-Tenancy-Server ohne Hardware-Isolation zwischen den Mietern
- Ein Host-Kernel ohne eingespielten Patches
- Ein Host ohne integriertes Netzwerk-Filtering
Das ersetzt die oben genannten Konfigurationsschritte nicht, da sauberes Container-Hardening unabhängig von der Infrastrukturschicht wichtig ist. Der Start auf isolierter Infrastruktur nimmt jedoch eine Fehlerquelle aus der Gleichung heraus.
Bei Cloudzy bieten wir zwei Wege an, je nach den Anforderungen deines Setups:
- Linux VPS: eine saubere Umgebung, um Docker selbst zu deployen und die Hardening-Schritte aus diesem Artikel anzuwenden
- Portainer VPS: eine Ein-Klick-Option mit vorinstalliertem Portainer; der Server startet, und du bist sofort im Dashboard
Beide Optionen laufen auf derselben Infrastruktur: KVM-Virtualisierung, AMD Ryzen 9 CPUs mit bis zu 5,7 GHz Boost-Takt, DDR5 Arbeitsspeicher, NVMe SSD Storage, bis zu 40 Gbps Netzwerk und kostenloser DDoS-Schutz über BuyVM-Filterung, an 12 globalen Standorten mit 99,95 % Uptime-SLA.
Einen ausführlicheren Einblick in den Betrieb von Portainer auf einem VPS gibt es in einem eigenen Artikel.
Sicherheits-Checkliste für Docker-Deployments
Die oben beschriebenen Docker-Sicherheitsfehler entstehen meist durch einmalige Konfigurationsentscheidungen, die danach nie mehr überprüft werden. Diese Checkliste deckt solche Lücken in bestehenden Setups auf. Sie dient als Audit, nicht als Deployment-Anleitung.
Diese Docker-Sicherheits-Best-Practices zeigen, wie du Docker-Container gegen die häufigsten oben beschriebenen Konfigurationsfehler absicherst.
Kurzübersicht: Alle 9 Fehler
| Fehler | Kategorie | Schnelle Lösung |
| Als root ausführen | Konfiguration | Füge die USER -Direktive zur Dockerfile hinzu |
| Ports an 0.0.0.0 gebunden | Konfiguration | An 127.0.0.1 binden und über einen Reverse Proxy routen |
| Keine Netzwerkisolierung | Konfiguration | Dienste auf separate benutzerdefinierte Netzwerke aufteilen, basierend auf den jeweiligen Zugriffsanforderungen. |
| Docker-Socket eingebunden | Konfiguration | Mount entfernen; stattdessen scoped APIs oder Alternativen verwenden |
| Nicht vertrauenswürdige oder veraltete Images | Bild | Offizielle Images mit festen Versions-Tags verwenden |
| Hartcodierte Secrets | Bild | Zugangsdaten in Runtime-Umgebungsvariablen oder einen Secrets Manager auslagern |
| Kein Image-Rebuild-Zeitplan | Bild | Monatlichen Rebuild-Rhythmus festlegen; wo möglich automatisieren |
| Dashboards ohne Authentifizierung | Zugriff | Authentifizierung hinzufügen und Management-UIs in private Netzwerke verlagern |
| Keine Container-Log-Erfassung | Zugriff | Zentralisiertes Logging und Laufzeit-Monitoring einrichten |
Wir empfehlen, das Tool zunächst gegen bestehende Setups laufen zu lassen, da dort Lücken am wahrscheinlichsten bereits vorhanden sind.
Container laufen ohne Root-Rechte: Prüfen Sie Ihre Docker-Dateien auf eine USER-Direktive. Fehlt diese, läuft der Container als Root.
Port-Bindungen auf localhost beschränkt oder über Proxy geleitet: Führen Sie docker ps aus und prüfen Sie die Port-Bindungen. Ein Eintrag mit 0.0.0.0:PORT ist auf Hosts öffentlich erreichbar, auf denen kein vorgelagerter Security Group-, externer Firewall- oder DOCKER-USER-Chain-Regel den Zugriff sperrt.
Benutzerdefinierte Bridge-Netzwerke im Einsatz: Container im Standard-Bridge-Netzwerk von Docker können sich gegenseitig uneingeschränkt erreichen. Container im selben benutzerdefinierten Bridge-Netzwerk können ebenfalls miteinander kommunizieren. Teilen Sie Dienste deshalb nach Vertrauensgrenze auf separate Netzwerke auf, um echte Isolation zu erreichen.
Docker-Socket nicht in Containern eingebunden: Prüfen Sie Compose-Dateien und Startargumente. Taucht /var/run/docker.sock als Volume auf, stellen Sie sicher, dass dies notwendig und beabsichtigt ist.
Basis-Images von verifizierten Anbietern mit festgelegten Versionen: Ein FROM ubuntu:latest zieht eine unbestimmte, möglicherweise veraltete Version. Pinnen Sie auf ein konkretes Release.
Keine Secrets in Docker-Dateien, Compose-Dateien oder Build-Argumenten: Der Image-Layer-Verlauf speichert Zugangsdaten auch nach dem Löschen des Containers. Verwenden Sie Compose Secrets, Swarm Secrets, Build Secret Mounts oder einen externen Secrets Manager. Laufzeit-Umgebungsvariablen sind besser als hardcodierte Werte, erscheinen aber weiterhin in der Inspect-Ausgabe und in Logs.
Rebuild-Zeitplan für Images festgelegt: Alte Images sammeln Schwachstellen an. Ein monatlicher Rebuild-Rhythmus hält das Angriffsfenster für die meisten Setups überschaubar.
Management-Interfaces hinter Authentifizierung: Jedes Dashboard auf einer öffentlichen IP ohne Authentifizierung ist ein offener Eintrittspunkt. Platzierung im privaten Netzwerk ist vorzuziehen, wo immer möglich.
Container-Logs werden erfasst: Ohne eine Log-Pipeline hängt die Erkennung von Vorfällen vom sichtbaren Systemausfall ab. Das ist ein zu später Hinweis, um noch rechtzeitig zu reagieren.
Fazit
Die Standardkonfiguration von Docker ist auf Bequemlichkeit ausgelegt, nicht auf Sicherheit. Die meisten Fehler in diesem Artikel lassen sich auf Einstellungen zurückführen, die nach dem ersten Deployment nie geändert wurden - nicht auf ausgefeilte Angriffe.
Die meisten Korrekturen sind einmalige Konfigurationsentscheidungen: eine USER-Direktive, eine Änderung der Port-Bindung, ein eigenes Netzwerk, ein Rebuild-Zeitplan. Für die meisten Setups sind keine neuen Tools erforderlich.
Die Container-Konfiguration korrekt aufzusetzen ist die erste Aufgabe. Die Infrastruktur, auf der er läuft, die zweite. Beides ist wichtig, und keines ersetzt das andere.