Comment puis-je déboguer une initialisation de conteneur docker?

93

J'ai eu un problème avec un conteneur, même s'il construit parfaitement, il ne démarre pas correctement. La cause est une solution de contournement que j'ai ajoutée au fichier Docker (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 docker fait 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 une meilleure solution.

Existe-t-il un moyen de rendre le docker plus bavard?

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 soit bien comprise). Maintenant , la question est encore comment pourrais - je déboguer quelque chose comme ça ou obtenir des faces intérieures à pourquoi ls -l échoué pourquoi ls ne l' ont pas.

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

estani
la source
S'il vous plaît, faites l'effort de marquer l'une des réponses comme "acceptée", merci!
Brian Topping

Réponses:

95

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

Commencez docker eventsen arrière-plan pour voir ce qui se passe.

docker events&

Ensuite, exécutez votre docker run ...commande en échec . Ensuite, vous devriez voir quelque chose comme l’écran suivant:

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

Vous pouvez ensuite obtenir l'ID hexadécimal 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 ayant échoué.

Comme @alexkb l'a suggéré dans un commentaire: cela 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 de conteneur hexadécimal des journaux /var/log/ecs/ecs-agent.log.<DATE>. Ensuite, utilisez docker logs <hex id>.

Peter Lamberg
la source
Très utile! Nouveau chez Docker et essayait de faire fonctionner Portainer. Résolu avec ces étapes de débogage. J'ai trouvé quelqu'un sur Medium.com avec le même problème: medium.com/@jameson_37151/…
Jameson
Je reçois "conteneur non trouvé" !?
hérisson dément
Étrange. Juste pour vous assurer, @dementedhedgehog avez-vous essayé de copier l'ID hexadécimal du message de log se terminant par " (from xxx/xxx:latest) die"?
Peter Lamberg
1
Merci beaucoup cette réponse, c'est une bouée de sauvetage. La seule chose à ajouter est que cela 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 donc être plus facile d’obtenir l’ID conteneur hexadécimal des journaux /var/log/ecs/ecs-agent.log.<DATE>. Puis utilisez docker logs <hex id>comme suggéré par cette réponse pour voir pourquoi les choses ne démarrent pas.
alexkb
1
@alexkb Merci! J'ai ajouté votre suggestion à la fin de la réponse pour que d'autres puissent la trouver plus facilement.
Peter Lamberg
18

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 quoi que ce soit réellement ... eh bien, il ne s'agit que de communiquer avec le démon, vous ne voulez donc pas déboguer le client mais le démon lui-même (normalement).

estani
la source
13

Dans mon cas, le -adrapeau (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 de conteneur s’affichent également ici.

claytond
la source
3

Je ne peux pas répondre à votre question sur la manière de rendre la sortie de docker plus complète, mais je peux vous dire que le remplacement rationnel d'une chaîne sur une chaîne dans un fichier .so est un peu fou: la chaîne ne dispose que de beaucoup d'espace, 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 que LD_LIBRARY_PATH ne soit modifié ) en dehors d’un conteneur - les dollars en donuts sont maintenant corrompus.

La raison pour laquelle cela fonctionne dans ce hack tristement nécessaire est 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 désirés ne sont pas modifiables, reconstruisez la bibliothèque et modifiez le chemin par défaut pour / etc / hosts dans la source. Ou mieux, lors de la création de votre modification, libnss_files.sorenommez-la libnss_altfiles.soet changez-la nsswitch.confpour hosts: altfilesdémarrer votre conteneur de docker (sauf si docker a également lié nsswitch.conf monté, vous ne pouvez pas le changer). Cela vous permettra d’avoir libnss_altfiles.so en parallèle avec vos bibliothèques normales dans le système de base. Si docker effectue le montage lié 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 tête-à-tête, les fichiers binaires suid / sgid ignorent LD_LIBRARY_PATH et LD_PRELOAD, ainsi certaines choses vont s'interrompre (lisez: retournez à l'aide de / etc / hosts par défaut) si vous utilisez ces variables.

Andrew Domaszek
la source
Merci beaucoup pour la grande perspicacité ... J'étais trop rapide et vois maintenant ce qui se passe. Je ne sais toujours pas pourquoi obtenir la stat doit résoudre un hôte (ls -l) tandis que le simple fichier liste (ls), ne fonctionne pas ...
estani
0

Parfois, vous pouvez trouver des messages d'erreur utiles en envoyant un message sur le nœud exécutant le démon docker, puis en effectuant:

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

Sur «Docker Community Edition» sous Mac OS, vous pouvez vous connecter à docker vm en procédant comme suit:

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