Como limpar os logs corretamente para um contêiner do Docker?

210

Eu uso docker logs [container-name]para ver os logs de um contêiner específico.

Existe uma maneira elegante de limpar esses logs?

Youssouf Maiga
fonte
14
Em uma nota, você pode obter o tamanho dos logs viasudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log"
Daniel F

Respostas:

251

A partir desta pergunta, há um one-liner que você pode executar:

echo "" > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

ou há o comando truncado semelhante:

truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

Eu não sou um grande fã de nenhum deles, pois eles modificam os arquivos do Docker diretamente. A exclusão do log externo pode ocorrer enquanto o docker estiver gravando dados formatados em json no arquivo, resultando em uma linha parcial e interrompendo a capacidade de ler todos os logs do docker logsCLI.

Em vez disso, você pode fazer com que o Docker gire os logs automaticamente para você. Isso é feito com sinalizadores adicionais para o dockerd, se você estiver usando o driver de log JSON padrão :

dockerd ... --log-opt max-size=10m --log-opt max-file=3

Você também pode configurá-lo como parte do seu arquivo daemon.json em vez de modificar seus scripts de inicialização:

{
  "log-driver": "json-file",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

Essas opções precisam ser configuradas com acesso root. Certifique-se de executar um systemctl reload dockerapós alterar este arquivo para aplicar as configurações. Essa configuração será o padrão para todos os contêineres criados recentemente. Observe que os contêineres existentes precisam ser excluídos e recriados para receber os novos limites de log.


Opções de log semelhantes podem ser passadas para contêineres individuais para substituir esses padrões, permitindo salvar mais ou menos logs em contêineres individuais. A partir docker rundisso se parece com:

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...

ou em um arquivo de composição:

version: '3.7'
services:
  app:
    image: ...
    logging:
      options:
        max-size: "10m"
        max-file: "3"

Para economizar espaço adicional, é possível alternar do driver de log json para o driver de log "local". Ele usa as mesmas opções de tamanho máximo e arquivo máximo, mas em vez de armazenar no json, ele usa uma sintaxe binária que é mais rápida e menor. Isso permite armazenar mais logs no mesmo tamanho de arquivo. A entrada daemon.json para isso se parece com:

{
  "log-driver": "local",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

A desvantagem do driver local são os analisadores / encaminhadores de logs externos que dependiam do acesso direto aos logs json não funcionarão mais. Portanto, se você usar uma ferramenta como a filebeat para enviar ao Elastic, ou ao encaminhador universal do Splunk, eu evitaria o driver "local".

Eu tenho um pouco mais sobre isso na minha apresentação de Dicas e Truques .

BMitch
fonte
6
Eu fiz um service docker restart que por si só não funcionou. Também tive que criar novos contêineres antes de entrar em vigor. ou seja, apenas abrir os contêineres antigos não aplicou o novo registro
Robbo_UK
Estou usando o Docker 1.13.1 e o 'docker inspeciona --format =' {{. LogPath}} '<ID do contêiner>' retorna uma string nula ("") .... mas ainda estou obtendo saída de ' logs do docker <ID do contêiner> '?!? De onde isso vem e como faço para limpá-lo?
JD Allen
O @JDAllen 1.13.1 está sem suporte há muito tempo. Não tenho um sistema tão antigo para exibir a saída de inspeção.
BMitch 27/03/19
Melhor ainda seria echo -n > .... De qualquer forma, eu gostaria de ter mais controle sobre meus logs. Por exemplo, após a reinicialização do docker-compose , eu adoraria ter o mecanismo para fazer algo com os logs preservados.
NarūnasK
2
@AlexisWilke, se você conseguir parar o docker, provavelmente poderá parar o contêiner. Se você pode fazer o último, recriar o contêiner com as opções de registro seria o meu conselho. O novo contêiner não possui logs antigos e os novos serão rolados automaticamente, resolvendo problemas de curto e longo prazo ao mesmo tempo.
BMitch 27/10/19
227

Usar:

truncate -s 0 /var/lib/docker/containers/*/*-json.log

Você pode precisar de sudo

sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"

ref. Jeff S. Como limpar os logs corretamente para um contêiner do Docker?

Referência: Truncando um arquivo enquanto ele está sendo usado (Linux)

duketwo
fonte
4
truncate: não pode abrir '/var/lib/docker/containers/*/*-json.log' para escrita: Nenhum tal lima ou diretório
BTR Naidu
2
@ BTRNaidu você tem que executá-lo como root / sudo, o conteúdo de containersnão está disponível de outra forma.
spydon
25
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"- funcionou para mim
Jeff S.
7
Ignore os dois profissionais acima. Se você não tiver certeza, basta verificar com "ls /var/lib/docker/containers/*/*-json.log" o que está sendo truncado.
duketwo
1
depois de esvaziar o arquivo de log, recebo este erro:error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value
arcol
42

No Docker para Windows e Mac, e provavelmente outros também, é possível usar a opção tail. Por exemplo:

docker logs -f --tail 100

Dessa forma, apenas as últimas 100 linhas são exibidas e você não precisa rolar primeiro pelas linhas de 1 milhão ...

(E, portanto, excluir o log provavelmente não é necessário)

Egbert Nierop
fonte
12
A ideia é arquivos de log limpas e não para imprimir as últimas n linhas de arquivos de log
Youssouf Maiga
41
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
Richard
fonte
4
Para obter o tamanho dos logs sudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log", obter apenas o tamanho total dos logssudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log | grep total"
Daniel F
Há algum problema com o dockerd / aufs ignorando e incapaz de remover os arquivos de log rotacionados?
ThorSummoner
Este comando funcionou para mim, enquanto os outros comandos neste SO não. Se isso importa, estou executando a versão 18 do Docker no CentOS 7
Tundra Fizz
27

Você pode configurar a rotação do log para limpar os logs periodicamente.

Arquivo de exemplo em /etc/logrotate.d/docker-logs

/var/lib/docker/containers/*/*.log {
 rotate 7
 daily
 compress
 size=50M
 missingok
 delaycompress
 copytruncate
}
AlexPnt
fonte
e como eu uso isso? é usado como padrão com docker run? arquivo /etc/logrotate.d/docker-logsnão existe, eu tenho que criá-lo?
Carlos.V 12/04/19
Você precisa chamar o utilitário logrotate (logrotate <config-file>) e ele lerá sua configuração e executará a limpeza. Você também pode configurá-lo como um trabalho cron, por exemplo.
precisa saber é o seguinte
O problema com este é que ele pode não estar corretamente sincronizado com o que a janela de encaixe está fazendo. Usar o recurso docker é provavelmente muito mais sábio. (o "log-opts"como mostrado por BMitch) #
Alexis Wilke
12

Docker4Mac, uma solução de 2018:

LOGPATH=$(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- truncate -s0 $LOGPATH

A primeira linha obtém o caminho do arquivo de log, semelhante à resposta aceita.

A segunda linha nsenterque permite executar comandos na xhyveVM que servidores como host para todos os contêineres do Docker4Mac. O comando que executamos é o familiar truncate -s0 $LOGPATHdas respostas que não são do Mac.

Se você estiver usando docker-compose, a primeira linha se tornará:

local LOGPATH=$(docker inspect --format='{{.LogPath}}' $(docker-compose ps -q <service>))

e <service>é o nome do serviço do seu docker-compose.ymlarquivo.

Agradecemos a https://github.com/justincormack/nsenter1 pelo nsentertruque.

elifiner
fonte
4
E para truncar os registos de todos os recipientes que você pode usar um curinga shell como mostrado em outras respostas, por isso é apenas um comando:docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- sh -c 'truncate -s0 /var/lib/docker/containers/*/*-json.log'
bradenm
11

Você não pode fazer isso diretamente através de um comando do Docker.

Você pode limitar o tamanho do log ou usar um script para excluir logs relacionados a um contêiner. Você pode encontrar exemplos de scripts aqui (leia a parte inferior): Funcionalidade: Capacidade de limpar o histórico de registros # 1083

Confira a seção de log da referência do arquivo docker-compose, onde é possível especificar opções (como rotação e limite de tamanho do log) para alguns drivers de log.

Tristan
fonte
7

Como um usuário root , tente executar o seguinte:

>  /var/lib/docker/containers/*/*-json.log

ou

cat /dev/null > /var/lib/docker/containers/*/*-json.log

ou

echo "" > /var/lib/docker/containers/*/*-json.log
matson kepson
fonte
6

Nos meus servidores Ubuntu, mesmo com o sudo, eu recebia Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory

Mas pentear a janela de encaixe inspecionar e truncar respostas funcionou:

sudo truncate -s 0 `docker inspect --format='{{.LogPath}}' <container>`
aqwan
fonte
2

Eu prefiro este (das soluções acima):

truncate -s 0 /var/lib/docker/containers/*/*-json.log

No entanto, estou executando vários sistemas (Ubuntu 18.x Bionic, por exemplo), onde esse caminho não funciona conforme o esperado. O Docker é instalado pelo Snap, portanto, o caminho para os contêineres é mais como:

truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log
igraczech
fonte
1

Você também pode fornecer os parâmetros de log-op na docker runlinha de comando, assim:

docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest

ou em um docker-compose.yml como este

my-app:
image: my-app:latest
logging:
    driver: "json-file"
    options:
        max-file: "5"
        max-size: 10m

Créditos: https://medium.com/@Quigley_Ja/rotating-docker-logs-keeping-your-overlay-folder-small-40cfa2155412 (James Quigley)

Dag Baardsen
fonte
Os valores dos parâmetros devem ser citado (ou seja, "5"e "10m", respectivamente), como mostrado aqui para o arquivo daemon.json global, mas é o mesmo para uma janela de encaixe-compose.yml. Nos dois casos, isso afetará apenas os contêineres criados recentemente.
Adrian W
@AdrianW: docker-compose.yml não precisa de aspas. Esses são formatos de arquivo totalmente diferentes. E sim, você está certo: os comandos "docker run" e os parâmetros de composição do docker afetam apenas os contêineres criados recentemente - em oposição à resposta aqui com mais votos que afeta apenas os daemons dockerd reiniciados e está disponível apenas através do acesso root. Minha resposta deve mostrar um caminho muito mais simples e atualizado do que editar do que reiniciar todo o processo do dockerd.
Dag Baardsen 05/04
Sem aspas, recebo: ERRO: para o aplicativo Não é possível criar um contêiner para o aplicativo de serviço: json: não é possível remover o número de ordem no campo Go struct LogConfig.Config do tipo string Se citar assim: "5"ele funciona. O 10mtrabalho sem citar de fato.
Adrian W
Parece que há uma diferença entre o Docker para Windows e o Docker para Linux. Neste último, tenho que colocar os valores entre aspas. Não no primeiro. Atualizou a descrição para se ajustar a ambos. Obrigado, @AdrianW
Dag Baardsen
0

Docker para usuários de Mac, aqui está a solução:

    1. Encontre o caminho do arquivo de log por:

      $ docker inspect | grep log

    1. SSH na máquina docker (suponha que o nome seja default, se não, executado docker-machine lspara descobrir):

      $ docker-machine ssh default

    1. Mude para usuário root ( referência ):

      $ sudo -i

    1. Exclua o conteúdo do arquivo de log:

      $ echo "" > log_file_path_from_step1

Jinsong Li
fonte
2
A docker-machine não funciona com o Docker for Mac. Em vez disso você pode executar "janela de encaixe prazo -ti -v / var / lib / janela de encaixe / contentores: / var / criação centos bash" depois "truncar --size 0 /var/inception/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de-json.log"
Jamshid
Você pode usar docker exec -it default shpara inserir um shell sh em um contêiner. No entanto, muitos contêineres não disponibilizam implicitamente o sudocomando.
Dag Baardsen