GitLab Container Scanning: Docker-Images direkt in der Pipeline auf Schwachstellen pruefen
AI generated
CI/CD
.yml
GitLab · CI/CD · Container Security
GitLab Container Scanning fuer Docker-Images in der Pipeline
Unterschied zu Trivy und Integration ins Merge-Request-Widget

Ein Docker-Image ist nur so sicher wie sein Basis-Image und die darin installierten System-Pakete, und genau dort verstecken sich viele Schwachstellen, die weder SAST noch Dependency Scanning erfassen, weil beide sich auf Anwendungscode und Sprachpakete konzentrieren. GitLabs Container Scanning schliesst diese Luecke, indem es das fertig gebaute Image direkt in der Pipeline gegen eine Vulnerability-Datenbank prueft. Dieser Artikel zeigt die Integration, den Unterschied zu einem eigenstaendigen Tool wie Trivy und wie die Ergebnisse im Merge-Request-Widget landen.

16 Min. Lesezeit Container Scanning Docker Security Trivy Vulnerability Management

1. Warum Docker-Images eine eigene Scan-Kategorie brauchen

Ein typisches Produktions-Image besteht aus deutlich mehr als dem eigenen Anwendungscode: Es enthaelt ein Basis-Betriebssystem wie Debian oder Alpine, System-Bibliotheken, einen Paketmanager-Layer und haeufig zusaetzliche Tools, die waehrend des Build-Prozesses installiert, aber nie wieder entfernt wurden. Jede dieser Komponenten kann bekannte Sicherheitsluecken enthalten, unabhaengig davon, wie sauber der eigentliche Anwendungscode ist. SAST prueft nur eigenen Quellcode, Dependency Scanning nur Sprachpakete wie Composer- oder npm-Abhaengigkeiten, keines von beiden schaut in die Betriebssystem-Ebene des fertigen Images hinein.

Container Scanning setzt genau hier an und analysiert das gebaute Image als Ganzes, inklusive aller Layer, gegen eine kontinuierlich aktualisierte Datenbank bekannter CVEs fuer Betriebssystem-Pakete. Das ist besonders relevant, weil viele Basis-Images monatelang unveraendert in Produktion laufen, waehrend im Hintergrund neue Schwachstellen fuer genau die darin enthaltenen Paketversionen veroeffentlicht werden. Ein Image, das beim Bauen als sicher galt, kann wenige Wochen spaeter bereits mehrere bekannte, oeffentlich dokumentierte Schwachstellen enthalten, ohne dass sich am eigenen Code oder Dockerfile etwas geaendert haette.

2. Das Container-Scanning-Template in eine bestehende Pipeline einbinden

Die Integration erfolgt ueber include:template mit Jobs/Container-Scanning.gitlab-ci.yml und setzt voraus, dass das zu scannende Image bereits in einer vorherigen Stage gebaut und in eine Registry gepusht wurde, typischerweise die projekteigene GitLab Container Registry. Ueber die Variable CS_IMAGE wird dem Scanner mitgeteilt, welches konkrete Image analysiert werden soll, standardmaessig wird dabei auf den Wert von CI_APPLICATION_REPOSITORY und CI_APPLICATION_TAG zurueckgegriffen, die sich aus dem Projektnamen und der Commit-SHA ableiten, falls keine eigenen Werte gesetzt werden.

Der Scan-Job selbst benoetigt Zugriff auf die Registry, in der das Image liegt, was bei der projekteigenen GitLab Registry automatisch ueber die CI-Job-Token-Authentifizierung funktioniert, bei einer externen Registry aber explizit ueber CS_REGISTRY_USER und CS_REGISTRY_PASSWORD konfiguriert werden muss. Ein haeufiger Fehler ist, den Scan-Job vor dem eigentlichen Push des Images auszufuehren, wodurch der Scanner ein nicht existierendes oder veraltetes Image analysiert. Die needs-Direktive stellt sicher, dass der Scan-Job zuverlaessig erst nach dem erfolgreichen Build- und Push-Job startet.


# .gitlab-ci.yml
stages:
  - build
  - security
  - deploy

build-image:
  stage: build
  script:
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"

include:
  - template: 'Jobs/Container-Scanning.gitlab-ci.yml'

container_scanning:
  stage: security
  variables:
    CS_IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
  needs: ["build-image"]

3. Wie der Analyzer unter der Haube arbeitet

Standardmaessig nutzt GitLabs Container-Scanning-Template intern Trivy als Analyzer-Engine, seit GitLab von der frueheren Grype-Standardeinstellung umgestellt hat. Das Image wird dabei nicht ausgefuehrt, sondern statisch analysiert: Der Scanner extrahiert die Layer, identifiziert installierte Paketversionen ueber die jeweilige Paketmanager-Metadatenbank, etwa dpkg fuer Debian-basierte Images oder apk fuer Alpine, und gleicht diese Liste gegen die Vulnerability-Datenbank ab. Dieser Prozess laeuft vollstaendig innerhalb der Pipeline, ohne dass das Image irgendwo deployed oder gestartet werden muss.

Ergaenzend zur reinen Betriebssystem-Paketpruefung erkennt der Analyzer je nach Konfiguration auch Sprachpaket-Schwachstellen innerhalb des Images, etwa wenn eine composer.lock oder package-lock.json in das finale Image kopiert wurde, was bei mehrstufigen Docker-Builds gelegentlich unbeabsichtigt passiert. In solchen Faellen ueberschneidet sich Container Scanning teilweise mit Dependency Scanning, was in der Praxis meist unproblematisch ist, da beide auf dieselbe zugrunde liegende Schwachstelle hinweisen und die Ergebnisse im Security-Dashboard entsprechend zusammengefuehrt dargestellt werden.

4. Unterschied zu Trivy als eigenstaendigem Tool

Trivy laesst sich auch vollstaendig unabhaengig von GitLabs Templates als eigener CI-Job einsetzen, entweder als Docker-Image oder als direkt installiertes Binary, mit vollem Zugriff auf saemtliche Trivy-eigenen Konfigurationsoptionen, Ausgabeformate und Scan-Modi, die das GitLab-Template nicht alle exponiert. Fuer Teams, die bereits eine etablierte Trivy-basierte Toolchain haben oder spezielle Anforderungen wie das Scannen von Infrastructure-as-Code-Dateien im selben Werkzeug abdecken wollen, ist der eigenstaendige Einsatz oft die flexiblere Wahl.

Der entscheidende Vorteil des GitLab-Templates liegt dagegen in der nahtlosen Integration: Ergebnisse landen automatisch im Merge-Request-Widget und im Security-Dashboard, ohne dass ein eigenes Skript die Trivy-JSON-Ausgabe in das GitLab-Report-Format konvertieren muesste. Bei einem eigenstaendigen Trivy-Job muesste diese Konvertierung manuell erfolgen, etwa ueber trivy image --format template mit einem passenden GitLab-kompatiblen Template, was zusaetzlichen Pflegeaufwand bedeutet. Fuer die meisten Teams ueberwiegt dieser Integrationsvorteil den Flexibilitaetsgewinn eines eigenstaendigen Trivy-Setups deutlich.


# Eigenstaendiger Trivy-Job als Alternative (ohne GitLab-Report-Integration)
trivy image --format table --severity CRITICAL,HIGH \
  --exit-code 1 "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"

5. Ergebnisse im Merge-Request-Widget

Nach einem erfolgreichen Scan-Lauf legt der Job einen Container-Scanning-Report als Artifact ab, den GitLab automatisch erkennt und im Merge-Request-Widget als eigene Sektion neben SAST- und Dependency-Scanning-Findings anzeigt. Jedes gefundene CVE erscheint dort mit Schweregrad, betroffenem Paket, installierter Version und, sofern verfuegbar, der Version, in der die Schwachstelle behoben wurde, sodass Reviewer auf einen Blick sehen, ob ein einfaches Basis-Image-Update das Problem loesen wuerde.

Besonders wertvoll ist die Diff-Ansicht: GitLab vergleicht die Findings des aktuellen Merge Requests automatisch mit dem Scan-Ergebnis des Ziel-Branches und markiert, welche Schwachstellen neu hinzugekommen sind und welche bereits vorher im Basis-Image vorhanden waren. Das verhindert, dass ein Merge Request faelschlicherweise fuer Altlasten verantwortlich gemacht wird, die bereits lange vor der eigenen Aenderung im Image vorhanden waren, und lenkt die Aufmerksamkeit gezielt auf tatsaechlich neu eingefuehrte Risiken.

6. Images aus externen Registries scannen

Nicht jedes Team baut und lagert seine Images ausschliesslich in der projekteigenen GitLab Container Registry. Basis-Images stammen haeufig aus Docker Hub, produktiv genutzte Images liegen mitunter in Amazon ECR oder Google Artifact Registry, und Container Scanning muss auch mit solchen externen Quellen umgehen koennen. Fuer eine externe Registry werden die Zugangsdaten ueber CS_REGISTRY_USER und CS_REGISTRY_PASSWORD als geschuetzte CI/CD-Variablen hinterlegt, waehrend CS_IMAGE die vollstaendige Registry-URL inklusive Tag enthaelt, statt sich wie bei der projekteigenen Registry auf CI_REGISTRY_IMAGE zu verlassen.

Wichtig ist dabei, die Zugangsdaten mit moeglichst eingeschraenkten Rechten zu versehen, idealerweise ein reiner Lesezugriff auf genau das eine Repository, das gescannt werden soll, statt eines administrativen Zugangs auf die gesamte Registry. Bei selbst gehosteten, privaten Registries mit selbstsigniertem Zertifikat kann zusaetzlich die Variable DOCKER_INSECURE oder ein manuell hinterlegtes CA-Zertifikat noetig sein, damit der Scan-Job die TLS-Verbindung erfolgreich aufbauen kann, ohne die generelle Sicherheit der Pipeline durch pauschales Abschalten der Zertifikatspruefung zu untergraben.


# .gitlab-ci.yml: Image aus einer externen Registry scannen
container_scanning:
  variables:
    CS_IMAGE: "registry.example.com/team/app:1.4.2"
    CS_REGISTRY_USER: "$EXTERNAL_REGISTRY_USER"
    CS_REGISTRY_PASSWORD: "$EXTERNAL_REGISTRY_PASSWORD"

7. Die richtige Basis-Image-Strategie als wirksamster Hebel

Die mit Abstand wirksamste Massnahme gegen Container-Scanning-Findings ist nicht das Scannen selbst, sondern die bewusste Wahl und Pflege des Basis-Images. Schlanke, spezialisierte Images wie Alpine-basierte Varianten oder distroless Images von Google enthalten von vornherein deutlich weniger installierte Pakete und damit eine kleinere Angriffsflaeche als ein volles Ubuntu- oder Debian-Image mit allen Standardwerkzeugen. Wo immer die Anwendung es zulaesst, reduziert ein schlankeres Basis-Image die Zahl der Findings oft drastischer als jede nachtraegliche Konfiguration des Scanners.

Ebenso wichtig ist, Basis-Images regelmaessig zu aktualisieren, statt einmal einen funktionierenden Tag zu fixieren und diesen jahrelang unveraendert zu lassen. Ein woechentlicher, per Scheduled Pipeline ausgeloester Rebuild mit dem jeweils aktuellen Basis-Image-Patch-Level zieht automatisch alle seither veroeffentlichten Sicherheitsfixes des Betriebssystem-Layers, ohne dass eine Aenderung am eigenen Dockerfile noetig waere. Diese Kombination aus schlankem Basis-Image und regelmaessigem Rebuild reduziert die Zahl der Container-Scanning-Findings in der Praxis meist um eine Groessenordnung.

8. Schwellenwerte, Ausnahmen und der Umgang mit unfixbaren Findings

Nicht jede gemeldete Schwachstelle hat bereits eine verfuegbare Fix-Version, insbesondere bei aelteren oder weniger aktiv gepflegten Basis-Images. Fuer solche Faelle bietet GitLab die Moeglichkeit, Findings ueber eine .gitlab/security-policies-Datei oder direkt im Security-Dashboard als vorlaeufig akzeptiertes Risiko zu markieren, mit Ablaufdatum, damit die Ausnahme nicht dauerhaft unbemerkt bestehen bleibt, sondern regelmaessig neu bewertet werden muss.

Fuer produktionskritische Images empfiehlt sich zudem eine Scan Result Policy, die Deployments mit ungeloesten Critical-Findings ohne dokumentierte Ausnahme blockiert, kombiniert mit einer klar definierten Eskalationsfrist, etwa dass ein Critical-Finding innerhalb von 72 Stunden entweder behoben oder mit Begruendung als Ausnahme dokumentiert werden muss. Diese Kombination aus technischer Durchsetzung und organisatorischem Prozess verhindert, dass Container Scanning zu reiner Kosmetik im Merge-Request-Widget verkommt, ohne tatsaechliche Verhaltensaenderung zu bewirken.


# .gitlab-ci.yml: nur Critical- und High-Findings sollen den Job scheitern lassen
container_scanning:
  variables:
    CS_SEVERITY_THRESHOLD: "HIGH"

9. Best Practices und Vergleich der Ansaetze

In der Praxis bewaehrt sich, Container Scanning fest als Pflichtschritt zwischen Image-Build und Deploy-Stage zu verankern, statt es als optionalen, leicht uebersehbaren Zusatzjob zu behandeln. Kombiniert mit einer klaren Basis-Image-Strategie, regelmaessigen Rebuilds und einer dokumentierten Ausnahme-Regelung fuer unfixbare Findings entsteht ein Prozess, der Container-Schwachstellen systematisch statt zufaellig behandelt.

Die Wahl zwischen dem GitLab-Template und einem eigenstaendigen Trivy-Einsatz haengt letztlich davon ab, wie stark die native Merge-Request-Integration gewichtet wird gegenueber der vollen Konfigurationsflexibilitaet eines eigenstaendigen Tools. Die folgende Tabelle stellt beide Ansaetze anhand ihrer wichtigsten Eigenschaften gegenueber, um die Entscheidung fuer das eigene Projekt zu erleichtern.

Kriterium GitLab Container Scanning Template Eigenstaendiges Trivy
Einrichtung Ein include:template Eintrag Eigener Job inklusive Ausgabekonvertierung
MR-Widget-Integration Automatisch Nur mit manueller Report-Konvertierung
Konfigurationsflexibilitaet Eingeschraenkt auf CS_ Variablen Voller Zugriff auf alle Trivy-Optionen
Security-Dashboard Automatisch aggregiert Nicht ohne Zusatzaufwand
IaC-Scanning im selben Tool Nicht enthalten Moeglich ueber trivy config

Mironsoft

CI/CD-Pipelines, Zero-Downtime-Deployments und Release-Automatisierung

Deployments, die ohne Ausfallzeit und ohne Nervenkitzel laufen?

Wir prüfen bestehende GitLab-Pipelines auf fragile Deployment-Schritte und fehlende Absicherung und bauen daraus einen Release-Prozess mit Zero-Downtime-Deployments, automatisierten Checks und einem Rollback, dem ihr im Ernstfall vertrauen könnt.

Pipeline-Review

Bestehende .gitlab-ci.yml auf Fragilität, fehlende Stages und Sicherheitslücken prüfen.

Zero-Downtime-Deployment

Symlink-Releases, Health-Checks und Rollback-Strategien für Magento-Shops aufbauen.

CI/CD-Automatisierung

Tests, Security-Scans und Deployments zu einer zuverlässigen Pipeline verbinden.

10. Zusammenfassung

GitLab Container Scanning: Das Wichtigste auf einen Blick

Eigene Scan-Kategorie

Container Scanning prueft die Betriebssystem-Ebene des Images, die SAST und Dependency Scanning nicht abdecken.

Einfache Integration

include:template plus CS_IMAGE reicht aus, needs stellt korrekte Reihenfolge nach dem Image-Push sicher.

Basis-Image ist der Hebel

Ein schlankes, regelmaessig neu gebautes Basis-Image reduziert Findings staerker als jede Scanner-Konfiguration.

Diff statt Vollbild

GitLab zeigt neu hinzugekommene Findings getrennt von bereits im Basis-Image vorhandenen an.

11. FAQ: GitLab Container Scanning: Das Wichtigste auf einen Blick

1Was prueft GitLab Container Scanning konkret?
Es analysiert ein fertig gebautes Docker-Image inklusive aller Layer auf bekannte Schwachstellen in installierten Betriebssystem-Paketen, ergaenzt teilweise um Sprachpaket-Findings, falls entsprechende Manifestdateien im finalen Image enthalten sind.
2Muss das Image vor dem Scan in eine Registry gepusht werden?
Ja, der Scan-Job benoetigt ein bereits in eine Registry gepushtes Image, referenziert ueber die Variable CS_IMAGE. Die needs-Direktive stellt sicher, dass der Scan erst nach dem erfolgreichen Push-Job startet.
3Welchen Analyzer nutzt GitLab intern fuer Container Scanning?
Standardmaessig Trivy, nach der Umstellung von der frueheren Grype-Standardeinstellung. Der Analyzer extrahiert Paketmetadaten aus den Image-Layern und gleicht sie gegen eine Vulnerability-Datenbank ab.
4Was ist der Hauptvorteil des GitLab-Templates gegenueber eigenstaendigem Trivy?
Die nahtlose Integration ins Merge-Request-Widget und ins Security-Dashboard ohne manuelle Konvertierung der Trivy-Ausgabe in ein kompatibles Report-Format, was bei einem eigenstaendigen Trivy-Job zusaetzlichen Pflegeaufwand bedeutet.
5Wann lohnt sich trotzdem ein eigenstaendiger Trivy-Einsatz?
Wenn volle Konfigurationsflexibilitaet benoetigt wird, etwa spezielle Ausgabeformate, oder wenn im selben Werkzeug zusaetzlich Infrastructure-as-Code-Dateien gescannt werden sollen, was das GitLab-Template nicht abdeckt.
6Wie reduziere ich die Zahl der Findings am effektivsten?
Durch ein schlankes Basis-Image wie eine Alpine- oder distroless-Variante mit weniger installierten Paketen sowie durch regelmaessige, zum Beispiel woechentliche Rebuilds, die automatisch die aktuellen Sicherheitsfixes des Basis-Images uebernehmen.
7Was passiert, wenn eine Schwachstelle noch keine Fix-Version hat?
Solche Findings lassen sich als vorlaeufig akzeptiertes Risiko mit Ablaufdatum dokumentieren, damit die Ausnahme regelmaessig neu bewertet wird, statt dauerhaft unbemerkt zu bestehen.
8Wie unterscheidet GitLab neue von bereits bestehenden Findings?
Ueber eine automatische Diff-Ansicht im Merge-Request-Widget, die die Scan-Ergebnisse des Merge Requests mit dem Scan-Ergebnis des Ziel-Branches vergleicht und neu hinzugekommene Schwachstellen separat markiert.
9Kann ich einstellen, dass nur Critical-Findings den Job scheitern lassen?
Ja, ueber die Variable CS_SEVERITY_THRESHOLD, die einen minimalen Schweregrad definiert, ab dem der Job als fehlgeschlagen gilt, zum Beispiel HIGH fuer High- und Critical-Findings.
10Ueberschneidet sich Container Scanning mit Dependency Scanning?
Teilweise, wenn Sprachpaket-Manifeste versehentlich im finalen Image landen, etwa bei nicht sauber getrennten mehrstufigen Docker-Builds. Beide Analysen zeigen dann denselben zugrunde liegenden Fund, was im Security-Dashboard entsprechend zusammengefuehrt dargestellt wird.