
Dockle détecte les erreurs de configuration dans vos images Docker en vérifiant leur conformité avec le benchmark CIS Docker et les bonnes pratiques de sécurité. Contrairement à Trivy qui scanne les vulnérabilités des paquets, Dockle se concentre sur la construction de l'image : utilisateur root, secrets exposés, cache non nettoyé, absence de HEALTHCHECK. En 30 secondes, vous savez si votre image respecte les standards de sécurité.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Installer Dockle sur Linux ou macOS
- Analyser une image Docker et comprendre les résultats
- Interpréter les codes CIS (CIS-DI-0001, DKL-DI-0005, etc.)
- Personnaliser l'analyse avec les options essentielles
- Intégrer Dockle dans un pipeline CI/CD (GitLab CI, GitHub Actions)
- Corriger les problèmes les plus fréquents
Qu'est-ce que Dockle ?
Section intitulée « Qu'est-ce que Dockle ? »Dockle est un linter de sécurité pour images Docker. Il vérifie que votre image respecte les recommandations du CIS Docker Benchmark, un standard reconnu en sécurité des conteneurs.
Ce que Dockle vérifie
Section intitulée « Ce que Dockle vérifie »Dockle inspecte l'image construite, pas le Dockerfile source. Il ouvre chaque couche et cherche des configurations à risque. Les cinq catégories ci-dessous couvrent l'essentiel de ses contrôles ; retenez surtout que Dockle attrape des problèmes invisibles dans le Dockerfile, comme un secret hérité d'une image de base ou un cache laissé par une couche intermédiaire.
| Catégorie | Exemples de contrôles |
|---|---|
| Utilisateur | Image qui tourne en root ? |
| Secrets | Variables d'environnement sensibles (PASSWORD, TOKEN) ? |
| Fichiers | Clés SSH, certificats privés dans l'image ? |
| Cache | Cache apt/yum non nettoyé ? |
| Bonnes pratiques | HEALTHCHECK présent ? Tag latest utilisé ? |
Dockle vs Trivy vs Hadolint
Section intitulée « Dockle vs Trivy vs Hadolint »| Outil | Analyse | Quand l'utiliser |
|---|---|---|
| Dockle | Configuration de l'image finale | Après le build, avant le push |
| Trivy | Vulnérabilités des paquets (CVE) | Après le build, avant le push |
| Hadolint | Syntaxe du Dockerfile | Pendant l'écriture du Dockerfile |
Installation de Dockle
Section intitulée « Installation de Dockle »VERSION=$( curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \ grep '"tag_name":' | \ sed -E 's/.*"v([^"]+)".*/\1/')curl -L -o dockle.deb \ "https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.deb"sudo dpkg -i dockle.deb && rm dockle.debVERSION=$( curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \ grep '"tag_name":' | \ sed -E 's/.*"v([^"]+)".*/\1/')sudo rpm -ivh \ "https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.rpm"Avec Homebrew :
brew install goodwithtech/r/dockleAvec apk :
VERSION=$( curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \ grep '"tag_name":' | \ sed -E 's/.*"v([^"]+)".*/\1/')curl -L -o dockle.apk \ "https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.apk"apk add --allow-untrusted dockle.apk && rm dockle.apkVérification :
dockle --version# dockle version 0.4.15Premier scan avec Dockle
Section intitulée « Premier scan avec Dockle »Analyser une image
Section intitulée « Analyser une image »La commande de base est simple :
dockle NOM_IMAGE:TAGExemple avec une image problématique :
Voici un Dockerfile volontairement mal configuré :
FROM ubuntu:26.04@sha256:3131b4cc82a783df6c9df078f86e01819a13594b865c2cad47bd1bca2b7063bbENV ADMIN_PASSWORD=secret123RUN apt-get update && apt-get install -y curlEXPOSE 8080CMD ["echo", "Hello"]Après construction (docker build -t test-bad:v1 .), le scan Dockle révèle :
dockle test-bad:v1FATAL - CIS-DI-0010: Do not store credential in environment variables/files * Suspicious ENV key found : ADMIN_PASSWORD on ENV ADMIN_PASSWORD=*******
FATAL - DKL-DI-0005: Clear apt-get caches * Use 'rm -rf /var/lib/apt/lists' after 'apt-get install|update'
WARN - CIS-DI-0001: Create a user for the container * Last user should not be root
INFO - CIS-DI-0005: Enable Content trust for Docker * export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image * not found HEALTHCHECK statement
INFO - CIS-DI-0008: Confirm safety of setuid/setgid files * setuid file: urwxr-xr-x usr/bin/passwd * setuid file: urwxr-xr-x usr/bin/su [...] # Fichiers système normauxComprendre les niveaux de gravité
Section intitulée « Comprendre les niveaux de gravité »Chaque ligne de résultat commence par un niveau, et c'est lui qui décide de votre réaction. Concentrez-vous d'abord sur les FATAL : ce sont les seuls qui doivent bloquer une mise en production. Un WARN mérite correction mais n'est pas rédhibitoire, tandis qu'un INFO relève souvent de l'image de base et non de votre Dockerfile. C'est aussi cette échelle que vous passerez en argument à --exit-level pour choisir le seuil qui fait échouer un pipeline.
| Niveau | Signification | Action |
|---|---|---|
| FATAL | Faille de sécurité critique | Corriger obligatoirement |
| WARN | Configuration risquée | Corriger fortement recommandé |
| INFO | Amélioration possible | Évaluer selon le contexte |
| PASS | Contrôle réussi | Rien à faire |
Sortie JSON pour automatisation
Section intitulée « Sortie JSON pour automatisation »La sortie colorée est faite pour l'oeil humain ; pour un traitement automatisé, demandez du JSON avec --format json. Le bloc summary donne d'emblée le compte par niveau, ce qui permet à un script de décider s'il bloque le pipeline sans analyser le détail. Le tableau details reprend chaque contrôle échoué avec son code et ses alertes, exploitable pour produire un rapport ou alimenter un tableau de bord.
dockle --format json test-bad:v1{ "image": "test-bad:v1", "summary": { "fatal": 2, "warn": 1, "info": 3, "skip": 0, "pass": 10 }, "details": [ { "code": "CIS-DI-0010", "title": "Do not store credential in environment variables/files", "level": "FATAL", "alerts": [ "Suspicious ENV key found : ADMIN_PASSWORD on ENV ADMIN_PASSWORD=*******" ] } ]}Comprendre les codes de vérification
Section intitulée « Comprendre les codes de vérification »Dockle utilise deux familles de codes :
- CIS-DI-XXXX : Règles du CIS Docker Benchmark (standard industriel)
- DKL-DI-XXXX : Règles spécifiques à Dockle (bonnes pratiques)
Codes CIS les plus importants
Section intitulée « Codes CIS les plus importants »Ces cinq codes reviennent dans la quasi-totalité des scans. Deux méritent une lecture attentive avant d'agir. CIS-DI-0005 (Content Trust) se règle par une variable d'environnement au moment du pull ou du build, pas dans l'image elle-même : c'est un réglage de votre poste ou de votre runner. CIS-DI-0008 (setuid/setgid) remonte presque toujours des binaires système légitimes comme passwd ou su ; ne le corrigez que si le fichier signalé n'a rien à faire dans une image applicative.
| Code | Règle | Comment corriger |
|---|---|---|
| CIS-DI-0001 | Ne pas utiliser root | Ajouter USER appuser |
| CIS-DI-0005 | Activer Content Trust | export DOCKER_CONTENT_TRUST=1 |
| CIS-DI-0006 | Ajouter HEALTHCHECK | HEALTHCHECK CMD curl -f http://localhost/ |
| CIS-DI-0008 | Vérifier setuid/setgid | Supprimer les bits avec chmod |
| CIS-DI-0010 | Pas de secrets en clair | Utiliser des secrets Docker ou variables d'exécution |
Codes Dockle spécifiques
Section intitulée « Codes Dockle spécifiques »Les codes préfixés DKL-DI sont propres à Dockle et ne figurent pas dans le benchmark CIS ; ils encodent des habitudes d'écriture de Dockerfile éprouvées. Le plus courant, DKL-DI-0003, sanctionne l'usage du tag latest d'une image de base, qui rend un build non reproductible : la même commande peut produire deux images différentes à un mois d'écart. DKL-DI-0006 préfère COPY à ADD parce que ADD déballe silencieusement les archives et télécharge des URL, deux comportements rarement souhaités.
| Code | Règle | Comment corriger |
|---|---|---|
| DKL-DI-0001 | Éviter sudo | Utiliser USER root puis USER appuser |
| DKL-DI-0002 | Éviter fichiers sensibles | Ajouter au .dockerignore |
| DKL-DI-0003 | Éviter latest | Utiliser un tag versionné |
| DKL-DI-0004 | Utiliser --no-cache (apk) | apk add --no-cache pkg |
| DKL-DI-0005 | Nettoyer le cache apt | rm -rf /var/lib/apt/lists/* |
| DKL-DI-0006 | Utiliser COPY plutôt que ADD | Remplacer ADD par COPY |
Options essentielles
Section intitulée « Options essentielles »Contrôler le code de sortie
Section intitulée « Contrôler le code de sortie »Par défaut, Dockle retourne toujours 0. Pour échouer en CI/CD :
# Échoue si WARN ou FATAL détectédockle --exit-code 1 mon-image:v1
# Échoue uniquement sur FATALdockle --exit-code 1 --exit-level FATAL mon-image:v1Ignorer des règles
Section intitulée « Ignorer des règles »Certaines règles peuvent ne pas s'appliquer à votre contexte :
# Ignorer une règle spécifiquedockle --ignore CIS-DI-0005 mon-image:v1
# Ignorer plusieurs règlesdockle -i CIS-DI-0005 -i CIS-DI-0008 mon-image:v1Personnaliser la détection de secrets
Section intitulée « Personnaliser la détection de secrets »Dockle détecte automatiquement les variables sensibles (PASSWORD, TOKEN, KEY...). Vous pouvez personnaliser cette détection :
# Accepter une variable normalement suspectedockle --accept-key GPG_KEY --accept-key CACHE_KEY mon-image:v1
# Ajouter des mots sensibles personnalisésdockle --sensitive-word api_secret --sensitive-word db_pass mon-image:v1
# Ajouter des fichiers sensibles personnalisésdockle --sensitive-file .git --sensitive-file .env mon-image:v1
# Ajouter des extensions sensibles personnaliséesdockle --sensitive-file-extension pfx --sensitive-file-extension p12 mon-image:v1Formats de sortie
Section intitulée « Formats de sortie »Le format se choisit selon le destinataire de la sortie. Le texte coloré sert à l'inspection manuelle, le JSON à vos propres scripts, et le SARIF à l'intégration avec les plateformes de sécurité. SARIF (Static Analysis Results Interchange Format) est le format standard que GitHub Security et SonarQube savent afficher directement dans leur interface : c'est lui qu'on produit en CI pour voir les alertes Dockle remonter à côté des autres analyses.
# Sortie par défaut (texte coloré)dockle mon-image:v1
# JSON pour parsing automatisédockle --format json mon-image:v1
# SARIF pour outils de sécurité (GitHub Security, SonarQube...)dockle --format sarif mon-image:v1 > dockle-results.sarifAnalyser une image distante
Section intitulée « Analyser une image distante »Dockle n'a pas besoin de télécharger l'image au préalable : il sait lire directement une image publiée dans un registre. C'est utile pour auditer une image déjà en production sans la reconstruire. L'option --username/--password gère l'authentification aux registres privés, et --insecure autorise un registre interne servi en HTTP ou avec un certificat auto-signé, à réserver aux réseaux de confiance.
# Depuis un registre (nécessite authentification)dockle --username user --password pass registry.example.com/mon-image:v1
# Connexion non sécurisée (pour registres internes)dockle --insecure registry.internal:5000/mon-image:v1Intégration CI/CD
Section intitulée « Intégration CI/CD »GitLab CI
Section intitulée « GitLab CI »dockle_scan: stage: test image: docker:27.5@sha256:aa3df78ecf320f5fafdce71c659f1629e96e9de0968305fe1de670e0ca9176ce services: - docker:27.5-dind variables: DOCKLE_VERSION: "0.4.15" before_script: - apk add --no-cache curl - | curl -L -o /usr/local/bin/dockle \ "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit" - chmod +x /usr/local/bin/dockle script: - docker build -t $CI_PROJECT_NAME:$CI_COMMIT_SHA . - dockle --exit-code 1 --exit-level WARN $CI_PROJECT_NAME:$CI_COMMIT_SHA rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event"GitHub Actions
Section intitulée « GitHub Actions »Sur GitHub, le scan Dockle s'exécute après le build et pousse son rapport SARIF dans l'onglet Security du dépôt. Trois réglages de sécurité sont indispensables ici. Le workflow part de permissions: {} et le job ne se voit accorder que security-events: write, nécessaire à l'envoi du SARIF, plus contents: read pour le checkout. Le persist-credentials: false empêche le checkout de laisser le GITHUB_TOKEN dans .git/config. Enfin les deux actions tierces sont épinglées par SHA de commit, un tag mobile comme v3 pouvant être redéployé sur un autre code.
name: Dockle Security Scan
on: push: branches: [main] pull_request: branches: [main]
permissions: {}
jobs: dockle: runs-on: ubuntu-24.04 permissions: contents: read security-events: write steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false
- name: Build image run: docker build -t app:${{ github.sha }} .
- name: Install Dockle env: DOCKLE_VERSION: "0.4.15" run: | curl -L -o dockle.deb \ "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb" sudo dpkg -i dockle.deb
- name: Run Dockle run: dockle --exit-code 1 --format sarif -o dockle-results.sarif app:${{ github.sha }}
- name: Upload SARIF uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 with: sarif_file: dockle-results.sarifExemple de Dockerfile conforme
Section intitulée « Exemple de Dockerfile conforme »Voici un Dockerfile qui passe tous les contrôles Dockle :
FROM ubuntu:24.04@sha256:4fbb8e6a8395de5a7550b33509421a2bafbc0aab6c06ba2cef9ebffbc7092d90
# Installer les dépendances et nettoyer le cacheRUN apt-get update && \ apt-get install -y --no-install-recommends curl && \ rm -rf /var/lib/apt/lists/*
# Créer un utilisateur non-rootRUN useradd -m -s /bin/bash appuser
WORKDIR /app
# Changer vers l'utilisateur non-rootUSER appuser
# Ajouter un healthcheckHEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost:8080/health || exit 1
EXPOSE 8080CMD ["./app"]Résultat Dockle :
dockle app-conforme:v1INFO - CIS-DI-0005: Enable Content trust for Docker * export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0008: Confirm safety of setuid/setgid files * setuid file: urwxr-xr-x usr/bin/passwd [...] # Fichiers système normaux de l'image de baseSeuls des INFO restent, liés à l'image de base Ubuntu. Aucun FATAL ni WARN.
Dépannage
Section intitulée « Dépannage »Problèmes courants
Section intitulée « Problèmes courants »Deux catégories d'erreurs se distinguent dans ce tableau. Les trois premières lignes sont des résultats d'analyse attendus : Dockle fait son travail et signale une vraie configuration à risque, la solution est de corriger l'image. Les deux dernières sont des problèmes d'exécution de Dockle lui-même, un dépassement de délai ou un accès refusé au démon Docker, sans rapport avec la sécurité de l'image. Identifiez d'abord dans quelle catégorie vous êtes avant de chercher la solution.
| Symptôme | Cause probable | Solution |
|---|---|---|
FATAL CIS-DI-0010 | Variable sensible détectée | Utiliser --accept-key ou supprimer la variable |
FATAL DKL-DI-0005 | Cache apt non nettoyé | Ajouter rm -rf /var/lib/apt/lists/* |
WARN CIS-DI-0001 | Image tourne en root | Ajouter USER nonroot |
timeout exceeded | Image trop volumineuse | Utiliser --timeout 5m |
permission denied | Socket Docker inaccessible | Vérifier les droits sur /var/run/docker.sock |
Variables d'environnement
Section intitulée « Variables d'environnement »Toutes les options peuvent être passées via variables d'environnement :
| Variable | Équivalent option |
|---|---|
DOCKLE_IGNORES | --ignore |
DOCKLE_ACCEPT_KEYS | --accept-key |
DOCKLE_EXIT_CODE | --exit-code |
DOCKLE_EXIT_LEVEL | --exit-level |
DOCKLE_OUTPUT_FORMAT | --format |
DOCKLE_TIMEOUT | --timeout |
export DOCKLE_IGNORES="CIS-DI-0005,CIS-DI-0008"export DOCKLE_EXIT_CODE=1dockle mon-image:v1À retenir
Section intitulée « À retenir »-
Dockle analyse la configuration, pas les vulnérabilités, utilisez-le avec Trivy
-
FATAL et WARN doivent être corrigés avant mise en production
-
Toujours spécifier
--exit-code 1en CI/CD pour bloquer les images non conformes -
Pinnez la version de Dockle dans vos pipelines pour la reproductibilité
-
Utilisez
.dockleignorepour ignorer les règles non applicables à votre contexte -
Les codes CIS-DI sont des standards reconnus, leur respect facilite les audits de sécurité
-
Combinez Hadolint + Dockle + Trivy pour une couverture complète
Prochaines étapes
Section intitulée « Prochaines étapes »Plus d'infos
Section intitulée « Plus d'infos »Questions fréquentes
Section intitulée « Questions fréquentes »- Dockle analyse la configuration de l'image : utilisateur root, secrets exposés, cache non nettoyé, absence de HEALTHCHECK
- Trivy scanne les vulnérabilités CVE dans les paquets installés
- Ne pas exécuter les conteneurs en root
- Activer Docker Content Trust
- Ajouter des HEALTHCHECK
- Ne pas stocker de secrets dans l'image
| Niveau | Signification | Action |
|---|---|---|
| FATAL | Faille critique | Corriger obligatoirement |
| WARN | Configuration risquée | Corriger fortement recommandé |
| INFO | Amélioration possible | Évaluer selon contexte |
| PASS | Contrôle réussi | Rien à faire |
--exit-code 1 pour bloquer sur FATAL/WARN.dockle --ignore CIS-DI-0005 -i CIS-DI-0008 mon-image:v1
2. Avec un fichier .dockleignore :CIS-DI-0005
CIS-DI-0008
Dockle lira automatiquement ce fichier à la racine du projet.- Installer Dockle dans le job (ou utiliser une image Docker pré-configurée)
- Builder l'image Docker
- Scanner avec
--exit-code 1pour échouer si des problèmes sont détectés
# GitLab CI exemple
script:
- docker build -t app:$CI_COMMIT_SHA .
- dockle --exit-code 1 app:$CI_COMMIT_SHA
Important : pinnez toujours la version de Dockle pour la reproductibilité.- Supprimer la variable du Dockerfile et la passer au runtime :
docker run -e API_KEY=xxx mon-image - Utiliser Docker Secrets pour les données sensibles
- Si la variable est un faux positif, l'accepter :
dockle --accept-key GPG_KEY mon-image:v1
# Créer un utilisateur
RUN useradd -m -s /bin/bash appuser
# Changer vers cet utilisateur (à la fin du Dockerfile)
USER appuser
Assurez-vous que l'instruction USER est après toutes les commandes nécessitant root (apt install, etc.).RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
Pour Alpine avec apk :RUN apk add --no-cache curl
dockle --format sarif -o dockle-results.sarif mon-image:v1
Dans GitHub Actions, uploadez le fichier avec :- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: dockle-results.sarif
Les résultats apparaîtront dans l'onglet Security de votre repo..env sont également détectés.Pour ajouter vos propres fichiers sensibles :# Fichiers spécifiques
dockle --sensitive-file .git --sensitive-file config.secret mon-image:v1
# Extensions spécifiques
dockle --sensitive-file-extension pfx --sensitive-file-extension p12 mon-image:v1
Ces options déclenchent une alerte si les fichiers sont trouvés dans l'image.