Aller au contenu
Sécurité medium

Auditer la sécurité de vos images Docker avec Dockle

18 min de lecture

logo dockle

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é.

  • 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

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.

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égorieExemples de contrôles
UtilisateurImage qui tourne en root ?
SecretsVariables d'environnement sensibles (PASSWORD, TOKEN) ?
FichiersClés SSH, certificats privés dans l'image ?
CacheCache apt/yum non nettoyé ?
Bonnes pratiquesHEALTHCHECK présent ? Tag latest utilisé ?
OutilAnalyseQuand l'utiliser
DockleConfiguration de l'image finaleAprès le build, avant le push
TrivyVulnérabilités des paquets (CVE)Après le build, avant le push
HadolintSyntaxe du DockerfilePendant l'écriture du Dockerfile
Fenêtre de terminal
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.deb

Vérification :

Fenêtre de terminal
dockle --version
# dockle version 0.4.15

La commande de base est simple :

Fenêtre de terminal
dockle NOM_IMAGE:TAG

Exemple avec une image problématique :

Voici un Dockerfile volontairement mal configuré :

FROM ubuntu:26.04@sha256:3131b4cc82a783df6c9df078f86e01819a13594b865c2cad47bd1bca2b7063bb
ENV ADMIN_PASSWORD=secret123
RUN apt-get update && apt-get install -y curl
EXPOSE 8080
CMD ["echo", "Hello"]

Après construction (docker build -t test-bad:v1 .), le scan Dockle révèle :

Fenêtre de terminal
dockle test-bad:v1
FATAL - 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 normaux

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.

NiveauSignificationAction
FATALFaille de sécurité critiqueCorriger obligatoirement
WARNConfiguration risquéeCorriger fortement recommandé
INFOAmélioration possibleÉvaluer selon le contexte
PASSContrôle réussiRien à faire

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.

Fenêtre de terminal
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=*******"
]
}
]
}

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)

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.

CodeRègleComment corriger
CIS-DI-0001Ne pas utiliser rootAjouter USER appuser
CIS-DI-0005Activer Content Trustexport DOCKER_CONTENT_TRUST=1
CIS-DI-0006Ajouter HEALTHCHECKHEALTHCHECK CMD curl -f http://localhost/
CIS-DI-0008Vérifier setuid/setgidSupprimer les bits avec chmod
CIS-DI-0010Pas de secrets en clairUtiliser des secrets Docker ou variables d'exécution

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.

CodeRègleComment corriger
DKL-DI-0001Éviter sudoUtiliser USER root puis USER appuser
DKL-DI-0002Éviter fichiers sensiblesAjouter au .dockerignore
DKL-DI-0003Éviter latestUtiliser un tag versionné
DKL-DI-0004Utiliser --no-cache (apk)apk add --no-cache pkg
DKL-DI-0005Nettoyer le cache aptrm -rf /var/lib/apt/lists/*
DKL-DI-0006Utiliser COPY plutôt que ADDRemplacer ADD par COPY

Par défaut, Dockle retourne toujours 0. Pour échouer en CI/CD :

Fenêtre de terminal
# Échoue si WARN ou FATAL détecté
dockle --exit-code 1 mon-image:v1
# Échoue uniquement sur FATAL
dockle --exit-code 1 --exit-level FATAL mon-image:v1

Certaines règles peuvent ne pas s'appliquer à votre contexte :

Fenêtre de terminal
# Ignorer une règle spécifique
dockle --ignore CIS-DI-0005 mon-image:v1
# Ignorer plusieurs règles
dockle -i CIS-DI-0005 -i CIS-DI-0008 mon-image:v1

Dockle détecte automatiquement les variables sensibles (PASSWORD, TOKEN, KEY...). Vous pouvez personnaliser cette détection :

Fenêtre de terminal
# Accepter une variable normalement suspecte
dockle --accept-key GPG_KEY --accept-key CACHE_KEY mon-image:v1
# Ajouter des mots sensibles personnalisés
dockle --sensitive-word api_secret --sensitive-word db_pass mon-image:v1
# Ajouter des fichiers sensibles personnalisés
dockle --sensitive-file .git --sensitive-file .env mon-image:v1
# Ajouter des extensions sensibles personnalisées
dockle --sensitive-file-extension pfx --sensitive-file-extension p12 mon-image:v1

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.

Fenêtre de terminal
# 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.sarif

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.

Fenêtre de terminal
# 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:v1
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"

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.sarif

Voici un Dockerfile qui passe tous les contrôles Dockle :

FROM ubuntu:24.04@sha256:4fbb8e6a8395de5a7550b33509421a2bafbc0aab6c06ba2cef9ebffbc7092d90
# Installer les dépendances et nettoyer le cache
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
# Créer un utilisateur non-root
RUN useradd -m -s /bin/bash appuser
WORKDIR /app
# Changer vers l'utilisateur non-root
USER appuser
# Ajouter un healthcheck
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["./app"]

Résultat Dockle :

Fenêtre de terminal
dockle app-conforme:v1
INFO - 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 base

Seuls des INFO restent, liés à l'image de base Ubuntu. Aucun FATAL ni WARN.

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ômeCause probableSolution
FATAL CIS-DI-0010Variable sensible détectéeUtiliser --accept-key ou supprimer la variable
FATAL DKL-DI-0005Cache apt non nettoyéAjouter rm -rf /var/lib/apt/lists/*
WARN CIS-DI-0001Image tourne en rootAjouter USER nonroot
timeout exceededImage trop volumineuseUtiliser --timeout 5m
permission deniedSocket Docker inaccessibleVérifier les droits sur /var/run/docker.sock

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
Fenêtre de terminal
export DOCKLE_IGNORES="CIS-DI-0005,CIS-DI-0008"
export DOCKLE_EXIT_CODE=1
dockle mon-image:v1
  1. Dockle analyse la configuration, pas les vulnérabilités, utilisez-le avec Trivy

  2. FATAL et WARN doivent être corrigés avant mise en production

  3. Toujours spécifier --exit-code 1 en CI/CD pour bloquer les images non conformes

  4. Pinnez la version de Dockle dans vos pipelines pour la reproductibilité

  5. Utilisez .dockleignore pour ignorer les règles non applicables à votre contexte

  6. Les codes CIS-DI sont des standards reconnus, leur respect facilite les audits de sécurité

  7. Combinez Hadolint + Dockle + Trivy pour une couverture complète

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn