Como depurar uma inicialização de contêiner de docker?

93

Eu tive um problema com um contêiner, mesmo que ele crie perfeitamente, ele não inicia corretamente. A causa é uma solução alternativa que eu adicionei ao Dockerfile (por ter um roteamento / etc / hosts auto-configurado)

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

Obviamente, há algum erro lá, mas me pergunto como posso obter mais informações sobre o que o docker está fazendo durante a execução. por exemplo, isso funciona:

$ docker run image ls
usr bin ...

Mas isso não acontece:

$ docker run image ls -l
$

Não há nada nos logs e também não posso chamar um shell interativo. Posso usar strace para ver o que está acontecendo, mas esperava que houvesse uma maneira melhor.

Existe alguma maneira de definir a janela de encaixe para ser mais detalhada?

EDIT : Graças a Andrew D. Agora eu sei o que há de errado com o código acima (deixei para que sua resposta possa ser entendida). Agora, a questão ainda é como eu pode depurar algo parecido com isso ou obter algumas entranhas o motivo pelo qual ls -l falhou porque ls não.

EDIT : O -D = true pode dar mais saída, embora não no meu caso ...

estani
fonte
Faça um esforço para marcar uma das respostas como "aceita", obrigado!
Brian Topping

Respostas:

95

O eventscomando Docker pode ajudar e o comando Docker logs pode buscar logs mesmo após a falha na inicialização da imagem.

Primeiro comece docker eventsem segundo plano para ver o que está acontecendo.

docker events&

Em seguida, execute seu docker run ...comando com falha . Então você deve ver algo como o seguinte na tela:

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

Em seguida, você pode obter o ID hexadecimal de inicialização da mensagem anterior ou a saída do comando run. Então você pode usá-lo com o comando logs:

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

Agora você deve ver alguma saída da falha na inicialização da imagem.

Como o @alexkb sugeriu em um comentário: docker events&pode ser problemático se o contêiner estiver sendo constantemente reiniciado a partir de algo como o serviço AWS ECS. Nesse cenário, pode ser mais fácil obter o ID hexadecimal do contêiner dos logs /var/log/ecs/ecs-agent.log.<DATE>. Em seguida, use a janela de encaixe logs <hex id>.

Peter Lamberg
fonte
Muito útil! Novo no docker e estava tentando colocar o portainer em execução. Resolvido com estas etapas de depuração. Encontrei alguém no Medium.com com o mesmo problema: medium.com/@jameson_37151/…
Jameson
Recebo "contêiner não encontrado" !?
ouriço demente Dem
Estranho. Só para garantir, @dementedhedgehog você tentou copiar o ID hexadecimal da mensagem de log que termina em " (from xxx/xxx:latest) die"?
Peter Lamberg
1
Muito obrigado esta resposta, é um salva-vidas. A única coisa a acrescentar é que isso docker events&pode ser problemático se o contêiner estiver sendo constantemente reiniciado a partir de algo como o serviço AWS ECS. Portanto, nesse cenário, pode ser mais fácil obter o ID hexadecimal do contêiner dos logs /var/log/ecs/ecs-agent.log.<DATE>. Em seguida, use docker logs <hex id>como sugerido por esta resposta para ver por que as coisas não estão inicializando.
alexkb
1
@alexkb Thanks! Adicionei sua sugestão ao final da resposta para que outros a encontrem mais facilmente.
Peter Lamberg
18

Bem, o melhor que descobri até agora é:

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

Basta iniciar o cliente a partir de um novo shell. O equívoco era pensar que o cliente realmente faz alguma coisa ... bem, está apenas se comunicando com o daemon, para que você não queira depurar o cliente, mas o próprio daemon (normalmente).

estani
fonte
13

No meu caso, o -asinalizador (anexar ao STDOUT / STDERR) foi suficiente:

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

Ele mostrou o erro de inicialização (no nosso caso, um caminho de log ausente usado por supervisord). Suponho que a maioria dos erros de inicialização do contêiner apareça aqui também.

claytond
fonte
3

Não consigo responder à sua pergunta sobre como tornar a saída do Docker mais completa, mas posso dizer que a regex no local que substitui uma sequência em um arquivo .so é um pouco insana: a sequência possui apenas muito espaço alocado e se você alterar as compensações de arquivo de outras entradas, o arquivo elf será corrompido. Tente executar o objdump ou leia-se no seu arquivo .so depois de executar o comando perl ( antes da alteração do LD_LIBRARY_PATH ) fora de um contêiner - dólares para rosquinhas agora estão corrompidos.

A razão pela qual ele funciona nesse hack, infelizmente necessário, é porque "tmp" e "etc" têm o mesmo comprimento de string, portanto, nenhuma compensação é alterada. Considere o diretório / dkr ou similar, se você preferir não usar / tmp.

Se você DEVE adotar essa abordagem e os caminhos desejados são imutáveis, reconstrua a biblioteca e altere o caminho padrão para / etc / hosts na fonte. Ou melhor, ao criar o seu modificado, libnss_files.sorenomeie-o para algo como libnss_altfiles.soe mude nsswitch.confpara usar hosts: altfilesao iniciar o contêiner do docker (a menos que o docker também tenha o nsswitch.conf montado no bind, então você não poderá alterá-lo). Isso permitirá que você libnss_altfiles.so seja paralelo às suas bibliotecas normais no sistema base. Se o docker ligar o mount nsswitch.conf, deixe uma cópia do seu libnss_files.so reconstruído no diretório / lib-override pronto para ser carregado pelo LD_LIBRARY_PATH.

Como um alerta, os binários suid / sgid ignoram LD_LIBRARY_PATH e LD_PRELOAD, portanto, algumas coisas serão interrompidas (leia-se: volte a usar o / etc / hosts padrão) se você usar essas variáveis.

Andrew Domaszek
fonte
Muito obrigado pela ótima visão ... Fui rápido demais e agora vejo o que está acontecendo. Eu ainda não sei por que recebendo o status precisa resolver um host (ls -l) enquanto o arquivo simples listagem (ls), não ...
Estani
0

Às vezes, você pode encontrar mensagens de erro úteis sshing no nó executando o daemon do docker e, em seguida, executando:

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

Na 'Docker Community edition' no Mac OS, você pode conectar-se ao docker vm fazendo o seguinte:

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