Como posso depurar uma inicialização do contêiner do Docker?

62

Eu tive um problema com um contêiner, mesmo que ele seja construído perfeitamente, não é iniciado corretamente. A causa é uma solução 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, mas eu 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. Eu posso usar strace para ver o que está acontecendo, mas eu esperava que houvesse uma maneira melhor.

Existe alguma maneira de definir o docker para ser mais detalhado?

EDITAR : Obrigado a Andrew D. Agora sei o que há de errado com o código acima (deixei para que sua resposta seja compreendida). Agora, o problema ainda é como depurar algo assim ou obter algumas informações sobre o motivo pelo qual o ls -l falhou porque o ls não o fez.

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

    
por estani 19.05.2014 / 17:28

4 respostas

63

O comando Docker events pode ajudar e o comando Registros do Docker pode buscar logs mesmo após a imagem falhou ao iniciar.

Primeiro inicie docker events no fundo para ver o que está acontecendo.

docker events&

Em seguida, execute seu comando docker run ... 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 de execução. Então você pode usá-lo com o comando logs:

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

Você deve ver agora alguma saída da inicialização da imagem com falha.

Como @alexkb sugeriu em um comentário: docker events& pode ser problemático se seu contêiner estiver sendo constantemente reiniciado 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 em /var/log/ecs/ecs-agent.log.<DATE> . Em seguida, use o docker logs <hex id> .

    
por 22.12.2015 / 14:24
16

Bem, o melhor que descobri até agora é:

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

Apenas inicie o cliente a partir de um novo shell. O equívoco era pensar que o cliente realmente faz alguma coisa ... bem, é só comunicar com o daemon, então você não quer depurar o cliente, mas o próprio daemon (normalmente).

    
por 26.05.2014 / 11:07
8

No meu caso, o sinalizador -a (anexar a 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 ). Eu suponho que a maioria dos erros de inicialização do contêiner apareceria aqui também.

    
por 29.03.2016 / 15:27
2

Não consigo responder à sua pergunta sobre como tornar a saída do Docker mais completa, mas posso dizer que o regex no local que substitui uma cadeia em um arquivo .so é um pouco insano: a cadeia tem apenas muito espaço alocado para e, se você alterar os deslocamentos de arquivo de outras entradas, o arquivo elf ficará corrompido. Tente executar o objdump ou readelf 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 donuts agora está corrompido.

A razão pela qual funciona neste hack infelizmente necessário é porque "tmp" e "etc" são o mesmo comprimento de string, então nenhum deslocamento muda. Considere o diretório / dkr ou similar se você preferir não usar / tmp.

Se você DEVE adotar esta abordagem e seus caminhos desejados forem imutáveis, reconstrua a biblioteca e altere o caminho padrão para / etc / hosts na origem. Ou melhor, ao criar seu libnss_files.so modificado, renomeie-o para algo como libnss_altfiles.so e altere nsswitch.conf para usar hosts: altfiles ao iniciar seu contêiner docker (a menos que o docker tenha o nsswitch.conf montado por ligação também. mude). Isso permitirá que você tenha o libnss_altfiles.so em paralelo com suas bibliotecas normais no sistema base. Se o docker não montar o 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 heads-up, suid / sgid binários ignoram LD_LIBRARY_PATH e LD_PRELOAD, então algumas coisas vão quebrar (leia: volte a usar o padrão / etc / hosts) se você usar essas variáveis.

    
por 19.05.2014 / 23:01