164 votes

Comment déboguer l'initialisation d'un conteneur Docker ?

J'ai eu un problème avec un conteneur, même s'il se construit parfaitement, il ne démarre pas correctement. La cause en est une solution de contournement que j'ai ajoutée au Dockerfile (pour avoir un routage /etc/hosts auto-configuré)

RUN mkdir -p -- /lib-override /etc-override && cp /lib/libnss_files.so.2 /lib-override
ADD hosts.template /etc-override/hosts
RUN perl -pi -e 's:/etc/hosts:/etc-override/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override

Il est évident qu'il y a une erreur, mais je me demande comment je peux obtenir plus d'informations sur ce que fait docker pendant son exécution. par exemple, ceci fonctionne :

$ docker run image ls
usr bin ...

Mais ce n'est pas le cas :

$ docker run image ls -l
$

Il n'y a rien dans les journaux et je ne peux pas non plus appeler un Shell interactif. Je peux utiliser strace pour voir ce qui se passe mais j'espérais qu'il y ait une meilleure solution.

Y a-t-il un moyen de configurer docker pour qu'il soit plus verbeux ?

EDIT : Merci à Andrew D. Je sais maintenant ce qui ne va pas avec le code ci-dessus (je l'ai laissé pour que sa réponse puisse être comprise). Maintenant, la question est de savoir comment je peux déboguer quelque chose comme ça ou comprendre pourquoi ls -l a échoué pourquoi ls ne l'a pas fait.

EDIT : Le -D=true pourrait donner plus de résultats, mais pas dans mon cas...

0 votes

Veuillez faire l'effort de marquer une des réponses comme "acceptée", merci !

174voto

Peter Lamberg Points 1656

Docker events peut aider et Journaux Docker peut récupérer les journaux même après l'échec du démarrage de l'image.

Premier départ docker events en arrière-plan pour voir ce qui se passe.

docker events&

Ensuite, exécutez votre échec docker run ... commande. Vous devriez alors voir quelque chose comme ce qui suit à l'écran :

2015-12-22T15:13:05.503402713+02:00 xxxxxxxacd8ca86df9eac5fd5466884c0b42a06293ccff0b5101b5987f5da07d: (from xxx/xxx:latest) die

Ensuite, vous pouvez obtenir le code hexadécimal de démarrage à partir du message précédent ou de la sortie de la commande run. Vous pouvez ensuite l'utiliser avec la commande logs :

docker logs <copy the instance id from docker events messages on screen>

Vous devriez maintenant voir des résultats de l'échec du démarrage de l'image.

Comme l'a suggéré @alexkb dans un commentaire : docker events& peut être problématique si votre conteneur est constamment redémarré à partir de quelque chose comme le service AWS ECS. Dans ce scénario, il peut être plus facile d'obtenir l'identifiant hex du conteneur à partir des journaux dans la rubrique /var/log/ecs/ecs-agent.log.<DATE> . Utilisez ensuite docker logs <hex id> .

0 votes

Très utile ! Je suis nouveau dans Docker et j'essayais de faire fonctionner Portainer. Je l'ai résolu avec ces étapes de débogage. J'ai trouvé quelqu'un sur Medium.com qui avait le même problème : medium.com/@jameson_37151/

1 votes

J'obtiens "container non trouvé" !?

0 votes

Étrange. Juste pour être sûr, @dementedhedgehog avez-vous essayé de copier l'hex-id du message de log se terminant par " (from xxx/xxx:latest) die " ?

27voto

Girish Kumar Points 1

Eh bien, le mieux que j'ai trouvé jusqu'à présent est :

#stop the current demon and start it in debug modus
sudo service docker stop
dockerd -D # --debug

Il suffit de démarrer le client à partir d'un nouveau Shell. L'idée fausse était de penser que le client fait quelque chose du tout... en fait, il ne fait que communiquer avec le démon, donc vous ne voulez pas... déboguer le client mais le démon lui-même (normalement).

1 votes

Je ne comprends pas vraiment. Mais j'ai exécuté vos commandes (avec sudo dockerd -D # --debug ) et maintenant tous mes conteneurs démarrent comme prévu :)

22voto

Gorm Casper Points 135

Dans mon cas, le -a (attacher à STDOUT/STDERR) était suffisant :

user@machine:~$ docker start -a server_name
Error: The directory named as part of the path /log/log_path/app.log does not exist.
For help, use /usr/bin/supervisord -h

Il a montré l'erreur de démarrage (dans notre cas, un chemin de journal manquant utilisé par supervisord ). Je suppose que la plupart des erreurs de démarrage des conteneurs apparaîtraient également ici.

0 votes

Fabuleux, merci.

4voto

Andrew Domaszek Points 5073

Je ne peux pas répondre à votre question sur la façon de rendre la sortie de docker plus complète, mais je peux vous dire que le remplacement d'une chaîne dans un fichier .so par une regex en place est un peu fou : la chaîne n'a qu'un espace limité qui lui est alloué, et si vous modifiez les offsets de fichier des autres entrées, le fichier elf devient corrompu. Essayez d'exécuter objdump ou readelf sur votre fichier .so après avoir exécuté la commande perl ( avant le changement de LD_LIBRARY_PATH ) à l'extérieur d'un conteneur. Je vous parie que c'est maintenant corrompu.

La raison pour laquelle cela fonctionne dans ce piratage tristement nécessaire c'est parce que "tmp" et "etc" ont la même longueur de chaîne, donc aucun décalage ne change. Considérez le répertoire /dkr ou similaire si vous préférez ne pas utiliser /tmp.

Si vous DEVEZ adopter cette approche et que les chemins souhaités ne sont pas modifiables, reconstruisez la bibliothèque et changez le chemin par défaut pour /etc/hosts dans les sources. Ou mieux, lors de la construction de votre libnss_files.so le renommer en quelque chose comme libnss_altfiles.so et le changement nsswitch.conf à utiliser hosts: altfiles lors du démarrage de votre conteneur docker (à moins que docker n'ait également monté bind nsswitch.conf, alors vous ne pouvez pas le modifier). Cela vous permettra d'avoir la libnss_altfiles.so en parallèle avec vos bibliothèques normales dans le système de base. Si docker fait bind-mount nsswitch.conf, laissez une copie de votre libnss_files.so reconstruite dans votre répertoire /lib-override prête à être chargée par LD_LIBRARY_PATH.

En guise d'avertissement, les binaires suid/sgid ignorent LD_LIBRARY_PATH et LD_PRELOAD, donc certaines choses vont se casser (lire : revenir à l'utilisation du /etc/hosts par défaut) si vous utilisez ces variables.

0 votes

Merci beaucoup pour cette grande perspicacité... J'ai été trop rapide et je vois maintenant ce qui se passe. Je ne sais toujours pas pourquoi l'obtention du stat doit résoudre un hôte (ls -l) alors que la simple liste de fichiers (ls), ne le fait pas...

3voto

user674669 Points 159

Parfois, vous pouvez trouver des messages d'erreur utiles en vous connectant par sshing au nœud qui exécute le démon Docker, puis en faisant :

$ tail -f /var/log/containers/* /var/log/docker.log 2>&1

Sur 'Docker Community edition' sur Mac OS, vous pouvez vous connecter à la vm docker en faisant :

$  screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

0 votes

tty n'existe pas pour moi (macOS 11.2.3, Docker 20.10.5)

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X