Comment puis-je 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-overrideADD hosts.template /etc-override/hostsRUN perl -pi -e 's:/etc/hosts:/etc-override/hosts:g' /lib-override/libnss_files.so.2ENV LD_LIBRARY_PATH /lib-override

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

$ docker run image lsusr 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 avait un meilleur moyen.

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

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 pourrais-je déboguer quelque chose comme ça ou comprendre pourquoi ls-l échoué pourquoi ls ne l'a pas fait.

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

Docker events la commande peut aider et Journaux Docker la commande peut récupérer les journaux même après le 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 programme docker run ... commande. 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 hexadécimal de démarrage à partir du message précédent ou de la sortie de la commande exécuter. 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 de l'échec du démarrage de l'image.

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

Eh bien, le meilleur que j'ai découvert jusqu'à présent est:

#stop the current demon and start it in debug modussudo service docker stopdockerd -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 réellement n'importe quoi... eh bien, il ne fait que communiquer avec le démon, donc vous ne voulez pas débogage le client mais le démon lui-même (normalement).

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

user@machine:~$ docker start -a server_nameError: 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'afficheraient également ici.

Je ne peux pas répondre à votre question sur la façon de rendre la sortie docker plus complète, mais je peux vous dire que le remplacement d'une expression régulière sur place d'une chaîne dans un fichier .so est un peu insensé: la chaîne n'a que beaucoup d'espace qui lui est 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 le changement de LD_LIBRARY_PATH) en dehors d'un conteneur dollars dollars à beignets, il est maintenant corrompu.

La raison pour laquelle ça marche dans ce hack 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 modifiez le chemin par défaut pour /etc / hosts dans la source. Ou mieux, lors de la construction de votre maison libnss_files.so renommez-le en quelque chose comme libnss_altfiles.so et le changement nsswitch.conf utiliser hosts: altfiles lors du démarrage de votre conteneur docker (sauf si docker a nsswitch monté sur bind.conf aussi, alors vous ne pouvez pas le changer). 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 lie-monte nsswitch.conf, laissez une copie de votre message libnss_files.so dans votre répertoire / lib-override prêt à être chargé par LD_LIBRARY_PATH.

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

Parfois, vous pouvez trouver des messages d'erreur utiles en vous connectant au 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 à la machine virtuelle docker en procédant comme suit:

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

Veuillez faire l’effort de marquer l’une des réponses comme “acceptée”, merci!