Skip to main content

10 Best Practices für Docker-Sicherheit

Docker security best practices blog small

8. Januar 2025

0 Min. Lesezeit

Wichtige Aspekte der Docker-Sicherheit

Docker-Sicherheit umfasst die Aspekte von Docker-Containern beim Erstellen, zur Laufzeit und bei der Orchestrierung. Dazu gehören die Sicherheitsaspekte von Dockerfiles und Docker-Basis-Images ebenso wie die Sicherheitsaspekte von Docker-Containern zur Laufzeit – etwa Benutzerberechtigungen, der Docker-Daemon, geeignete CPU-Begrenzungen für einen Container und weitere Aspekte der Orchestrierung von Docker-Containern in großem Maßstab.

Die Docker-Container-Sicherheit lässt sich in vier zentrale Sicherheitsprobleme unterteilen:

  • Dockerfile-Sicherheit und Best Practices

  • Docker-Container-Sicherheit zur Laufzeit

  • Risiken für die Supply-Chain-Sicherheit bei Docker Hub und ihre Auswirkungen auf Docker-Container-Images

  • Sicherheitsaspekte der Cloud-Native-Container-Orchestrierung im Zusammenhang mit Kubernetes und Helm

Snyk-Spickzettel mit dem Titel „Best Practices für die Sicherheit von Docker-Images“ mit 10 Empfehlungen zur Absicherung von Docker-Images.

Container-Sicherheit für DevSecOps

Finden und beheben Sie Container-Schwachstellen kostenlos mit Snyk.

10 Best Practices für Docker-Sicherheit

1. Bevorzugen Sie minimale Basis-Images

Ein häufiges Sicherheitsproblem bei Docker-Containern sind übergroße Images. Grundsätzlich gilt: Je mehr Software Ihr Container enthält, desto größer ist die potenzielle Angriffsfläche. Deshalb sollte er nur das absolute Minimum enthalten, das Ihre Anwendung benötigt. Oft ist es am einfachsten, ein allgemeines Docker-Container-Image zu verwenden, damit schnell alles läuft. Das kann ein Betriebssystem-Image wie Debian oder ein offizielles Runtime-Image wie Node sein. Wenn Ihr Projekt keine allgemeinen Systembibliotheken oder Systemprogramme benötigt, sollten Sie kein vollwertiges Betriebssystem als Basis-Image verwenden.

Allgemeine Runtime-Images enthalten naturgemäß alles, was zum Ausführen von Anwendungen unter den meisten Umständen erforderlich ist, und wahrscheinlich sehr viel Software, die Ihre Anwendung gar nicht nutzt. Best Practice ist es, mehrstufige Builds zu nutzen: Verwenden Sie beispielsweise während des Builds ein allgemeines Image mit den Build-Tools und übertragen Sie die erstellte Anwendung anschließend in ein schlankes Image mit einer minimalen, für den Produktionseinsatz geeigneten Umgebung. 

Sie können auch spezialisierte Container-Distributionen wie die Distroless-Images von Google oder Alpine Linux verwenden, das standardmäßig deutlich kleiner ist. Bei kompilierten Sprachen wie Go oder C können Sie sogar vollständig leere Container erstellen, indem Sie in der Dockerfile scratch angeben, da solche Binärdateien möglicherweise keinerlei externe Abhängigkeiten haben.

2. Benutzer mit den geringsten Berechtigungen

Wenn in einer Dockerfile kein USER angegeben ist, wird der Container standardmäßig mit dem Root-Benutzer ausgeführt. In der Praxis gibt es nur sehr wenige Gründe, warum ein Container Root-Berechtigungen haben sollte – andernfalls kann daraus ein Sicherheitsproblem entstehen. Docker führt Container standardmäßig mit dem Root-Benutzer aus. Wird dieser Namensraum dann dem Root-Benutzer im laufenden Container zugeordnet, kann der Container potenziell auf dem Docker-Host Root-Zugriff erhalten. Wenn eine Anwendung im Container als Root-Benutzer ausgeführt wird, kann das die Rechteausweitung erleichtern, falls die Anwendung selbst angreifbar ist.

Um die Angriffsfläche zu verringern, erstellen Sie im Docker-Image einen dedizierten Benutzer und eine dedizierte Gruppe für die Anwendung. Verwenden Sie die USER-Anweisung in der Dockerfile, damit die Anwendung im Container mit möglichst geringen Berechtigungen ausgeführt wird.

Beachten Sie, dass neue Benutzer oder Gruppen möglicherweise nicht im Image vorhanden sind. Legen Sie sie daher mit den Anweisungen in der Dockerfile an.

Das folgende Beispiel zeigt, wie Sie dies für ein allgemeines Ubuntu-Image umsetzen:

FROM ubuntu
RUN mkdir /app
RUN groupadd -r lirantal && useradd -r -s /bin/false -g lirantal lirantal
WORKDIR /app
COPY . /app
RUN chown -R lirantal:lirantal /app
USER lirantal
CMD node index.js

Das obige Beispiel:

  • erstellt einen Systembenutzer (-r) ohne Passwort, ohne festgelegtes Home-Verzeichnis und ohne Shell

  • fügt den erstellten Benutzer einer zuvor angelegten vorhandenen Gruppe hinzu (mit groupadd)

  • fügt als letztes Argument den Benutzernamen hinzu, den wir zusammen mit der erstellten Gruppe anlegen möchten

Wenn Sie Node.js und Alpine-Images verwenden, ist darin bereits ein allgemeiner Benutzer namens node enthalten. Hier ein Node.js-Beispiel, das den allgemeinen Benutzer node verwendet:

FROM node:10-alpine 
RUN mkdir /app
COPY . /app
RUN chown -R node:node /app
USER node
CMD [“node”, “index.js”]

Wenn Sie Node.js-Anwendungen entwickeln, empfiehlt sich die offizielle Anleitung Docker and Node.js Best Practices.

Container-Sicherheit für DevSecOps

Finden und beheben Sie Container-Schwachstellen kostenlos mit Snyk.

3. Signieren und überprüfen Sie Images, um MITM-Angriffe zu verhindern

Die Authentizität von Docker-Images stellt eine Herausforderung dar. Wir vertrauen diesen Images sehr, da sie als Container unseren Code in der Produktionsumgebung ausführen. Deshalb müssen wir unbedingt sicherstellen, dass das abgerufene Image dem vom Herausgeber veröffentlichten entspricht und nicht von Dritten verändert wurde. Manipulationen können während der Übertragung zwischen Docker-Client und Registry oder durch die Kompromittierung des Kontos des Registry-Inhabers erfolgen, um ein bösartiges Image hochzuladen.

Das Signieren von Images und anderen zugehörigen Artefakten ist ein wichtiges Thema für die Sicherheit Ihrer Software-Supply-Chain. Die Technologien in diesem Bereich entwickeln sich rasant weiter. Derzeit sind hierfür vor allem diese beiden Tools im Einsatz:

  • Docker Notary v1, die Grundlage der in die Docker CLI integrierten Docker-Content-Trust-Funktion (DCT)

  • Das SigStore-Projekt mit seinem Tool cosign ermöglicht das einfache Signieren, Speichern und Überprüfen von Artefakten.

Docker Content Trust

Docker Content Trust (DCT) gibt es seit mehreren Jahren. Damit können Image-Autoren die Tags signieren, die sie an unterstützte Image-Registry-Server wie DockerHub übertragen, sofern diese die Docker-Notary-API implementieren. Ist DCT auf Ihrem Docker-Host aktiviert, wird jedes Image blockiert, dessen Signatur nicht überprüft werden kann – es kann dann weder abgerufen noch übertragen oder ausgeführt werden. 

Das Signieren Ihres Container-Images mit DCT ist einfach: Legen Sie die Umgebungsvariable `DOCKER_CONTENT_TRUST=1` fest. Wenn Sie Ihr Image dann an DockerHub oder eine andere Notary-fähige Image-Registry übertragen, signiert Docker das Image und speichert die Signatur mit dem Image-Tag.

❯ export DOCKER_CONTENT_TRUST=1                                                                                                                   
❯ docker push myaccount/myimage:1                                                                                                          
The push refers to repository [docker.io/myaccount/myimage]
64ab2aa20cf9: Layer already exists 
b99937123ca0: Layer already exists 
…
orig: digest: sha256:c221d4dc80b8a0d3866602020b09722d942157c720273d325a0496a529b5fcab size: 4093
Signing and pushing trust metadata
You are about to create a new root signing key passphrase. This passphrase
will be used to protect the most sensitive key in your signing system. Please
choose a long, complex passphrase and be careful to keep the password and the
key file itself secure and backed up. It is highly recommended that you use a
password manager to generate the passphrase and keep it safe. There will be no
way to recover this key. You can find the key in your config directory.
Enter passphrase for new root key with ID 85871b5: 
Repeat passphrase for new root key with ID 85871b5: 
Enter passphrase for new repository key with ID e675351: 
Repeat passphrase for new repository key with ID e675351: 
Finished initializing "docker.io/ericsmalling/javagoof"
Successfully signed docker.io/myaccount/myimage:1

Beim Start des Containers können Sie die Signaturprüfung einfach durch Festlegen derselben Umgebungsvariable erzwingen. Die Docker CLI verweigert dann den Abruf oder Start eines Container-Image-Tags, wenn es nicht signiert ist oder eine ungültige Signatur hat.

❯ docker run --rm -it myaccount/someapp                                                                                                docker: Error: remote trust data does not exist for docker.io/myaccount/someapp: notary.docker.io does not have trust data for docker.io/myaccount/someapp.
See 'docker run --help'.

Komplexere Themen wie der Widerruf von Schlüsseln werden mit dem Notary-Binärtool verwaltet. Weitere Informationen zu Notary v1 und DCT finden Sie in der offiziellen Dokumentation.

Sigstore

Die Tools des Projekts Sigstore unterstützen nicht nur Signaturen für Container-Images, sondern auch für beliebige Artefakte, die Sie signieren möchten. Dazu gehören etwa eine Software-Stückliste (SBOM), Bescheinigungen zu einem Artefakt (z. B. Build-Metadaten) oder auch eine Binärdatei, die kein Image ist, ein sogenannter Blob.

Im einfachsten Anwendungsfall signieren Sie ein Image, indem Sie die Binärdatei `cosign sign` ausführen und die Registry sowie das Image samt Tag angeben. Mit dem entsprechenden Befehl `cosign verify` überprüfen Sie anschließend die Signatur.

❯ `Generate keypair (do this once):
❯ cosign generate-key-pair                                                                                                                        
Enter password for private key: 
Enter password for private key again: 
Private key written to cosign.key
Public key written to cosign.pub

❯ `Sign the already-pushed image
❯ cosign sign --key cosign.key myaccount/myimage:1                                                                                       Enter password for private key: 
tlog entry created with index: 1234567
Pushing signature to: index.docker.io/myaccount/myimage

Seit Version 1.9 müssen Sie Ihre Schlüsselpaare mit cosign selbst generieren und verwalten. Zwar gibt es dafür auch den sehr einfach zu verwendenden Befehl `generate-key-pair` (siehe oben), doch die nächste GA-Version wird auch eine Signaturfunktion ohne Schlüssel unterstützen. Diese nutzt einen OpenID-Connect-Autorisierungsmechanismus (kurz OIDC), der automatisch kurzlebige Schlüsselpaare generiert, in denen Ihre E-Mail-Adresse hinterlegt ist. Diese Funktion können Sie bereits jetzt nutzen, indem Sie vor den Befehlen `sign` oder `verify` die Variable `COSIGN_EXPERIMENTAL=1` festlegen.

❯ export COSIGN_EXPERIMENTAL=1
❯ cosign sign myaccount/myimage:1                                                                                                          
Generating ephemeral keys...
Retrieving signed certificate...

        Note that there may be personally identifiable information associated with this signed artifact.
        This may include the email address associated with the account with which you authenticate.
        This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
        By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs.

Are you sure you want to continue? (y/[N]): y
Your browser will now be opened to:
https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=********************
Successfully verified SCT...
tlog entry created with index: 1234567
Pushing signature to: index.docker.io/myaccount/myimage

Bei Image-Signaturen sollten Sie auch berücksichtigen, wie Sie die Container ausführen. Die meisten von uns verwenden Kubernetes als Plattform. Da Kubernetes DCT nicht nativ unterstützt, müssen Sie – sofern Ihre Distribution dies nicht implementiert – eine Form der Laufzeitprüfung bereitstellen. Dafür lässt sich die Kubernetes-Admission-Controller-API nutzen. Open-Source-Projekte wie Connaisseur können die Prüfung für DCT-/Notary-v1- und Cosign-Signaturen übernehmen.

4. FINDEN, BEHEBEN UND ÜBERWACHEN SIE OPEN-SOURCE-SCHWACHSTELLEN

Wenn Sie ein Basis-Image für Ihren Docker-Container auswählen, übernehmen Sie indirekt auch die Risiken aller Aspekte der Container-Sicherheit, die mit dem Basis-Image einhergehen. Dazu gehören möglicherweise unsichere Standardeinstellungen, die nicht zur Sicherheit des Betriebssystems beitragen, sowie Systembibliotheken, die im ausgewählten Basis-Image enthalten sind.

Ein guter erster Schritt ist die Verwendung eines möglichst minimalen Basis-Images, mit dem Ihre Anwendung dennoch problemlos ausgeführt werden kann. So lässt sich die Angriffsfläche verringern, indem Sie die Exposition gegenüber Schwachstellen begrenzen. Das Image wird dadurch jedoch nicht automatisch überprüft und schützt Sie auch nicht vor zukünftigen Schwachstellen, die für die verwendete Version des Basis-Images bekannt gegeben werden.

Eine Möglichkeit, sich vor Schwachstellen in Open-Source-Sicherheitssoftware zu schützen, ist daher der Einsatz von Tools wie Snyk, um kontinuierliche Docker-Sicherheitsscans und die Überwachung potenzieller Schwachstellen in sämtlichen verwendeten Docker-Image-Ebenen zu ergänzen.

Terminalfenster mit einer Befehlszeilen-Arbeitsumgebung unter ~/projects/forks/goof auf dem Master-Branch

Scannen Sie ein Docker-Image mit den folgenden Befehlen auf bekannte Schwachstellen:

# fetch the image to be tested so it exists locally
$ docker pull node:10
# scan the image with snyk
$ snyk test --docker node:10 --file=path/to/Dockerfile

Überwachen Sie ein Docker-Image auf bekannte Schwachstellen. Werden neue Schwachstellen im Image entdeckt, kann Snyk Sie benachrichtigen und Empfehlungen zur Behebung bereitstellen:

$ snyk monitor --docker node:10

Scans von Snyk-Nutzern haben ergeben, dass 44 % der Docker-Image-Scans bekannte Schwachstellen aufwiesen, obwohl neuere und sicherere Basis-Images verfügbar waren. Snyk bietet einzigartige Empfehlungen zur Behebung, mit denen Entwickler handeln und ihre Docker-Images aktualisieren können.

Snyk stellte außerdem fest, dass bei 20 % aller Docker-Image-Scans ein erneuter Build des Docker-Images ausreichte, um die Anzahl der Schwachstellen zu verringern.

Wie prüfen Sie die Container-Sicherheit?

Ein wichtiger Schritt zur Sicherung Ihrer Umgebung ist es, Ihr Linux-basiertes Container-Projekt auf bekannte Schwachstellen zu scannen. Dazu überprüft Snyk das Basis-Image, die installierten und vom Paketmanager verwalteten Betriebssystempakete (OS) sowie wichtige Binärdateien in Image-Ebenen, die nicht über den Paketmanager installiert wurden.

Snyk Container bietet Empfehlungen und Anleitungen zur Behebung von Problemen in öffentlichen Docker-Hub-Images. Dazu gehören Empfehlungen für Basis-Images, die Dockerfile-Ebene, auf der eine Schwachstelle gefunden wurde, und mehr.

5. GEBEN SIE KEINE VERTRAULICHEN INFORMATIONEN IN DOCKER-IMAGES PREIS

Wenn Sie eine Anwendung in einem Docker-Image erstellen, benötigen Sie manchmal Geheimnisse, etwa einen privaten SSH-Schlüssel, um Code aus einem privaten Repository abzurufen, oder Token für die Installation privater Pakete. Kopieren Sie diese in einen temporären Docker-Container, werden sie auf der entsprechenden Image-Ebene zwischengespeichert – selbst wenn Sie sie später löschen. Diese Token und Schlüssel müssen außerhalb der Dockerfile bleiben.

Mehrstufige Builds verwenden

Eine weitere Möglichkeit, die Docker-Container-Sicherheit zu verbessern, ist der Einsatz mehrstufiger Builds. Mit der Unterstützung für mehrstufige Builds in Docker können Sie Geheimnisse in einer temporären Image-Ebene abrufen und verwalten, die später verworfen wird. So gelangen keine vertraulichen Daten in das erstellte Image. Fügen Sie die Geheimnisse wie im folgenden Beispiel per Code zu dieser temporären Ebene hinzu:

FROM ubuntu as intermediate

WORKDIR /app
COPY secret/key /tmp/
RUN scp -i /tmp/key build@acme/files .

FROM ubuntu
WORKDIR /app
COPY --from=intermediate /app .

Docker-BuildKit-Secrets verwenden

Mit einer BuildKit-Funktion in Docker können Sie vertrauliche Dateien einbinden, ohne sie zwischenzuspeichern. Beispiel:

# syntax = docker/dockerfile:1.0-experimental
FROM alpine

# shows secret from default secret location
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecre

# shows secret from custom secret location
RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar

Erfahren Sie auf der Website mehr über Docker-Build-Secrets.

Vorsicht beim rekursiven Kopieren

Seien Sie auch beim Kopieren von Dateien in das zu erstellende Image vorsichtig. Der folgende Befehl kopiert beispielsweise den gesamten Build-Kontextordner rekursiv in das Docker-Image. Dadurch könnten auch vertrauliche Dateien kopiert werden:

COPY . .

Wenn Ihr Ordner vertrauliche Dateien enthält, entfernen Sie sie oder schließen Sie sie mit .dockerignore aus:

private.key
appsettings.json

Wie schützen Sie einen Docker-Container?

Verwenden Sie mehrstufige Builds, damit das für die Produktion erstellte Container-Image frei von Entwicklungsressourcen, Geheimnissen und Token ist.

Stellen Sie außerdem sicher, dass Sie ein Container-Sicherheitstool verwenden, um Ihre Docker-Images über die CLI, direkt über Docker Hub oder die in der Produktion bereitgestellten Images mit Amazon ECR, Google GCR oder anderen Diensten zu scannen.

6. Verwenden Sie feste Tags für Unveränderlichkeit

Jedes Docker-Image kann mehrere Tags haben, die Varianten desselben Images kennzeichnen. Der am häufigsten verwendete Tag ist latest. Er steht für die neueste Version des Images. Image-Tags sind nicht unveränderlich, und die Ersteller der Images können denselben Tag mehrmals veröffentlichen.

Das bedeutet, dass sich das Basis-Image Ihrer Docker-Datei zwischen Builds ändern kann. Änderungen am Basis-Image können zu inkonsistentem Verhalten führen. Es gibt verschiedene Möglichkeiten, dieses Problem zu entschärfen und Ihre Docker-Sicherheitslage zu verbessern:

  • Bevorzugen Sie den spezifischsten verfügbaren Tag. Wenn ein Image mehrere Tags hat, etwa :8 und :8.0.1 oder sogar :8.0.1-alpine, sollten Sie den spezifischsten Tag verwenden, da er die genaueste Image-Referenz darstellt. Vermeiden Sie möglichst allgemeine Tags wie latest. Beachten Sie, dass ein festgelegter Tag irgendwann gelöscht werden könnte.

  • Um zu verhindern, dass ein bestimmter Image-Tag nicht mehr verfügbar ist und für Teams, die darauf angewiesen sind, zum Hindernis wird, können Sie ein lokales Mirror dieses Images in einer Registry oder einem Konto betreiben, das Sie selbst kontrollieren. Berücksichtigen Sie dabei den Wartungsaufwand dieses Ansatzes, denn Sie müssen eine Registry betreiben. Es empfiehlt sich, das gewünschte Image in eine eigene Registry zu replizieren, damit sich das verwendete Image nicht ändert.

  • Seien Sie besonders präzise! Ziehen Sie statt eines Tags ein Image über die spezifische SHA256-Referenz des Docker-Images. So erhalten Sie bei jedem Abruf dasselbe Image. Beachten Sie jedoch, dass die Verwendung einer SHA256-Referenz riskant sein kann: Ändert sich das Image, ist dieser Hash möglicherweise nicht mehr verfügbar.

Sind Docker-Images sicher?

Docker-Images können auf Open-Source-Linux-Distributionen basieren und darin Open-Source-Software und -Bibliotheken bündeln. Eine aktuelle Studie von Snyk zur Open-Source-Sicherheit ergab, dass die beliebtesten Docker-Images mindestens 30 Schwachstellen enthalten.

7. Verwenden Sie COPY statt ADD

Docker bietet zwei Befehle, um beim Erstellen Dateien vom Host in das Docker-Image zu kopieren: COPY und ADD. Die Anweisungen sind ähnlich, unterscheiden sich jedoch in ihrer Funktion. Das kann zu Sicherheitsproblemen im Docker-Container des Images führen:

  • COPY — kopiert lokale Dateien rekursiv, sofern Quell- und Zieldateien oder -verzeichnisse ausdrücklich angegeben sind. Bei COPY müssen Sie die Speicherorte angeben.

  • ADD — kopiert lokale Dateien rekursiv, erstellt das Zielverzeichnis automatisch, falls es noch nicht existiert, und akzeptiert Archive als Quelle – entweder lokal oder über eine Remote-URL. Archive werden im Zielverzeichnis entpackt, Remote-Dateien dorthin heruntergeladen.

Die Unterschiede zwischen ADD und COPY sind subtil, aber wichtig. Machen Sie sich damit vertraut, um potenzielle Sicherheitsprobleme zu vermeiden:

  • Wenn Remote-URLs verwendet werden, um Daten direkt an einen Quellpfad herunterzuladen, kann dies zu Man-in-the-Middle-Angriffen führen, bei denen der Inhalt der heruntergeladenen Datei verändert wird. Außerdem müssen Herkunft und Authentizität von Remote-URLs zusätzlich überprüft werden. Wenn Sie COPY verwenden, muss die Quelle der von Remote-URLs herunterzuladenden Dateien über eine sichere TLS-Verbindung abgerufen und ihre Herkunft ebenfalls überprüft werden.

  • Überlegungen zu Speicherplatz und Image-Layern: Mit COPY können Sie das Hinzufügen eines Archivs von einem Remote-Speicherort und dessen Entpacken auf separate Layer verteilen. So wird der Image-Cache optimiert. Wenn Remote-Dateien benötigt werden, optimiert ein einziger RUN-Befehl, der sie herunterlädt, entpackt und anschließend bereinigt, den Vorgang in einem Layer. Mit ADD wären dafür mehrere Layer erforderlich.

  • Bei lokalen Archiven entpackt ADD diese automatisch in das Zielverzeichnis. Das kann zwar akzeptabel sein, birgt aber das Risiko von Zip-Bomben und Zip-Slip-Schwachstellen, die dadurch automatisch ausgelöst werden könnten.

8. Verwenden Sie Metadaten-Labels

Image-Labels enthalten Metadaten zu dem Image, das Sie erstellen. So können Nutzer leichter nachvollziehen, wie sie das Image verwenden. Der am häufigsten verwendete Label ist „maintainer“. Er gibt den Namen und die E-Mail-Adresse der Person an, die dieses Image betreut. Fügen Sie Metadaten mit folgendem LABEL-Befehl hinzu:

LABEL maintainer="me@acme.com"

Ergänzen Sie neben den Kontaktdaten der zuständigen Person alle Metadaten, die für Sie wichtig sind. Dazu können ein Commit-Hash, ein Link zum entsprechenden Build, der Qualitätsstatus (wurden alle Tests bestanden?), der Quellcode, ein Verweis auf den Speicherort Ihrer SECURITY.TXT-Datei und weitere Angaben gehören.

Es empfiehlt sich, eine SECURITY.TXT-Datei (RFC5785) zu verwenden, die auf Ihre Richtlinie zur verantwortungsvollen Offenlegung für Ihr Docker-Label-Schema verweist, wenn Sie Labels hinzufügen, zum Beispiel:

LABEL securitytxt="https://www.example.com/.well-known/security.txt"

Weitere Informationen zu Labels für Docker-Images finden Sie hier.

9. Verwenden Sie Multi-Stage-Builds für kleine und sichere Docker-Images

Beim Erstellen Ihrer Anwendung mit einer Dockerfile entstehen viele Artefakte, die nur während der Build-Phase benötigt werden. Dazu zählen beispielsweise Entwicklungstools und Bibliotheken, die zum Kompilieren gebraucht werden, Abhängigkeiten für Unit-Tests, temporäre Dateien, Secrets und vieles mehr.

Bleiben diese Artefakte im Basis-Image, das möglicherweise in der Produktion zum Einsatz kommt, wird das Docker-Image größer. Dadurch dauert der Download länger und die Angriffsfläche wächst, weil mehr Pakete installiert sind. Dasselbe gilt für das Docker-Image, das Sie verwenden: Möglicherweise benötigen Sie ein bestimmtes Docker-Image zum Erstellen, aber nicht zum Ausführen des Anwendungscodes.

Golang ist ein gutes Beispiel. Zum Erstellen einer Golang-Anwendung benötigen Sie den Go-Compiler. Dieser erzeugt eine ausführbare Datei, die auf jedem Betriebssystem ohne Abhängigkeiten läuft – auch in Scratch-Images.

Das ist ein guter Grund, warum Docker Multi-Stage-Builds unterstützt. Mit dieser Funktion können Sie im Build-Prozess mehrere temporäre Images verwenden und nur das letzte Image sowie die hineinkopierten Informationen beibehalten. So erhalten Sie zwei Images:

  • Erstes Image – ein sehr großes Image mit zahlreichen Abhängigkeiten, die zum Erstellen Ihrer Anwendung und zum Ausführen von Tests benötigt werden.

  • Zweites Image – ein sehr schlankes Image mit wenigen Bibliotheken, das nur eine Kopie der Artefakte enthält, die zum Ausführen der Anwendung in der Produktion benötigt werden.

10. Verwenden Sie einen Linter

Setzen Sie einen Linter ein, um häufige Fehler zu vermeiden und Best Practices festzulegen, an denen sich Entwickler automatisiert orientieren können. Damit lassen sich Docker-Sicherheitsprobleme statisch analysieren – ein wichtiger Schritt beim Docker-Sicherheitsscanning.

Ein solcher Linter ist hadolint. Er analysiert eine Dockerfile und gibt für jeden Verstoß gegen seine Best-Practice-Regeln eine Warnung aus.

Terminalausgabe eines Hadolint-Scans einer Dockerfile mit Warnungen zu festgelegten Paketversionen, apt-Listen und der Verwendung von COPY statt ADD.

Hadolint ist noch leistungsfähiger, wenn Sie es in einer integrierten Entwicklungsumgebung (IDE) verwenden. Wenn Sie beispielsweise hadolint als VSCode-Erweiterung nutzen, werden Lint-Fehler bereits während der Eingabe angezeigt. So schreiben Sie schneller bessere Dockerfiles.

Container-Sicherheit für DevSecOps

Finden und beheben Sie Container-Schwachstellen kostenlos mit Snyk.

Wie härten Sie ein Docker-Container-Image?

Mit Lintern wie hadolint oder dockle können Sie sicherstellen, dass die Dockerfile sicher konfiguriert ist. Scannen Sie außerdem Ihre Container-Images, um Schwachstellen mit schwerwiegenden Auswirkungen auf die Sicherheit Ihrer Produktions-Container zu vermeiden. 

Stellt Docker ein Sicherheitsrisiko dar?

Docker ist eine Technologie zur Software-Virtualisierung, die sich großer Beliebtheit erfreut und weit verbreitet ist. Beim Erstellen und Bereitstellen von Docker-Images müssen wir bewährte Sicherheitspraktiken berücksichtigen, um Risiken wie Sicherheitslücken in Docker-Basis-Images oder Datenschutzverletzungen durch falsch konfigurierte Docker-Container zu minimieren.

Wie sichere ich einen Docker-Container?

Befolgen Sie die Best Practices für die Docker-Sicherheit, um Docker-Basis-Images mit möglichst wenigen oder keinen bekannten Schwachstellen und sichere Dockerfile-Einstellungen zu verwenden. Überwachen Sie außerdem Ihre bereitgestellten Container, damit sich die Images zwischen Entwicklung und Produktion nicht unbemerkt ändern. Befolgen Sie darüber hinaus die Best Practices für Infrastructure as Code für Lösungen zur Container-Orchestrierung.

Docker-Sicherheit: weitere Ressourcen

Abschließend finden Sie hier weitere Ressourcen, wenn Sie über Best Practices für die Erstellung optimaler Docker-Images für Node.js- und Java-Anwendungen auf dem Laufenden bleiben möchten:

  1. Entwickeln Sie mit Java? Diese Ressource könnte für Sie interessant sein: Docker für Java-Entwickler: 5 Dinge, die Sie wissen müssen, um Sicherheitsprobleme zu vermeiden

  2. 10 Best Practices zum Erstellen eines Java-Containers mit Docker – Ein ausführlicher Leitfaden mit bewährten Methoden zum Erstellen produktionsreifer Container für Java-Anwendungen.

  3. 10 Best Practices zum Containerisieren von Node.js-Webanwendungen mit Docker – Wenn Sie mit Node.js entwickeln, wird Ihnen diese Schritt-für-Schritt-Anleitung gefallen. Sie zeigt, wie Sie leistungsfähige und sichere Docker-Basis-Images für Ihre Node.js-Anwendungen erstellen.

Entdecken Sie den Stand der Open-Source-Sicherheit

Erfahren Sie mehr über aktuelle Trends und Ansätze für Open-Source-Software und Supply-Chain-Sicherheit.