14. Monitorer ses conteneurs - Docker

Toujours dans une démarche de maîtriser Docker, savoir débugger un conteneur c'est aussi récupérer les logs de son conteneur, monitorer ses conteneurs, connaître la consommation d'un conteneur etc...

Bien qu'il est possible de monitorer ses conteneurs Docker de pleins de manières différentes avec des outils tierces comme Prometheus, Grafana, Zabbix, CheckMK etc... Regardons d'abord comment effectuer le monitoring de conteneurs avec ce que nous mets à disposition Docker.

Les logs

Afin de pouvoir débugger un conteneur Docker pour notamment connaître la cause de son échec, ou bien ce qu'il exécute tout simplement, il est important de savoir comment récupérer les logs d'un conteneur.

Il faut savoir que lorsque l'on parle des logs d'un conteneur, il s'agit en réalité de la STDOUT et de la STDERR.
Pour l'afficher, il suffit d'exécuter la commande suivante :

docker logs <nom du conteneur>

Il est aussi possible de suivre les logs en temps réel, à la manière de la commande tail -f avec l'argument -f.

Prenons le cas où vous avez besoin d'avoir les logs de votre conteneur dans un autre format (pour des exigences de logiciels tiers comme Elasticsearch ou autre), sachez qu'il est possible avec Docker de modifier le driver des logs.
Le driver de logs par défaut utilisé par Docker est json-file. Les fichiers de logs sont stockés dans /var/lib/docker/containers/<container-id>/<container-id>-json.log sur l'hôte.

Pour spécifier un autre driver de logs au lancement d'un conteneur, il faut préciser l'argument --log-driver de la commande docker run. Les autres drivers existant sont notamment syslog, journald, fluentd, awslogs et gcplogs.

Il est aussi possible de changer le driver de logs avec Docker Compose en ajoutant les lignes suivantes dans votre fichier docker-compose.yml :

x-logging:
  &json-logging
  options:
    max-size: "10m"
    max-file: "1"
  driver: "json-file"

Et dans votre service, ajouter la clé logging comme ceci :

services:
  monservice:
    image: monrepo/monimage
    logging: *json-logging
💡
Cela utilise les fonctionnalités avancées du langage YAML.

Les ressources

Voilà une partie très importante : les ressources !
En effet, je vous ai présenté Docker comme un technologie pleine d'avantages, avec des gains de ressources énormes etc... Regardons comment monitorer les ressources de nos conteneurs sans outils tierces.

Pour afficher la consommation des conteneurs en cours d'exécution, il existe la commande suivante :

docker stats
Exemple de retour :
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O         PIDS
56b5026ec0e3   monconteneur   0.00%     191.5MiB / 30.96GiB   0.60%     145kB / 2.19MB   725MB / 2.49MB    3
87a1ac57fe37   redis     0.19%     7.684MiB / 30.96GiB   0.02%     76.3kB / 0B      36.2MB / 1.08MB   5

Maintenant que nous connaissons la consommations de nos conteneurs, regardons comment limiter les ressources utilisées par un conteneur. Pour limiter la mémoire RAM utilisée par un conteneur, il suffit d'utiliser l'argument --memory.
Par exemple, pour limiter la RAM à 512Mo d'un nouveau conteneur, ce sera la commande suivante qui sera exécutée :

docker run --memory 512m <image>

Avec Docker Compose, ce sont les lignes suivantes qu'il faut ajouter à notre service :

deploy:
  resources:
    limits:
      memory: 512m

Les autres ressources pouvant être limitées sont le nombre de CPUs utilisés par un conteneur avec l'argument --cpus, sa bande passante ainsi que les I/O disque.

Il est aussi possible de réserver des ressources pour un conteneur, comme le montre cet exemple :

deploy:
  resources:
    reservations:
      cpus: '0.5'
      memory: 256m

Le Healthcheck

Le monitoring passe aussi par la vérification du statut d'un service. Par exemple si l'endpoint d'une API est bien UP etc...

Dans Docker, la vérification d'un statut peut se faire de plusieurs manières :

  • Dans le Dockerfile avec l'instruction HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/healthcheck || exit 1

Dans cet exemple, l'instruction HEALTHCHECK  utilise curl pour vérifier l'état de l'application en exécutant une requête HTTP sur l'URL http://localhost:8080/healthcheck. Si la requête échoue, le HEALTHCHECK renvoie un code retour 1, ce qui signifie que l'application est considérée comme étant en échec.

Le HEALTHCHECK est configuré pour s'exécuter toutes les 30 secondes avec une période de démarrage de 5 secondes. Si le HEALTHCHECK échoue après trois tentatives, le conteneur sera considéré comme étant en échec et redémarré automatiquement.

  • Au lancement d'un conteneur Docker avec l'argument  --health-cmd
docker run --name mon-conteneur \
  --health-cmd="curl -f http://localhost:8080/healthcheck || exit 1" \
  -p 8080:8080 mon-image

Ici, l'argument --health-cmd est l'équivalent de l'instruction HEALTHCHECK au lancement d'un conteneur.
Le système de HEALTHCHECK est configuré par défaut pour s'exécuter toutes les 30 secondes. S'il échoue après trois tentatives, le conteneur sera considéré comme étant en échec et redémarrera automatiquement.

  • Dans le fichier docker-compose.yml :
---
version: "3"
services:
  mon-conteneur:
    image: mon-image
    ports:
      - "8080:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 3

Avec Docker Compose, il faut créer une liste nommée healthcheck suivi du nom de la commande a exécuter. Ici, c'est la clé test qui est utilisée avec curl pour vérifier l'état de l'application en exécutant une requête HTTP sur l'URL http://localhost:8080/healthcheck.

Les clés interval, timeout et retries sont les équivalents de ce qui a été présenté au dessus.

Pour démarrer le service, il suffit d'exécuter la commande docker-compose up. Le système de HEALTHCHECK sera activé automatiquement et affichera les résultats dans la sortie de la console.

Aller plus loin

Pour aller plus loin dans l'administration et le monitoring de Docker, il est possible d'utiliser le logiciel Portainer qui est Open Source afin de disposer d'une interface web graphique.

GitHub - portainer/portainer: Making Docker and Kubernetes management easy.
Making Docker and Kubernetes management easy. Contribute to portainer/portainer development by creating an account on GitHub.

Avec Portainer, il est possible d'effectuer tout ce qui est possible de faire avec Docker, mais cette fois-ci, depuis son interface web. Il dispose d'un affichage clair avec un design épuré.

Dans un contexte de travail en équipe, Portainer a un réel intérêt car cela vous permet de gérer vos conteneurs dans un endroit centralisé et également affiner les droits d'accès.

Nous arrivons quasiment au bout de notre cours sur Docker, terminons cette formation avec le prochain cours qui n'est autre que la conclusion !