Sécurité des API 2025 : Guide Complet OWASP Top 10
Guide complet de sécurité des API basé sur l'OWASP API Security Top 10 : authentication, authorization, protection contre les vulnérabilités et meilleures pratiques 2025.
Guide complet des meilleures pratiques Docker pour 2025 : sécurité, performance et optimisation des images pour la production.
Docker a considérablement évolué depuis ses débuts. En 2025, c’est une plateforme de production sophistiquée qui nécessite des workflows modernes et des bonnes pratiques actualisées. Ce guide complet vous présente les 42 meilleures pratiques essentielles pour sécuriser, optimiser et maintenir vos conteneurs Docker.
Pourquoi c’est critique : Exécuter des conteneurs en tant qu’utilisateur root augmente considérablement les risques d’escalade de privilèges. Si un attaquant compromet votre conteneur, il obtient des droits administratifs.
Solution :
# Créer un utilisateur non-privilégié
RUN addgroup -g 1001 -S appgroup &&
adduser -u 1001 -S appuser -G appgroup
# Basculer vers cet utilisateur
USER appuser
Utilisez des outils comme Trivy ou Docker Scout pour analyser régulièrement vos images. Ces outils détectent les vulnérabilités connues dans vos dépendances et composants système.
# Installation de Trivy
docker run aquasec/trivy image votre-image:tag
# Utilisation de Docker Scout
docker scout cves votre-image:tag
Le fichier .dockerignore empêche l’inclusion de fichiers sensibles comme .env, credentials.json ou des clés SSH dans vos images.
Exemple de .dockerignore :
.env
.git
.pem
.key
nodemodules
.vscode
secrets/
Mauvaise pratique :
# ❌ DANGER : Secret en dur
ENV APIKEY="sk-1234567890abcdef"
Bonne pratique :
# ✅ Utiliser Docker Secrets ou des variables d'environnement
# Les secrets sont injectés au runtime
# Avec Docker Swarm
echo "monsecret" | docker secret create apikey -
# Avec docker-compose
docker-compose --env-file .env up
Restreignez les capacités système (capabilities) aux seules nécessaires pour l’application.
# docker-compose.yml
services:
app:
capdrop:
- ALL
capadd:
- NETBINDSERVICE
Prévenez les attaques par épuisement des ressources en définissant des limites CPU et mémoire.
services:
app:
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
Les builds multi-stages séparent l’environnement de build et l’environnement d’exécution, produisant des images ultra-légères.
# Stage 1 : Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2 : Production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/nodemodules ./nodemodules
USER node
CMD ["node", "dist/server.js"]
Avantages :
BuildKit est le moteur de build moderne de Docker, activé par défaut depuis Docker 23.0. Il offre :
# Activer BuildKit (si version < 23.0)
export DOCKERBUILDKIT=1
# Utiliser les montages de cache
docker build --progress=plain .
Exemple avec cache mount :
# Installer les dépendances avec cache persistant
RUN --mount=type=cache,target=/root/.npm
npm install
Docker construit les images en couches. Ordonnez vos instructions du plus stable au plus changeant.
# ✅ Bon ordre : cache efficace
FROM python:3.12-slim
# 1. Dépendances système (changent rarement)
RUN apt-get update && apt-get install -y
gcc
&& rm -rf /var/lib/apt/lists/
# 2. Dépendances Python (changent occasionnellement)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 3. Code applicatif (change fréquemment)
COPY . .
# ❌ Mauvais ordre : cache inefficace
FROM python:3.12-slim
COPY . . # Invalide le cache à chaque modification
RUN pip install -r requirements.txt
Supprimez les fichiers de cache après installation des paquets pour réduire la taille de l’image.
# Pour Debian/Ubuntu
RUN apt-get update && apt-get install -y
package1 package2
&& apt-get clean
&& rm -rf /var/lib/apt/lists/
# Pour Alpine
RUN apk add --no-cache package1 package2
# Pour RHEL/CentOS
RUN yum install -y package1 package2
&& yum clean all
En 2025, les « micro-distros » comme Wolfi et Chainguard Images offrent d’excellentes garanties de sécurité avec une empreinte minimale.
Comparaison des tailles :
ubuntu:latest → 77 MB
python:3.12 → 1.02 GB
python:3.12-slim → 131 MB
python:3.12-alpine → 51 MB
chainguard/python → 45 MB (+ sécurité renforcée)
Recommandations par langage :
# Node.js
FROM node:20-alpine
# Python
FROM python:3.12-slim
# Go (distroless)
FROM gcr.io/distroless/static-debian12
# Rust
FROM rust:1.75-alpine AS builder
FROM gcr.io/distroless/cc-debian12
N’installez que les dépendances strictement nécessaires.
# ❌ Mauvais : installe des recommandations inutiles
RUN apt-get install -y curl
# ✅ Bon : n'installe que le minimum
RUN apt-get install -y --no-install-recommends curl
Chaque instruction RUN crée une nouvelle couche. Combinez les commandes pour réduire le nombre de couches.
# ❌ Mauvais : 3 couches
RUN apt-get update
RUN apt-get install -y curl
RUN curl https://example.com/install.sh | bash
# ✅ Bon : 1 seule couche
RUN apt-get update &&
apt-get install -y curl &&
curl https://example.com/install.sh | bash &&
apt-get clean &&
rm -rf /var/lib/apt/lists/
Les health checks permettent à Docker et aux orchestrateurs (Kubernetes, Swarm) de détecter et redémarrer les conteneurs défaillants.
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD curl -f http://localhost:3000/health || exit 1
# docker-compose.yml
services:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 3s
retries: 3
startperiod: 5s
Ne vous contentez pas du tag :latest. Utilisez des versions sémantiques et des hash de commit.
# ❌ Mauvais : impossible de tracer la version
docker build -t monapp:latest .
# ✅ Bon : tracabilité complète
docker build -t monapp:1.2.3 .
docker build -t monapp:1.2.3-$(git rev-parse --short HEAD) .
docker build -t monapp:sha-a3b2c1d .
Mettez régulièrement à jour vos images de base et dépendances pour corriger les vulnérabilités.
# Spécifier une version précise (mais pas latest)
FROM node:20.11-alpine3.19
# Planifier des mises à jour régulières (ex: mensuelle)
Les labels documentent vos images et facilitent l’automatisation.
LABEL org.opencontainers.image.title="Mon Application"
LABEL org.opencontainers.image.description="API REST pour la gestion d'utilisateurs"
LABEL org.opencontainers.image.version="1.2.3"
LABEL org.opencontainers.image.authors="dev@monentreprise.com"
LABEL org.opencontainers.image.source="https://github.com/monentreprise/monapp"
LABEL org.opencontainers.image.revision="${GITCOMMIT}"
Docker 24.0+ inclut docker init qui génère automatiquement les fichiers Docker pour votre projet.
# Génère Dockerfile, .dockerignore et compose.yaml
docker init
# Supporte : Go, Python, Node.js, Rust, ASP.NET
Docker Scout analyse vos images et recommande des corrections.
# Analyser une image
docker scout cves monapp:latest
# Obtenir des recommandations
docker scout recommendations monapp:latest
# Comparer deux versions
docker scout compare monapp:1.0.0 monapp:2.0.0
Les attestations prouvent la provenance et l’intégrité de vos images.
# Créer une image avec attestation
docker buildx build --sbom=true --provenance=true -t monapp:1.0 .
# Vérifier l'attestation
docker buildx imagetools inspect monapp:1.0 --format "{{json .Provenance}}"
Respectez le principe « one process per container » pour faciliter la scalabilité.
# ✅ Bon : Services séparés
services:
api:
image: monapp-api:latest
worker:
image: monapp-worker:latest
scheduler:
image: monapp-scheduler:latest
# ❌ Mauvais : Tout dans un conteneur
services:
monolithe:
image: monapp-tout-en-un:latest
# api + worker + scheduler + cron
Isolez vos services avec des réseaux Docker dédiés.
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # Pas d'accès externe
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
database:
networks:
- backend # Accessible uniquement par l'API
Dirigez les logs vers STDOUT/STDERR pour que Docker les capture.
# ✅ Bon : Logs vers STDOUT
CMD ["node", "server.js"]
# Configuration du logging
# docker-compose.yml
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Définissez votre stack complète dans compose.yaml.
version: '3.9'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
- /app/nodemodules
environment:
- NODEENV=development
ports:
- "3000:3000"
dependson:
db:
condition: servicehealthy
db:
image: postgres:16-alpine
environment:
POSTGRESDB: myapp
POSTGRESUSER: dev
POSTGRESPASSWORD: devpass
volumes:
- postgresdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pgisready -U dev"]
interval: 5s
volumes:
postgresdata:
Fixez les versions de toutes vos dépendances.
# ✅ Bon : Versions fixes
FROM node:20.11.1-alpine3.19
RUN npm install express@4.18.2
# ❌ Mauvais : Versions flottantes
FROM node:latest
RUN npm install express
Intégrez Docker dans votre pipeline CI/CD.
# .github/workflows/docker.yml
name: Docker Build & Push
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUBUSERNAME }}
password: ${{ secrets.DOCKERHUBTOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
monapp:latest
monapp:${{ github.sha }}
cache-from: type=registry,ref=monapp:buildcache
cache-to: type=registry,ref=monapp:buildcache,mode=max
Passez des secrets aux builds sans les exposer dans les couches.
# Utiliser un secret pendant le build
RUN --mount=type=secret,id=npmtoken
echo "//registry.npmjs.org/:authToken=$(cat /run/secrets/npmtoken)" > .npmrc &&
npm install &&
rm .npmrc
# Build avec secret
docker buildx build --secret id=npmtoken,src=$HOME/.npmrc .
Minimisez le nombre de fichiers modifiés dans chaque couche.
# ✅ Bon : Suppression dans la même couche
RUN wget https://example.com/large-file.tar.gz &&
tar xzf large-file.tar.gz &&
rm large-file.tar.gz # Fichier non présent dans l'image finale
# ❌ Mauvais : Suppression dans une autre couche
RUN wget https://example.com/large-file.tar.gz
RUN tar xzf large-file.tar.gz
RUN rm large-file.tar.gz # Fichier toujours dans la couche précédente!
Les ARG permettent de paramétrer vos builds.
ARG NODEVERSION=20
ARG APPENV=production
FROM node:${NODEVERSION}-alpine
ENV NODEENV=${APPENV}
# Build avec args personnalisés
# docker build --build-arg NODEVERSION=18 --build-arg APPENV=staging .
Exécutez le daemon Docker lui-même sans privilèges root.
# Installation de Docker en mode rootless
curl -fsSL https://get.docker.com/rootless | sh
# Configurer les variables d'environnement
export PATH=/home/user/bin:$PATH
export DOCKERHOST=unix:///run/user/1000/docker.sock
Attendez que les dépendances soient prêtes avant de démarrer.
services:
api:
dependson:
db:
condition: servicehealthy
redis:
condition: servicehealthy
Définissez comment Docker doit gérer les redémarrages.
services:
app:
restart: unless-stopped
deploy:
restartpolicy:
condition: on-failure
delay: 5s
maxattempts: 3
Utilisez des volumes pour les données persistantes et les caches.
services:
app:
volumes:
# Données persistantes
- appdata:/app/data
# Cache de build (performance)
- nodemodules:/app/nodemodules
# Code en développement (bind mount)
- ./src:/app/src:ro # read-only
volumes:
appdata:
driver: local
nodemodules:
Les montages tmpfs utilisent la RAM pour des performances maximales.
services:
app:
tmpfs:
- /tmp
- /app/cache:size=100M
Intégrez Trivy dans votre CI pour bloquer les images vulnérables.
# .github/workflows/security.yml
name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: 'monapp:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1' # Fail le build si vulnérabilités
Renforcez l’isolement avec des profils de sécurité.
services:
app:
securityopt:
- apparmor:docker-default
- no-new-privileges:true
Ne montez JAMAIS /var/run/docker.sock sauf nécessité absolue.
# ❌ TRÈS DANGEREUX
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# Cette configuration donne au conteneur un contrôle TOTAL sur l'hôte
Montez le système de fichiers racine en lecture seule.
services:
app:
readonly: true
tmpfs:
- /tmp
- /var/run
Fournissez un endpoint de métriques pour Prometheus.
EXPOSE 3000 9090
# 3000: Application
# 9090: Métriques Prometheus
// Exemple Node.js avec prom-client
const prometheus = require('prom-client');
const register = new prometheus.Registry();
// Métriques par défaut
prometheus.collectDefaultMetrics({ register });
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
Envoyez les logs vers un système centralisé.
services:
app:
logging:
driver: "fluentd"
options:
fluentd-address: "fluentd:24224"
tag: "monapp"
Intégrez OpenTelemetry pour le tracing.
# Installer l'agent OpenTelemetry
RUN npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node
Avant de déployer en production, vérifiez :
Sécurité :
Performance :
Production :
Observabilité :
Docker en 2025 est une plateforme mature qui exige rigueur et expertise. Les pratiques obsolètes de 2015 n’ont plus leur place : les images doivent être minimales, sécurisées et optimisées pour la production.
Points clés à retenir :
En appliquant ces 42 meilleures pratiques, vous construirez des images Docker robustes, sécurisées et performantes, prêtes pour les environnements de production exigeants.
Article mis à jour en décembre 2025 avec les dernières pratiques et outils de l’écosystème Docker.
Cet article est vivant — corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.