Introduction
Exécuter Docker en production repose sur des builds reproductibles, des réglages sécurisés par défaut, une observabilité solide et une gestion des changements sans risque. Le gain : une fiabilité accrue avec moins de retouches et de surprises. Utilisez cette checklist pour standardiser votre approche et accélérer la livraison.
Vue d’ensemble du flux de travail
Suivez ces étapes pour chaque service :
- Construire des images minimales et verrouillées (pinned)
- Configurer l’exécution de façon sûre (utilisateur, capabilities, système de fichiers)
- Isoler les réseaux et n’exposer que le nécessaire
- Définir des limites de ressources et des healthchecks
- Brancher les logs et métriques avec rétention bornée
- Persister l’état via des volumes nommés et tester les sauvegardes
- Mettre à niveau avec rollback, valider avec des sondes
- Maintenir les hôtes et artefacts selon un calendrier
Astuce : de petites étapes observables réduisent le retravail et facilitent l’isolement des problèmes. Par exemple, ajoutez un healthcheck avant d’activer une politique de redémarrage afin que le conteneur soit marqué sain avant de recevoir du trafic.
Socle de configuration
Checklist :
- Builds multi‑stage pour garder les images légères
- Verrouiller les images de base et les outils par version (ou digest)
- Utilisateur non‑root avec UID/GID fixes
- HEALTHCHECK dans l’image ou dans Compose
- Fichiers minimaux via un .dockerignore strict
- Labels de provenance (organisation, version, VCS, date de build)
Exemple de Dockerfile (service Go) :
# Build stage
FROM golang:1.22-alpine AS build
WORKDIR /src
RUN adduser -D -u 10001 app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags='-s -w' -o /out/app ./cmd/server
# Runtime stage
FROM alpine:3.20
RUN addgroup -g 10001 app \
&& adduser -D -u 10001 -G app app \
&& apk add --no-cache ca-certificates curl
WORKDIR /app
COPY --from=build /out/app /app/app
USER 10001:10001
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -fsS http://127.0.0.1:8080/health || exit 1
ENTRYPOINT [
/
/app/app/
]
Renforcement de la sécurité
Checklist :
- Exécuter en tant qu’utilisateur non‑root (UID/GID)
- Système de fichiers racine en lecture seule ; écriture temporaire via tmpfs
- Supprimer toutes les capabilities Linux, n’ajouter que le strict nécessaire
- no-new-privileges pour bloquer l’élévation de privilèges
- Éviter les namespaces PID/réseau hôte et le mode privileged
- Stocker les secrets sous forme de fichiers, pas de variables d’environnement
Exemple de docker‑compose.yml avec défauts de sécurité :
version: '3.9'
services:
app:
image: myorg/myapp:1.2.3
user: '10001:10001'
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid,size=64m
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
restart: always
stop_grace_period: 30s
Secrets en fichiers avec Compose :
services:
app:
secrets:
- source: db_password
target: db_password
mode: 0400
secrets:
db_password:
file: ./secrets/db_password.txt
L’application doit lire le secret à /run/secrets/db_password.
Limites de ressources et healthchecks
Checklist :
- Ajouter un healthcheck au conteneur
- Définir des limites CPU et mémoire
- Configurer les ulimits (nofile, nproc)
- Utiliser une politique de redémarrage sensée (always ou unless‑stopped)
Exemple Compose (hors Swarm) :
services:
app:
# build ou image ici
healthcheck:
test: ['CMD', 'wget', '-q', '-O', '-', 'http://127.0.0.1:8080/health']
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
restart: always
mem_limit: 512m
cpus: '0.50'
ulimits:
nofile:
soft: 65536
hard: 65536
nproc: 4096
Note : deploy.resources est réservé à Swarm. Pour Docker Compose autonome, utilisez mem_limit et cpus comme illustré.
Réseau et ingress
Checklist :
- Utiliser un réseau bridge défini par l’utilisateur par application ou domaine
- Mapper uniquement les ports requis vers l’hôte
- Garder les services internes privés sur le réseau de l’application
- Terminer le TLS au niveau d’un proxy d’ingress (ex. Nginx) et monter les certificats en lecture seule
Exemple d’isolation réseau :
services:
app:
networks: [app-net]
nginx:
image: nginx:1.25
depends_on: [app]
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
networks: [app-net]
networks:
app-net:
driver: bridge
Exemple minimal de nginx.conf (upstream) :
worker_processes auto;
events { worker_connections 1024; }
http {
upstream app_upstream { server app:8080; }
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/certs/server.crt;
ssl_certificate_key /etc/nginx/certs/server.key;
location / {
proxy_pass http://app_upstream;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
Logs et métriques
Checklist :
- Utiliser un driver de logs cohérent avec rotation
- Émettre des logs structurés (JSON lines) depuis l’application, incluant horodatage, niveau, nom du service et request id
- Collecter CPU, mémoire et compteurs de redémarrage au niveau conteneur
Exemple de logging Compose :
services:
app:
logging:
driver: json-file
options:
max-size: '10m'
max-file: '3'
Astuces opérationnelles :
docker logs --since 10m appdocker stats appdocker inspect --format '{{.State.Health}}' app
Stockage et sauvegardes
Checklist :
- Utiliser des volumes nommés pour l’état
- Garder la configuration et les secrets hors de l’image
- Documenter et tester la sauvegarde/restauration ; planifier des sauvegardes régulières (ex. quotidiennes via cron)
Créer et sauvegarder un volume nommé :
# Créer un volume
docker volume create mydata
# Sauvegarder dans un tarball horodaté dans le répertoire courant
docker run --rm \
-v mydata:/data \
-v "$PWD:/backup" \
busybox sh -c 'tar czf /backup/mydata-$(date +%F).tgz -C / data'
# Lister les sauvegardes
ls -lh mydata-*.tgz
# Restaurer à partir d’une sauvegarde
docker run --rm \
-v mydata:/data \
-v "$PWD:/backup" \
busybox sh -c 'tar xzf /backup/mydata-2026-07-13.tgz -C /'
Pour les bases de données, privilégier les outils natifs (ex. pg_dump, mysqldump) afin d’assurer la cohérence.
Mises à niveau et rollbacks
Checklist :
- Verrouiller les images par version ou digest
- Mettre à niveau par petits incréments
- Vérifier la santé et les logs avant de basculer le trafic
- Conserver un chemin de rollback rapide
Verrouiller par tag et digest dans Compose :
services:
nginx:
image: nginx:1.25.5@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Mise à niveau roulante avec deux projets (style canary) :
# Déployer la version suivante
docker compose -p myapp-next up -d
# Vérifier la santé
docker compose -p myapp-next ps
# Basculer le trafic au niveau ingress (mettre à jour l’upstream ou le DNS)
# Décommissionner la version précédente
docker compose -p myapp-current down
Mise à niveau simple sur place :
docker compose pull
docker compose up -d
docker compose ps
Maintenance et dépannage
Checklist :
- Surveiller l’utilisation disque et purger prudemment
- Rotater les logs et conserver des bornes
- Ne conserver que les images et réseaux nécessaires
Commandes utiles :
# Afficher l’utilisation de l’espace
docker system df
# Lister d’abord les images dangling
docker images -f dangling=true
# Purger prudemment (demande de confirmation)
docker image prune
# Purge complète des images et du cache de build inutilisés (attention)
docker image prune -af
# Inspecter les redémarrages récents
docker events --since 1h --filter 'event=restart'
Plan pilote local
Objectif : valider la checklist sur un service sans état avec des critères d’acceptation clairs.
Périmètre :
- Un service derrière Nginx
- Healthcheck, politique de redémarrage, limites mémoire et CPU
- Rotation des logs via le driver json-file
- Un petit volume nommé et une sauvegarde testée
Étapes :
- Implémenter le fichier Compose avec défauts de sécurité, limites et logging
- Ajouter un endpoint de santé et vérifier que
docker psaffiche healthy - Simuler un crash et vérifier le redémarrage :
docker kill -s SIGKILL app - Capturer les métriques de base avec
docker statset le temps de démarrage - Sauvegarder et restaurer le volume, vérifier l’intégrité des données
Critères d’acceptation :
- Le healthcheck passe dans les 10 secondes suivant le démarrage du conteneur
- Aucun log de conteneur ne dépasse 30 Mo après rotation
- Mémoire et CPU restent dans les limites configurées sous charge basique
- La restauration de la sauvegarde recrée l’état attendu
Pièges courants en production et correctifs
- Utiliser le tag
:latest→ Correctif : verrouiller les tags ou digests et mettre à jour intentionnellement. - Exécuter en root → Correctif : créer un utilisateur non‑root et définir
userdans l’image et Compose. - Absence de healthchecks → Correctif : ajouter
HEALTHCHECKdans l’image ou Compose. - Logs non bornés → Correctif : configurer la rotation json-file ou expédier les logs vers un stockage central avec rétention.
- Écrire l’état dans le système de fichiers du conteneur → Correctif : utiliser des volumes nommés et valider la sauvegarde/restauration.
- Exposer plus de ports que nécessaire → Correctif : garder les services internes sur un réseau privé.
- Oublier les ulimits → Correctif : définir
nofileetnprocselon les besoins de la charge. - S’appuyer sur
deploy.resourcesdans Compose hors Swarm → Correctif : utilisermem_limitetcpuspour Docker autonome.
Conclusion
Adoptez la checklist, démarrez avec le pilote local, puis étendez service par service. Maintenez les changements petits, mesurables et réversibles. Avec des réglages par défaut sécurisés, des limites claires et des sauvegardes éprouvées, vos opérations Docker en production seront plus sûres, plus rapides et plus faciles à dépanner.