← Retour aux tutoriels

Checklist de préparation à la production pour microservices Dockerisés (DevOps)

devopsdockermicroservicesproduction-readinesschecklistkubernetesci-cdsecuriteobservabilitesre

Checklist de préparation à la production pour microservices Dockerisés (DevOps)

Ce guide est une checklist pragmatique pour préparer des microservices Dockerisés à la production. Il vise les équipes DevOps/Platform et les développeurs qui livrent des services en conteneurs (Docker, orchestrés par Kubernetes, ECS, Nomad, Swarm, etc.). Les exemples utilisent Linux et des commandes réelles. Adaptez-les à votre environnement.


1) Objectifs de “production readiness”

Avant la technique, clarifiez ce que “prêt pour la prod” signifie pour vous :


2) Dockerfile : construction reproductible, petite, sûre

2.1 Multi-stage build et images minimales

Utilisez des builds multi-étapes pour éviter d’embarquer toolchains et dépendances de build en runtime.

Exemple (Node.js) :

# Étape build
FROM node:20-bookworm AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Étape runtime
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER 10001:10001
ENV NODE_ENV=production
CMD ["dist/server.js"]

Points clés :

Vérifiez la taille :

docker build -t monservice:local .
docker images | grep monservice

2.2 .dockerignore

Réduisez le contexte envoyé au daemon Docker (build plus rapide, moins de fuites).

Exemple .dockerignore :

.git
node_modules
dist
*.log
.env
coverage

2.3 Pinning des versions et digest

Évitez latest. Pinner les versions, idéalement via digest :

FROM python:3.12.3-slim@sha256:...

Raison : reproductibilité et réduction des surprises lors des rebuilds.

2.4 Labels OCI et métadonnées

Ajoutez des labels utiles :

LABEL org.opencontainers.image.source="https://git.example.com/monrepo" \
      org.opencontainers.image.revision="$GIT_SHA" \
      org.opencontainers.image.created="$BUILD_DATE"

Construisez en injectant les args :

docker build \
  --build-arg GIT_SHA="$(git rev-parse HEAD)" \
  --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  -t registry.example.com/monservice:$(git rev-parse --short HEAD) .

3) Exécution : moindre privilège, filesystem en lecture seule, capabilities

3.1 Lancer en non-root

Même si votre orchestrateur force un user, faites-le aussi au niveau image (USER).

Vérification :

docker run --rm monservice:local id

3.2 Read-only root filesystem + tmpfs

De nombreux services n’ont pas besoin d’écrire sur /. Testez :

docker run --rm \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  --tmpfs /run:rw,noexec,nosuid,size=16m \
  monservice:local

Si votre app échoue, identifiez ce qui écrit et redirigez vers un volume dédié.

3.3 Drop des Linux capabilities

Par défaut, Docker ajoute des capabilities. En production, réduisez :

docker run --rm \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  -p 8080:8080 \
  monservice:local

3.4 Seccomp et AppArmor

Sur hôtes compatibles, utilisez des profils restrictifs. À minima, gardez le profil seccomp par défaut. Pour aller plus loin, créez un profil adapté (selon runtime/orchestrateur).


4) Configuration : 12-factor, variables d’environnement, validation

4.1 Séparer config et code

Exemple de lancement :

docker run --rm \
  -e PORT=8080 \
  -e LOG_LEVEL=info \
  -e DATABASE_URL="postgres://user:pass@db:5432/app" \
  monservice:local

4.2 Validation au démarrage

Faites échouer le conteneur si la config est invalide. Cela améliore la sécurité et la fiabilité (fail fast). Exemple de contrôle (conceptuel) :

Testez ce comportement :

docker run --rm -e PORT=abc monservice:local
echo $?

Le code de sortie doit être non-zéro.

4.3 Gestion des dépendances externes


5) Réseau : ports, TLS, timeouts, DNS

5.1 Exposer uniquement ce qui est nécessaire

Dans le Dockerfile, EXPOSE est informatif, mais gardez une discipline :

5.2 Timeouts côté serveur

Un service HTTP doit avoir :

Test de charge simple :

wrk -t4 -c100 -d30s http://localhost:8080/healthz

5.3 DNS et résilience

En environnement orchestré, le DNS peut être instable lors de rollouts. Utilisez :


6) Stockage : stateless par défaut, volumes explicites

6.1 Microservice stateless

Idéalement, le conteneur ne stocke rien localement (sauf cache éphémère). Les données persistantes vont dans :

6.2 Si persistance : volumes nommés

Test local :

docker volume create monservice-data
docker run --rm -v monservice-data:/var/lib/monservice monservice:local

Documentez :


7) Healthchecks : liveness, readiness, startup

7.1 HEALTHCHECK Docker

Même si Kubernetes a ses probes, un HEALTHCHECK aide en exécution simple Docker.

Exemple :

HEALTHCHECK --interval=10s --timeout=2s --retries=3 \
  CMD node dist/healthcheck.js || exit 1

Ou via HTTP (si curl disponible, ce qui n’est pas le cas en distroless). Alternative : binaire minimal ou endpoint TCP.

7.2 Readiness vs Liveness

En pratique :


8) Logs : stdout/stderr, structuré, corrélation

8.1 Écrire sur stdout/stderr

En conteneur, évitez les fichiers de logs locaux. Utilisez stdout/stderr :

Test :

docker logs -f <container_id>

8.2 Logs JSON et champs standard

Adoptez un format structuré (JSON) avec :

Cela facilite l’indexation (ELK, Loki, Datadog, etc.).

8.3 Propagation d’un Request ID


9) Métriques et tracing : SLO, RED/USE, OpenTelemetry

9.1 Métriques essentielles (minimum)

Pour un service HTTP :

Pour les ressources :

Test d’un endpoint metrics (ex. Prometheus) :

curl -s http://localhost:8080/metrics | head

9.2 Traces distribuées

Activez OpenTelemetry :

Vérifiez que les spans apparaissent dans votre backend (Jaeger, Tempo, Datadog, etc.) et que les IDs se retrouvent dans les logs.


10) Gestion des erreurs : codes, retries, idempotence

10.1 Contrats HTTP

Évitez de renvoyer 200 avec un champ error=true. Les load balancers, alertes et clients s’appuient sur les codes.

10.2 Idempotence

Pour des endpoints critiques (paiement, création), implémentez une clé d’idempotence :

10.3 Retries côté client


11) Ressources : limites CPU/mémoire, OOM, GC, threads

11.1 Comprendre les limites en conteneur

Sans limites, un service peut consommer trop et impacter le nœud. Fixez des limites au niveau orchestrateur. En local Docker, vous pouvez simuler :

docker run --rm -m 256m --cpus="0.5" monservice:local

Surveillez :

docker stats

11.2 Comportement en OOM

Testez le cas où la mémoire est insuffisante :

Pour Java/Node, configurez la mémoire en tenant compte des cgroups (versions récentes gèrent mieux, mais vérifiez).


12) Démarrage/arrêt : signaux, shutdown gracieux, draining

12.1 Gestion de SIGTERM

En production, l’orchestrateur envoie SIGTERM puis SIGKILL après un délai. Votre service doit :

Test manuel :

docker run --rm --name test-stop -p 8080:8080 monservice:local
# Dans un autre terminal
docker stop -t 20 test-stop

Le -t 20 simule un délai de grâce de 20 secondes.

12.2 PID 1 et init

Si votre process est PID 1, il doit gérer correctement les signaux. Sinon, utilisez tini (ou l’option Docker) :

docker run --rm --init monservice:local

Ou dans Dockerfile (si image non distroless) :

RUN apt-get update && apt-get install -y tini && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["tini","--"]
CMD ["./monservice"]

13) Sécurité : secrets, scanning, SBOM, supply chain

13.1 Secrets : ne jamais les builder dans l’image

Anti-pattern :

Préférez :

13.2 Scan de vulnérabilités

Scannez images et dépendances.

Avec Trivy :

trivy image --severity HIGH,CRITICAL registry.example.com/monservice:abc123

Scannez aussi le repo :

trivy fs --severity HIGH,CRITICAL .

13.3 SBOM (Software Bill of Materials)

Générez une SBOM pour audit et traçabilité.

Avec Syft :

syft registry.example.com/monservice:abc123 -o spdx-json > sbom.spdx.json

13.4 Signature d’images

Signez vos images (Cosign) :

cosign sign registry.example.com/monservice:abc123
cosign verify registry.example.com/monservice:abc123

14) CI/CD : pipelines, tests, qualité, promotion d’artefacts

14.1 Construire une fois, promouvoir

Principe : l’image construite en CI est la même que celle déployée en prod (promotion par tag/digest), pas de rebuild en prod.

Exemple de tagging :

GIT_SHA="$(git rev-parse --short HEAD)"
docker build -t registry.example.com/monservice:$GIT_SHA .
docker push registry.example.com/monservice:$GIT_SHA

docker tag registry.example.com/monservice:$GIT_SHA registry.example.com/monservice:staging
docker push registry.example.com/monservice:staging

En prod, utilisez le digest :

docker pull registry.example.com/monservice@sha256:...

14.2 Tests indispensables

Hadolint :

hadolint Dockerfile

14.3 Politique de merge


15) Stratégies de déploiement : rolling, blue/green, canary

15.1 Rolling update

15.2 Blue/Green

15.3 Canary


16) Base de données : migrations, compatibilité, rollback

16.1 Migrations versionnées

Ne lancez pas des migrations “à la main” sans traçabilité. Utilisez un outil (Flyway, Liquibase, Alembic, Prisma, etc.) et versionnez les scripts.

16.2 Déploiement sans downtime

Pratique recommandée :

16.3 Tests de migration

En CI, exécutez migrations sur une DB éphémère :

docker run --rm -d --name pg -e POSTGRES_PASSWORD=pass -p 5432:5432 postgres:16
# Attendre que la DB soit prête puis lancer migrations (exemple)
psql "postgres://postgres:pass@localhost:5432/postgres" -c "SELECT 1;"
# ... commande de migration ...
docker rm -f pg

17) Files d’attente et traitements async : backpressure, DLQ

Si vous avez Kafka/RabbitMQ/SQS :

Test basique de connectivité réseau (selon protocole) :

nc -vz broker.example.com 9092

18) Observabilité opérationnelle : dashboards, alertes, runbooks

18.1 Dashboards minimaux

Pour chaque service :

18.2 Alerting basé sur SLO

Évitez d’alerter sur “CPU > 80%” sans contexte. Préférez :

18.3 Runbooks

Pour chaque alerte, documentez :

Exemples de commandes utiles (selon environnement) :

curl -i http://service.example.com/healthz
curl -i http://service.example.com/readyz
curl -o /dev/null -s -w "time_total=%{time_total}\n" http://service.example.com/api

19) Tests de résilience : chaos “light”, pannes simulées

19.1 Simuler une dépendance lente

Si vous contrôlez un proxy (ou en dev), injectez de la latence. Sinon, testez côté client avec timeouts très bas pour vérifier le comportement.

19.2 Couper le réseau (local Docker)

Vous pouvez isoler un conteneur sur un réseau dédié et retirer l’accès (approche simplifiée). Exemple : lancer sur un réseau puis stopper la dépendance, observer retries/backoff.

docker network create testnet
docker run -d --name db --network testnet -e POSTGRES_PASSWORD=pass postgres:16
docker run --rm --network testnet -e DATABASE_URL="postgres://postgres:pass@db:5432/postgres" monservice:local

Stopper la DB et vérifier que le service se dégrade proprement (readiness peut passer à false, mais le process reste stable).


20) Performance : profiling, limites, caches

20.1 Profiling contrôlé

En prod, évitez d’exposer des endpoints de profiling sans protection. Préférez :

20.2 Caches


21) Conformité et gouvernance : audit, rétention, PII

Test simple : cherchez des patterns de secrets dans vos logs (ex. en staging) et corrigez.


22) Checklist finale (à cocher avant prod)

Image & build

Sécurité runtime

Configuration & comportement

Santé & cycle de vie

Observabilité

Déploiement & données


23) Annexes : commandes utiles de diagnostic Docker

Lister conteneurs :

docker ps
docker ps -a

Inspecter un conteneur :

docker inspect <container_id> | less

Voir l’usage ressources :

docker stats

Entrer dans un conteneur (si shell présent) :

docker exec -it <container_id> sh

Suivre les logs :

docker logs -f <container_id>

Tester la config de sécurité d’exécution (exemple) :

docker run --rm \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges:true \
  monservice:local

Conclusion

La production n’est pas un “environnement” : c’est un ensemble d’exigences (sécurité, fiabilité, observabilité, exploitabilité). Pour des microservices Dockerisés, la différence entre un service “qui tourne” et un service “opérable” se joue dans les détails : signaux, healthchecks, limites de ressources, logs structurés, gestion des secrets, scans, promotion d’artefacts, et discipline de déploiement.

Si vous me donnez votre stack (langage, orchestrateur, registry, observabilité), je peux adapter cette checklist avec des exemples concrets (Dockerfile, commandes CI, probes, métriques, conventions de logs) correspondant exactement à vos outils.