truncate -s 0 "$(docker inspect --format '{{.LogPath}}' api)" esvazia o log de um contêiner em execução e libera o espaço na hora, sem reiniciar nada. Aqui não se usa rm: o daemon continua escrevendo no arquivo apagado, o espaço não volta e docker logs fica quebrado até o contêiner reiniciar.
1. Primeiro veja o que o Docker está ocupando
$ clai quanto espaço em disco o docker usa→ docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 48 14 28.88GB 20GB (69%)Containers 17 10 4.631MB 513.8kB (11%)Local Volumes 38 7 6.349GB 4.084GB (64%)Build Cache 181 0 0B 0B
Os logs não aparecem nesta tabela — a linha Containers conta apenas a camada de escrita. Se o df diz que o disco está cheio e o docker system df está tranquilo, o suspeito são os logs.
2. Descubra o contêiner que mais escreve
$ clai mostre o tamanho do arquivo de log de cada contêiner, do maior para o menor→ docker ps -q | xargs docker inspect --format '{{.LogPath}} {{.Name}}' | while read -r p n; do printf '%s\t%s\n' "$(du -h "$p" | cut -f1)" "${n#/}"; done | LC_ALL=C sort -rh | head -36.1M api3.2M worker1.9M cache
LogPath é a única forma confiável de achar o arquivo: ele muda entre instalações rootful e rootless. LC_ALL=C não é enfeite: numa locale com vírgula decimal, o sort -h coloca 844K acima de 6.1M.
3. Trunque o log de um contêiner em execução
$ clai esvazie o log do contêiner api sem parar ele→ truncate -s 0 "$(docker inspect --format '{{.LogPath}}' api)"
O contêiner segue escrevendo no mesmo descritor de arquivo, o fluxo não se rompe e o espaço volta imediatamente. É o comando que você quer durante um incidente.
4. A armadilha: rm no lugar de truncate
$ clai apague o arquivo de log do contêiner api→ rm "$(docker inspect --format '{{.LogPath}}' api)"⚠ CAUTION — depois disso docker logs fica quebrado até o contêiner reiniciar
O docker logs responde Error grabbing logs: open …-json.log: no such file or directory, e o arquivo não volta sozinho. O daemon continua com o arquivo apagado aberto, então o espaço também não é liberado: você perde a saída e mantém o problema.
5. Para não acontecer de novo
$ clai suba um contêiner com rotação de log de 10 megabytes e três arquivos→ docker run -d --log-opt max-size=10m --log-opt max-file=3 --name api alpine sleep 600
O tamanho de um arquivo vezes a quantidade de arquivos é o teto — 30 MB aqui. Coloque em todo contêiner falante.
6. Verifique se um contêiner em execução tem limite
$ clai mostre as configurações de log do contêiner api→ docker inspect -f '{{json .HostConfig.LogConfig}}' api{"Type":"json-file","Config":{"max-file":"3","max-size":"10m"}}
Um "Config":{} vazio significa que não há limite algum e o arquivo vai crescer até o disco acabar. É exatamente assim que aparece um contêiner iniciado sem essas opções.
Gotchas
- Truncar libera apenas o arquivo ativo. Um contêiner limitado a
max-size=1m --log-opt max-file=2escreveu 20000 linhas e odocker logsmostrava todas. Depois de truncar o arquivo ativo, sobraram 10122 linhas — o resto está no rotacionado…-json.log.1. Os rotacionados se apagam, o ativo se trunca. - daemon.json não vale para contêineres existentes. O
log-optsem/etc/docker/daemon.jsoné lido na criação do contêiner. Os que já rodam mantêm as configurações antigas até serem recriados. sort -hdepende da locale. Numa locale russa ou alemã o6.1Mnão é lido como número e o maior log vai parar no meio da lista. PonhaLC_ALL=Cantes dosort.
Related questions
Por que o docker system df não mostra os logs? Ele conta imagens, camadas de escrita, volumes e cache de build. Os arquivos json de log ficam ao lado, no diretório do contêiner, e nunca entram nessa tabela.
Como limito os logs de todos os contêineres de uma vez? Coloque "log-driver": "json-file" e "log-opts": {"max-size": "10m", "max-file": "3"} em /etc/docker/daemon.json, reinicie o daemon e recrie os contêineres.
Dá para não escrever logs em disco? Sim, --log-driver none desliga a coleta, mas aí o docker logs não mostra nada. O meio-termo é o driver local, que rotaciona por padrão.
See also
CliAI transforma a frase acima no comando exato e marca a variante com rm como CAUTION antes de rodar qualquer coisa. Instale em uma linha.