Comment effacer correctement les journaux d'un conteneur Docker?

210

J'utilise docker logs [container-name]pour voir les journaux d'un conteneur spécifique.

Existe-t-il un moyen élégant d'effacer ces journaux?

Youssouf Maiga
la source
14
Sur un sidenote, vous pouvez obtenir la taille des journaux viasudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log"
Daniel F

Réponses:

251

À partir de cette question, il y a un one-liner que vous pouvez exécuter:

echo "" > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

ou il y a la commande tronquée similaire:

truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

Je ne suis pas un grand fan de l'un d'eux car ils modifient directement les fichiers de Docker. La suppression du journal externe peut se produire pendant que le docker écrit des données au format json dans le fichier, ce qui entraîne une ligne partielle et empêche la lecture des journaux du docker logscli.

Au lieu de cela, Docker peut faire pivoter automatiquement les journaux pour vous. Cela se fait avec des indicateurs supplémentaires à dockerd si vous utilisez le pilote de journalisation JSON par défaut :

dockerd ... --log-opt max-size=10m --log-opt max-file=3

Vous pouvez également définir cela dans le cadre de votre fichier daemon.json au lieu de modifier vos scripts de démarrage:

{
  "log-driver": "json-file",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

Ces options doivent être configurées avec un accès root. Assurez-vous d'exécuter un systemctl reload dockeraprès avoir modifié ce fichier pour appliquer les paramètres. Ce paramètre sera alors la valeur par défaut pour tous les conteneurs nouvellement créés. Remarque: les conteneurs existants doivent être supprimés et recréés pour recevoir les nouvelles limites de journal.


Des options de journal similaires peuvent être transmises à des conteneurs individuels pour remplacer ces valeurs par défaut, ce qui vous permet d'enregistrer plus ou moins de journaux sur des conteneurs individuels. De docker runcela ressemble à:

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...

ou dans un fichier de composition:

version: '3.7'
services:
  app:
    image: ...
    logging:
      options:
        max-size: "10m"
        max-file: "3"

Pour des économies d'espace supplémentaires, vous pouvez passer du pilote de journal json au pilote de journal "local". Il prend les mêmes options max-size et max-file, mais au lieu de les stocker dans json, il utilise une syntaxe binaire plus rapide et plus petite. Cela vous permet de stocker plus de journaux dans le même fichier. L'entrée daemon.json pour cela ressemble à ceci:

{
  "log-driver": "local",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

L'inconvénient du pilote local est que les analyseurs / transitaires de journaux externes qui dépendaient d'un accès direct aux journaux json ne fonctionneront plus. Donc, si vous utilisez un outil comme filebeat pour envoyer à Elastic, ou le redirecteur universel de Splunk, j'éviterais le pilote "local".

J'en ai un peu plus à ce sujet dans ma présentation Trucs et astuces .

BMitch
la source
6
J'ai fait un service docker restart qui en soi ne fonctionnait pas. Il a également fallu créer de nouveaux conteneurs avant de prendre effet. c'est-à-dire que le simple fait de mettre en place les anciens conteneurs n'a pas appliqué la nouvelle journalisation
Robbo_UK
J'utilise Docker 1.13.1 et le 'docker inspect --format =' {{. LogPath}} '<id du conteneur>' renvoie une chaîne nulle ("") .... mais je reçois toujours la sortie de ' docker journaux <id du conteneur> '?!? D'où cela vient-il et comment le supprimer ??
JD Allen
@JDAllen 1.13.1 n'a plus de support depuis longtemps. Je n'ai pas de système aussi ancien pour voir leur sortie d'inspection.
BMitch
Ce serait encore mieux echo -n > .... Quoi qu'il en soit, j'aimerais pouvoir contrôler davantage mes journaux. Par exemple, après le redémarrage de docker-compose , j'aimerais avoir le mécanisme pour faire quelque chose avec les journaux conservés.
NarūnasK
2
@AlexisWilke si vous êtes en mesure d'arrêter docker, vous êtes probablement en mesure d'arrêter votre conteneur. Si vous pouvez le faire, recréer le conteneur avec les options de journalisation serait mon conseil. Le nouveau conteneur ne contient aucun ancien journal et les nouveaux journaux seront automatiquement roulés, résolvant à la fois le problème à court terme et à long terme.
BMitch
227

Utilisation:

truncate -s 0 /var/lib/docker/containers/*/*-json.log

Vous pourriez avoir besoin de sudo

sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"

réf. Jeff S. Comment effacer correctement les journaux d'un conteneur Docker?

Référence: tronquer un fichier en cours d'utilisation (Linux)

duketwo
la source
4
tronquer: impossible d'ouvrir '/var/lib/docker/containers/*/*-json.log' pour l'écriture: aucun fichier ou répertoire de ce type
BTR Naidu
2
@BTRNaidu vous devez l'exécuter en tant que root / sudo, le contenu de containersn'est pas disponible autrement.
spydon
25
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"- travaillé pour moi
Jeff S.
7
Ignorez les deux professionnels ci-dessus. Si vous n'êtes pas sûr, vous pouvez simplement vérifier avec "ls /var/lib/docker/containers/*/*-json.log" ce qui est tronqué.
duketwo
1
après avoir vidé le fichier journal, j'obtiens cette erreur:error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value
arcol
42

Sur Docker pour Windows et Mac, et probablement d'autres aussi, il est possible d'utiliser l'option tail. Par exemple:

docker logs -f --tail 100

De cette façon, seules les 100 dernières lignes sont affichées, et vous n'avez pas besoin de faire défiler d'abord 1 million de lignes ...

(Et donc, la suppression du journal est probablement inutile)

Egbert Nierop
la source
12
L'idée est de nettoyer les fichiers journaux et de ne pas imprimer les n dernières lignes de fichiers journaux
Youssouf Maiga
41
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
Richard
la source
4
Pour obtenir la taille des journaux sudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log", pour obtenir uniquement le total de la taille des journauxsudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log | grep total"
Daniel F
Existe-t-il des problèmes avec dockerd / aufs ignorant et incapable de supprimer les fichiers journaux pivotés?
ThorSummoner
Cette commande a fonctionné pour moi, contrairement aux autres commandes de ce SO. Si cela importe, j'exécute Docker version 18 sur CentOS 7
Tundra Fizz
27

Vous pouvez configurer logrotate pour effacer périodiquement les journaux.

Exemple de fichier dans /etc/logrotate.d/docker-logs

/var/lib/docker/containers/*/*.log {
 rotate 7
 daily
 compress
 size=50M
 missingok
 delaycompress
 copytruncate
}
AlexPnt
la source
et comment l'utiliser? il est utilisé par défaut avec docker run? le fichier /etc/logrotate.d/docker-logsn'existe pas, je dois le créer?
Carlos.V
Vous devez appeler l'utilitaire logrotate (logrotate <config-file>) et il lira votre configuration et exécutera le nettoyage. Vous pouvez également le définir comme un travail cron par exemple.
AlexPnt
Le problème avec celui-ci est qu'il peut ne pas être correctement synchronisé avec ce que fait Docker. L'utilisation de la fonction Docker est probablement beaucoup plus sage. ( "log-opts"comme le montre BMitch)
Alexis Wilke
12

Docker4Mac, une solution 2018:

LOGPATH=$(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- truncate -s0 $LOGPATH

La première ligne obtient le chemin du fichier journal, similaire à la réponse acceptée.

La deuxième ligne utilise nsenterqui vous permet d'exécuter des commandes dans la xhyvemachine virtuelle qui sert d' hôte pour tous les conteneurs Docker sous Docker4Mac. La commande que nous exécutons est le familier truncate -s0 $LOGPATHdes réponses non-Mac.

Si vous utilisez docker-compose, la première ligne devient:

local LOGPATH=$(docker inspect --format='{{.LogPath}}' $(docker-compose ps -q <service>))

et <service>est le nom du service de votre docker-compose.ymlfichier.

Merci à https://github.com/justincormack/nsenter1 pour l' nsenterastuce.

elifiner
la source
4
Et pour tronquer les journaux de tous les conteneurs, vous pouvez utiliser un caractère générique shell comme indiqué dans les autres réponses, il ne s'agit donc que d'une seule commande:docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- sh -c 'truncate -s0 /var/lib/docker/containers/*/*-json.log'
bradenm
11

Vous ne pouvez pas le faire directement via une commande Docker.

Vous pouvez soit limiter la taille du journal, soit utiliser un script pour supprimer les journaux liés à un conteneur. Vous pouvez trouver des exemples de scripts ici (lus à partir du bas): Fonctionnalité: Possibilité d'effacer l'historique des journaux # 1083

Consultez la section de journalisation de la référence de fichier docker-compose, où vous pouvez spécifier des options (telles que la rotation du journal et la limite de taille du journal) pour certains pilotes de journalisation.

Tristan
la source
7

En tant qu'utilisateur root , essayez d'exécuter ce qui suit:

>  /var/lib/docker/containers/*/*-json.log

ou

cat /dev/null > /var/lib/docker/containers/*/*-json.log

ou

echo "" > /var/lib/docker/containers/*/*-json.log
matson kepson
la source
6

Sur mes serveurs Ubuntu même en tant que sudo j'obtiendrais Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory

Mais peigner le docker inspecter et tronquer les réponses a fonctionné:

sudo truncate -s 0 `docker inspect --format='{{.LogPath}}' <container>`
aqwan
la source
2

Je préfère celui-ci (parmi les solutions ci-dessus):

truncate -s 0 /var/lib/docker/containers/*/*-json.log

Cependant, j'utilise plusieurs systèmes (Ubuntu 18.x Bionic par exemple), où ce chemin ne fonctionne pas comme prévu. Docker est installé via Snap, donc le chemin vers les conteneurs ressemble plus à:

truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log
igraczech
la source
1

Vous pouvez également fournir les paramètres de journalisation sur la docker runligne de commande, comme ceci:

docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest

ou dans un docker-compose.yml comme celui-ci

my-app:
image: my-app:latest
logging:
    driver: "json-file"
    options:
        max-file: "5"
        max-size: 10m

Crédits: https://medium.com/@Quigley_Ja/rotating-docker-logs-keeping-your-overlay-folder-small-40cfa2155412 (James Quigley)

Dag Baardsen
la source
Les valeurs des paramètres doivent être citées (c'est-à "5"- dire et "10m"respectivement), comme illustré ici pour le fichier global daemon.json, mais c'est la même chose pour un docker-compose.yml. Dans les deux cas, cela n'affectera que les conteneurs nouvellement créés.
Adrian W
@AdrianW: docker-compose.yml n'a pas besoin de guillemets. Ce sont des formats de fichiers entièrement différents. Et oui, vous avez raison: les commandes "docker run" et les paramètres docker-compose n'affectent que les conteneurs nouvellement créés - contrairement à la réponse ici avec le plus de votes qui n'affecte que les démons dockerd redémarrés et est disponible via un accès root uniquement. Ma réponse est censée montrer un chemin beaucoup plus simple et mis à jour que l'édition que le redémarrage de l'ensemble du processus dockerd.
Dag Baardsen
Sans guillemets, j'obtiens: ERREUR: pour l'application Impossible de créer un conteneur pour l'application de service: json: ne peut pas démarshal nombre dans le champ Go struct LogConfig.Config de type chaîne Si je cite comme ceci: "5"cela fonctionne. Le 10mtravail sans citer en effet.
Adrian W
Il semble qu'il y ait une différence entre Docker pour Windows et Docker pour Linux. Sur ce dernier, je dois mettre les valeurs entre guillemets. Pas sur le premier. Mise à jour de la description pour s'adapter aux deux. Merci, @AdrianW
Dag Baardsen
0

Utilisateurs de Docker pour Mac, voici la solution:

    1. Trouvez le chemin du fichier journal par:

      $ docker inspect | grep log

    1. SSH dans la machine docker (supposez que le nom est default, sinon, exécutez docker-machine lspour le savoir):

      $ docker-machine ssh default

    1. Changez en utilisateur root ( référence ):

      $ sudo -i

    1. Supprimez le contenu du fichier journal:

      $ echo "" > log_file_path_from_step1

Jinsong Li
la source
2
docker-machine ne fonctionne pas avec Docker pour Mac. Vous pouvez exécuter à la place "run docker -ti -v / var / lib / docker / conteneurs: / var / CentOS création bash" puis "troncature --size 0 /var/inception/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de-json.log"
Jamshid
Vous pouvez utiliser docker exec -it default shpour entrer un shell sh dans un conteneur. Cependant, de nombreux conteneurs ne rendent pas implicitement la sudocommande disponible.
Dag Baardsen