Come posso eseguire il debug di un'inizializzazione del contenitore docker?


93

Ho avuto un problema con un contenitore, anche se si costruisce perfettamente non si avvia correttamente. La causa è una soluzione alternativa che ho aggiunto al Dockerfile (per avere un routing autoconfigurato / etc / hosts)

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

Ovviamente c'è qualche errore lì dentro, ma mi chiedo come posso ottenere maggiori informazioni su cosa sta facendo la finestra mobile durante l'esecuzione. ad esempio, funziona:

$ docker run image ls
usr bin ...

Ma questo non:

$ docker run image ls -l
$

Non c'è nulla nei registri e nemmeno io posso chiamare una shell interattiva. Posso usare strace per vedere cosa sta succedendo ma speravo che ci fosse un modo migliore.

Esiste un modo per impostare la finestra mobile in modo più dettagliato?

EDIT : Grazie ad Andrew D. Ora so cosa c'è che non va nel codice sopra (l'ho lasciato in modo che la sua risposta possa essere compresa). Ora la questione è ancora come avrei potuto eseguire il debug di qualcosa di simile a questo o ottenere alcune parti interne al motivo per cui ls -l fallito perché ls non ha fatto.

EDIT : -D = true potrebbe dare più output, anche se non nel mio caso ...


Si prega di fare uno sforzo per contrassegnare una delle risposte come "accettate", grazie!
Brian Topping il

Risposte:


95

Il eventscomando Docker può essere d'aiuto e il comando Log loger può recuperare i log anche dopo il mancato avvio dell'immagine.

Primo avvio docker eventsin background per vedere cosa sta succedendo.

docker events&

Quindi eseguire il docker run ...comando non riuscito . Quindi dovresti vedere qualcosa di simile sullo schermo:

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

Quindi è possibile ottenere l'id esadecimale di avvio dal messaggio precedente o dall'output del comando run. Quindi puoi usarlo con il comando logs:

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

Ora dovresti vedere alcuni output dall'avvio dell'immagine fallito.

Come suggerito da @alexkb in un commento: docker events&può essere problematico se il contenitore viene costantemente riavviato da qualcosa come il servizio AWS ECS. In questo scenario potrebbe essere più semplice estrarre l'ID esadecimale del contenitore dai log /var/log/ecs/ecs-agent.log.<DATE>. Quindi utilizzare la finestra mobile logs <hex id>.


Molto utile! Nuovo per docker e stavo cercando di far funzionare Portainer. Risolto con questi passaggi di debug. Trovato qualcuno su Medium.com con lo stesso problema: medium.com/@jameson_37151/…
Jameson

Ottengo "contenitore non trovato" !?
Demented Hedgehog

Strano. Solo per essere sicuro, @dementedhedgehog hai provato a copiare l'id esadecimale dal messaggio di registro che termina con " (from xxx/xxx:latest) die"?
Peter Lamberg,

1
Grazie mille questa risposta, è un salvavita. L'unica cosa da aggiungere è che docker events&può essere problematico se il contenitore viene costantemente riavviato da qualcosa come il servizio AWS ECS. Quindi, in questo scenario, potrebbe essere più semplice estrarre l'ID esadecimale del contenitore dai log /var/log/ecs/ecs-agent.log.<DATE>. Quindi utilizzare docker logs <hex id>come suggerito da questa risposta per capire perché le cose non si stanno avviando.
alexkb,

1
@alexkb Grazie! Ho aggiunto il tuo suggerimento alla fine della risposta in modo che altri possano trovarlo più facilmente.
Peter Lamberg,

18

Bene, il migliore che ho scoperto finora è:

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

Basta avviare il client da una nuova shell. L'idea sbagliata era di pensare che il client effettivamente facesse qualsiasi cosa ... beh, stava solo comunicando con il demone, quindi non si vuole eseguire il debug del client ma il demone stesso (normalmente).


13

Nel mio caso, il -aflag (allegare a STDOUT / STDERR) era abbastanza:

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

Ha mostrato l'errore di avvio (nel nostro caso, un percorso di log mancante utilizzato da supervisord). Presumo che la maggior parte degli errori di avvio del contenitore vengano visualizzati anche qui.


3

Non posso rispondere alla tua domanda su come rendere più completa l'output della finestra mobile, ma posso dirti che regex sul posto che sostituisce una stringa in un file .so è un po 'folle: la stringa ha solo così tanto spazio allocato ad esso, e se si modificano gli offset dei file di altre voci, il file elf viene danneggiato. Prova a eseguire objdump o leggiti sul tuo file .so dopo aver eseguito il comando perl ( prima della modifica di LD_LIBRARY_PATH ) al di fuori di un contenitore: dollari a ciambelle ora sono corrotti.

Il motivo per cui funziona in questo trucco purtroppo necessario è perché "tmp" ed "etc" hanno la stessa lunghezza di stringa, quindi non cambia alcun offset. Considera la directory / dkr o simile se preferisci non usare / tmp.

Se DEVI adottare questo approccio e i percorsi desiderati sono immutabili, ricostruisci la libreria e modifica il percorso predefinito per / etc / hosts nel sorgente. O meglio, quando costruisci il tuo modificato, libnss_files.sorinominalo in qualcosa di simile libnss_altfiles.soe cambia nsswitch.confin uso hosts: altfilesquando avvii il tuo contenitore docker (a meno che la docker non abbia anche montato nsswitch.conf, quindi non puoi cambiarlo). Questo ti permetterà di avere libnss_altfiles.so in parallelo con le tue normali librerie nel sistema di base. Se la finestra mobile esegue il bind-mount di nsswitch.conf, lascia una copia del tuo libnss_files.so ricostruito nella tua directory / lib-override pronta per essere caricata da LD_LIBRARY_PATH.

Come avvertimento, i binari suid / sgid ignorano LD_LIBRARY_PATH e LD_PRELOAD, quindi alcune cose si romperanno (leggi: torna a usare l'impostazione predefinita / etc / hosts) se usi queste variabili.


Grazie mille per l'ottima intuizione ... Ero troppo veloce e vedo ora cosa sta succedendo. Ancora non so perché ottenere la stat debba risolvere un host (ls -l) mentre la semplice lista dei file (ls), non ...
estani,

0

A volte, è possibile trovare utili messaggi di errore immettendosi nel nodo che esegue il daemon docker e quindi facendo:

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

Su 'Docker Community edition' su Mac OS, puoi connetterti alla docker vm facendo:

$  screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.