web-dev-qa-db-fra.com

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 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

Évidemment, il y a une erreur là-dedans, mais je me demande comment puis-je obtenir plus d'informations sur ce que fait Docker en cours d'exécution. par exemple, cela fonctionne:

$ docker run image ls
usr bin ...

Mais cela ne veut pas:

$ 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 aurait une meilleure façon.

Existe-t-il un moyen de définir Docker pour qu'il soit plus détaillé?

MODIFIER : 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, le problème est toujours de savoir comment déboguer quelque chose comme ça ou obtenir des informations sur pourquoi ls -l a échoué pourquoi ls ne l'a pas fait.

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

104
estani

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

Commencez d'abord docker events En arrière-plan pour voir ce qui se passe.

docker events&

Exécutez ensuite votre commande docker run ... Défaillante. Ensuite, vous devriez 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 l'id hex de démarrage du message précédent ou la sortie de la commande d'exécution. Ensuite, vous pouvez l'utiliser avec la commande logs:

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

Vous devriez maintenant voir une sortie du démarrage de l'image qui a échoué.

Comme l'a suggéré @alexkb dans un commentaire: docker events& Peut être gênant 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'extraire l'ID hexadécimal du conteneur des journaux dans /var/log/ecs/ecs-agent.log.<DATE>. Utilisez ensuite docker logs <hex id>.

110
Peter Lamberg

Eh bien, le meilleur que j'ai découvert 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 vraiment n'importe quoi ... eh bien, il s'agit simplement de communiquer avec le démon, donc vous ne voulez pas déboguer le client mais le démon lui-même (normalement).

18
estani

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 du conteneur s'afficheront également ici.

15
claytond

Je ne peux pas répondre à votre question sur la façon de rendre la sortie du docker plus complète, mais je peux vous dire que l'expression régulière sur place remplaçant une chaîne dans un fichier .so est un peu folle: la chaîne n'a qu'un espace alloué, et si vous modifiez les décalages de fichier des autres entrées, le fichier elf est corrompu. Essayez d'exécuter objdump ou readelf sur votre fichier .so après avoir exécuté la commande Perl ( avant la modification de LD_LIBRARY_PATH ) en dehors d'un conteneur - dollars pour les beignets, c'est maintenant corrompu.

La raison pour laquelle cela fonctionne dans ce hack malheureusement nécessaire 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 vos chemins souhaités sont immuables, reconstruisez la bibliothèque et changez le chemin par défaut pour/etc/hosts dans la source. Ou mieux, lors de la création de votre libnss_files.so le renommer en quelque chose comme libnss_altfiles.so et changez nsswitch.conf utiliser hosts: altfiles lors du démarrage de votre conteneur Docker (sauf si Docker a également lié nsswitch.conf monté, vous ne pouvez pas le modifier). Cela vous permettra d'avoir le libnss_altfiles.so en parallèle avec vos bibliothèques normales dans le système de base. Si Docker effectue le montage de liaison nsswitch.conf, laissez une copie de votre fichier libnss_files.so reconstruit dans votre répertoire/lib-override prêt à être chargé 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: recommencer à utiliser le/etc/hosts par défaut) si vous utilisez ces variables.

3
Andrew Domaszek

Parfois, vous pouvez trouver des messages d'erreur utiles en sshing dans le nœud exécutant 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 au docker vm en faisant:

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