Conteúdo

Como liberar espaço em disco ocupado pelo Docker (comandos prune)

Depois de usar o Docker por algum tempo, imagens antigas, contêineres parados, cache de build e volumes sem uso vão se acumulando e podem ocupar dezenas de GB. Nesta seção, primeiro descubra o que está consumindo espaço e depois faça a limpeza com segurança. Todas as saídas são resultados de comandos executados em sequência no mesmo ambiente.

Confira o espaço usado

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          13        3         2.886GB   2.377GB (82%)
Containers      4         1         98.3kB    16.38kB (16%)
Local Volumes   4         1         40.61MB   40.61MB (100%)
Build Cache     151       0         3.554GB   2.954GB
CampoSignificado
TOTALTotal
ACTIVEQuantidade em uso por contêineres
SIZEEspaço ocupado
RECLAIMABLEParte que pode ser liberada (sem uso)

Neste ambiente, há 13 imagens, mas apenas 3 estão em uso; 2.377 GB (82%) podem ser recuperados. O cache de build é ainda maior, com 2.954 GB. Adicione -v para ver os detalhes de cada imagem, contêiner e volume: docker system df -v.

Imagens e contêineres atuais:

$ docker images
IMAGE               ID             DISK USAGE   CONTENT SIZE   EXTRA
adminer:latest      74f29c416e14        164MB         43.8MB
alpine:3.23         85fe1e81d675       26.6MB         8.21MB   U
hello-node:latest   4063457524bb        245MB         62.2MB
myapp:latest        80cb5c41a286       54.9MB         24.8MB   U
mysql:8.4           24989179f588       1.12GB          254MB
nginx:1.30          9bf97bd7714f        242MB         66.5MB
nginx:1.30-alpine   0985e772fb9f       93.7MB           27MB   U
node:24-alpine      ebfe2f904627        242MB           62MB
postgres:18         74935e722416        650MB          169MB
python:3.14-slim    a2b82f3c4855        180MB         45.7MB
redis:8-alpine      3811787313eb        161MB         39.6MB
registry:3          ddf754342cfc       86.9MB         20.7MB
ubuntu:26.04        f144425ff09b        162MB         45.6MB
$ docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS                     PORTS     NAMES
cc43746c9a29   alpine:3.23         "true"                   7 seconds ago   Exited (0) 6 seconds ago             anon1
7e269fff858b   nginx:1.30-alpine   "/docker-entrypoint.…"   8 seconds ago   Up 7 seconds               80/tcp    web
bf5ff318eb63   alpine:3.23         "echo done"              8 seconds ago   Exited (0) 7 seconds ago             old2
b580380c1fd2   myapp               "cat /version.txt"       9 seconds ago   Exited (0) 8 seconds ago             old1

O U na coluna EXTRA indica In Use (em uso por um contêiner). Entre os contêineres, apenas web está em execução; os outros três foram encerrados (Exited), mas ainda ocupam espaço.

Limpeza por categoria

ComandoO que remove
docker container pruneTodos os contêineres parados
docker image pruneImagens pendentes (sem nome, <none>)
docker image prune -aTodas as imagens que não estão em uso por nenhum contêiner
docker builder pruneCache de build
docker volume pruneVolumes anônimos sem uso
docker volume prune -aTodos os volumes sem uso (inclusive os nomeados)
docker network pruneRedes personalizadas sem uso

Cada comando pede confirmação primeiro (Are you sure you want to continue? [y/N]). Adicione -f para ignorar a confirmação, o que é útil em scripts. Os exemplos a seguir usam -f.

Excluir contêineres parados

$ docker container prune -f
Deleted Containers:
cc43746c9a2993bda0fb21ab3f161b78603353714f396f86fa8c4b5caf90e25a
bf5ff318eb6331a05239ad7fa39420ff96dc1c8f84b9a3548ce38a0f71a2d63a
b580380c1fd2dc6cca2dc6e009bb877c3eb2df1cf388664a32c8932aff8169fa

Total reclaimed space: 16.38kB

Os três contêineres parados foram excluídos. O contêiner em execução web não foi afetado.

Se você usa o Docker Desktop, também pode selecionar os contêineres na tela Containers e clicar em Delete:

Na tela Containers do Docker Desktop, selecione os contêineres e clique em Delete
Docker Desktop: selecione os contêineres e clique em Delete. Imagem: documentação oficial do Docker (Apache-2.0)

Docker 29: novas builds não deixam imagens <none>

Antes, ao reconstruir uma imagem com o mesmo nome (por exemplo, executando docker build -t myapp . várias vezes), a versão antiga ficava como uma “imagem pendente” chamada <none>, que precisava ser removida com docker image prune. Veja o teste no Docker 29:

$ docker build -q --build-arg VERSION=4 -t myapp:latest .
sha256:3f33bc33eb36171280e9b90d904e25c58b2dcf509390536580ffacafc35d4595

$ docker images --filter dangling=true
IMAGE   ID             DISK USAGE   CONTENT SIZE   EXTRA

$ docker ps -a --filter name=old1
CONTAINER ID   IMAGE          COMMAND              CREATED          STATUS                      PORTS     NAMES
b580380c1fd2   80cb5c41a286   "cat /version.txt"   26 seconds ago   Exited (0) 26 seconds ago             old1

Após quatro builds seguidas de myapp:latest, o resultado de --filter dangling=true ficou vazio. Por padrão, o Docker 29 usa o armazenamento de imagens containerd. Quando uma nova imagem substitui a versão antiga, ela não é mais mantida como <none>. Para contêineres que ainda usam a versão antiga, como old1, a coluna IMAGE passa a mostrar o ID da imagem.

Por isso, no Docker 29, normalmente há pouco para limpar com docker image prune (sem -a). O que realmente ocupa espaço são as imagens sem uso, mas que ainda têm nome, e o cache de build.

Remover volumes anônimos

$ docker volume ls
DRIVER    VOLUME NAME
local     6f6f8ce590c609d4f39b3a676282da88866c8ab20a064132f7746c3cf6717f2c
local     991c93cb6ebeac8570e9c15a89b4225c2bb5e20cbfde2f5bf665fa4dfa23a1aa
local     5396795eeeaab8415295814207a02f75f6ea136d5c34574ba9b16ecdc1b975f9
local     cleanup-demo_pgdata

$ docker volume prune -f
Deleted Volumes:
5396795eeeaab8415295814207a02f75f6ea136d5c34574ba9b16ecdc1b975f9
991c93cb6ebeac8570e9c15a89b4225c2bb5e20cbfde2f5bf665fa4dfa23a1aa
6f6f8ce590c609d4f39b3a676282da88866c8ab20a064132f7746c3cf6717f2c

Total reclaimed space: 0B

$ docker volume ls
DRIVER    VOLUME NAME
local     cleanup-demo_pgdata
  • Os três primeiros nomes longos são volumes anônimos. Por exemplo, o Dockerfile da imagem postgres declara VOLUME. Mesmo que você não monte um volume ao executar o contêiner, o Docker cria automaticamente um volume anônimo, que continua existindo depois que o contêiner é removido (consulte Volumes e persistência de dados).
  • docker volume prune remove apenas volumes anônimos que não estão em uso.
  • cleanup-demo_pgdata é um volume nomeado do projeto Compose. Embora nenhum contêiner o esteja usando depois de docker compose down, ele não foi removido.

Remover o cache de build

$ docker builder du | tail -n 3
Private:	2.996GB
Reclaimable:	3.596GB
Total:		3.596GB

$ docker builder prune -f --filter until=1h | tail -n 3
lv85kuv5xx5h65k941qjoxecz               	true 	98.69kB   	About an hour ago
kc9tcgw8l1aq9dz1agx096se0               	true 	870kB     	About an hour ago
Total:	1.662GB

$ docker builder prune -f | tail -n 3
6os07ml167zpcfh09ushitk2b               	true 	8.285kB   	38 minutes ago
7ir7u28j6esk2x7pyu6q38kvk               	true 	74.75MB   	38 minutes ago
Total:	1.334GB
  • docker builder du mostra que o cache de build totaliza 3.596 GB, todos recuperáveis.
  • --filter until=1h remove apenas o cache que não foi usado há mais de 1 hora, liberando 1.662 GB.
  • Sem o filtro, mais 1.334 GB são removidos.

Remover o cache de build significa que, na próxima compilação, todas as etapas terão que ser executadas novamente (por exemplo, rodar npm ci e pip install outra vez), o que será mais lento. Isso não afeta nenhuma imagem nem contêiner.

Limpeza de uma só vez: docker system prune

docker system prune

Remove: contêineres parados, redes não utilizadas, imagens dangling e cache de build.

docker system prune -a

Também remove todas as imagens que não estão em uso. Elas precisarão ser baixadas novamente quando forem usadas.

Teste prático: --volumes remove os dados do banco de dados?

Muitos tutoriais (incluindo uma versão anterior deste) alertam que docker system prune --volumes também remove o volume do banco de dados que fica “temporariamente sem uso” depois de docker compose down. Testamos no Docker 29:

$ docker system prune --volumes -f
Deleted Containers:
871f1c408d23dd413804105498b5520385dfafc9e558c02447ed940684bbc483

Deleted Volumes:
e5d0caa972c5323d5a64e9baf5fcb21d66ce7fbb4879bdcc7aa068a14fdbbf76

Total reclaimed space: 8.192kB

$ docker volume ls
DRIVER    VOLUME NAME
local     cleanup-demo_pgdata

--volumes removeu apenas um volume anônimo. O volume nomeado cleanup-demo_pgdata do banco de dados do Compose continua lá. Desde o Docker 23, volume prune e system prune --volumes tratam apenas volumes anônimos por padrão.

O comando que realmente remove volumes nomeados é docker volume prune -a:

$ docker volume prune -a -f
Deleted Volumes:
cleanup-demo_pgdata

Total reclaimed space: 40.61MB

$ docker volume ls
DRIVER    VOLUME NAME

Desta vez, cleanup-demo_pgdata foi removido, e os 40.61 MB de arquivos do banco de dados que estavam nele também desapareceram, sem possibilidade de recuperação.

Use docker volume prune -a somente quando tiver certeza de que não precisa de nenhum dado. Para remover um volume específico, é mais seguro usar docker volume rm nome; em um projeto Compose, use docker compose down -v, que remove apenas os volumes desse projeto. Se você usa Docker 20.10 ou anterior, --volumes ainda remove volumes nomeados.

Remover todas as imagens não utilizadas

$ docker image prune -a -f | grep -E "^untagged|^Total"
untagged: nginx:1.30
untagged: node:24-alpine
untagged: postgres:18
untagged: python:3.14-slim
untagged: myapp:latest
untagged: mysql:8.4
untagged: redis:8-alpine
untagged: registry:3
untagged: ubuntu:26.04
untagged: adminer:latest
untagged: alpine:3.23
untagged: hello-node:latest
Total reclaimed space: 2.665GB

$ docker images
IMAGE               ID             DISK USAGE   CONTENT SIZE   EXTRA
nginx:1.30-alpine   0985e772fb9f       93.7MB           27MB   U

$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          1         1         93.66MB   0B (0%)
Containers      1         1         81.92kB   0B (0%)
Local Volumes   0         0         0B        0B
Build Cache     26        0         599.6MB   506.9MB
  • Com exceção de nginx:1.30-alpine, que está sendo usado pelo contêiner web, as outras 12 imagens foram removidas, liberando 2.665 GB.
  • O docker system df final mostra que restaram apenas 93.66 MB de imagens.

Essas imagens serão baixadas novamente automaticamente na próxima vez que você executar docker run ou fizer um build. Se a rede for lenta ou a imagem for muito grande (por exemplo, imagens relacionadas a modelos de IA podem facilmente ocupar vários GB), considere usar --filter para remover apenas as antigas:

docker image prune -a --filter "until=168h"      # Remove apenas as imagens criadas há mais de 7 dias

Observe que until compara o horário de criação da imagem (quando o autor da imagem a compilou), e não o horário em que você a baixou.

Os logs dos contêineres também ocupam espaço

Por padrão, os logs json-file não têm limite de tamanho. Veja o teste prático com um contêiner que produz saída continuamente (o comando yes imprime uma grande quantidade de texto por segundo):

$ docker run -d --name noisy alpine:3.23 sh -c "timeout 3 yes hello-docker-log; sleep 600"
863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6

$ docker inspect --format "{{.LogPath}}" noisy
/var/lib/docker/containers/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6-json.log

$ du -h $(docker inspect --format "{{.LogPath}}" noisy)
69.3M	/var/lib/docker/containers/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6/863ccacbc4bcf86a81cc3bf7603cef1d6ecc004553ac4b36dd7ef52172ed3dc6-json.log

$ docker rm -f noisy
noisy

O arquivo de log chegou a 69.3 MB com apenas 3 segundos de saída. Os arquivos de log de contêineres que ficam em execução por muito tempo e produzem muitos logs podem chegar a dezenas de GB. Eles não são removidos automaticamente; isso só acontece quando o contêiner é removido. Os arquivos de log ficam em /var/lib/docker/containers/ID_DO_CONTÊINER/. Em um host Linux, você pode encontrar os maiores arquivos de log assim:

sudo du -h /var/lib/docker/containers/*/*-json.log | sort -h | tail

Defina limites para um único contêiner

$ docker run -d --name noisy --log-opt max-size=10m --log-opt max-file=3 alpine:3.23 sh -c "timeout 3 yes hello-docker-log; sleep 600"
fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161

$ ls -lh $(dirname $(docker inspect --format "{{.LogPath}}" noisy)) | grep json
-rw-------    1 root     root        3.2K Oct 13 01:07 config.v2.json
-rw-r-----    1 root     root        7.2M Oct 13 01:07 fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161-json.log
-rw-r-----    1 root     root        9.5M Oct 13 01:07 fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161-json.log.1
-rw-r-----    1 root     root        9.5M Oct 13 01:07 fab1c34ceecb955dc33c01f0e7aa0a60b4137e68d0fe465d52ce23b49ba66161-json.log.2
-rw-------    1 root     root        1.5K Oct 13 01:07 hostconfig.json

$ docker inspect --format '{{json .HostConfig.LogConfig}}' noisy
{"Type":"json-file","Config":{"max-file":"3","max-size":"10m"}}

$ docker rm -f noisy
noisy

max-size=10m significa que cada arquivo pode ter no máximo 10 MB; max-file=3 significa que até 3 arquivos serão mantidos. Os mais antigos são rotacionados para .1, .2. Com o mesmo volume de saída, os logs ocupam apenas cerca de 26 MB no total e não crescerão mais.

No Compose, a configuração fica assim:

services:
  app:
    image: myapp
    logging:
      options:
        max-size: "10m"
        max-file: "3"

Defina limites globais para os logs

Para aplicar limites a todos os novos contêineres: no Linux, edite /etc/docker/daemon.json; no Docker Desktop, edite o mesmo JSON em Settings → Docker Engine:

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

Depois de editar no Linux, execute sudo systemctl restart docker; no Docker Desktop, clique em Apply & restart. A configuração só será aplicada aos contêineres criados depois disso. Para os contêineres existentes, remova-os e crie-os novamente (no Compose, use docker compose up -d --force-recreate).

Docker Desktop: o espaço em disco não aumentou após a limpeza

No Windows e no macOS, todos os dados do Docker ficam em um arquivo de disco virtual. Quando você exclui imagens, o espaço dentro do disco virtual é liberado, mas o próprio arquivo pode não diminuir imediatamente.

  • Docker Desktop: em Settings → Resources → Advanced, você pode ver e ajustar o limite do disco virtual. Clean / Purge data, na tela Troubleshoot, apaga todos os dados do Docker (imagens, contêineres e volumes). Use essa opção somente como último recurso.
  • Windows (WSL 2): se o arquivo .vhdx ainda estiver grande, execute wsl --shutdown e depois use compact vdisk no diskpart para compactar o arquivo .vhdx correspondente.

Limpeza periódica recomendada

Em um servidor, você pode usar o cron para executar a limpeza uma vez por semana:

docker container prune -f --filter "until=168h"
docker image prune -af --filter "until=168h"
docker builder prune -af --filter "until=168h"

Esses comandos não afetam nenhum volume, então os dados do banco de dados ficam seguros. Combinados com um limite global para os logs, eles ajudam a evitar que o uso de disco saia do controle.

Resumo

  • Primeiro, consulte docker system df; depois, decida o que limpar.
  • image prune -a exclui todas as imagens que não estão em uso; builder prune limpa o cache de build.
  • volume prune exclui apenas volumes anônimos; -a também inclui os nomeados.
  • Defina limites para os logs com max-size e max-file.

Exercícios

Exercício 1: escreva um conjunto de comandos que possa ser usado no cron sem afetar nenhum volume e que limpe apenas imagens e cache de build com mais de 7 dias.

Resposta
docker image prune -af --filter "until=168h"
docker builder prune -af --filter "until=168h"

Perguntas frequentes

O comando docker system prune é seguro?

Sem --volumes, ele não afeta nenhum volume; desde o Docker 23, mesmo com --volumes, ele só exclui volumes anônimos. O comando realmente perigoso é docker volume prune -a.

O espaço em disco do Windows não aumentou após a limpeza?

Os dados do Docker Desktop ficam em um arquivo de disco virtual. Depois de excluir imagens, o arquivo pode não diminuir imediatamente; consulte a última seção deste capítulo.

Posso excluir todo o cache de build?

Sim. Isso não afeta nenhuma imagem nem contêiner, mas a próxima build será mais lenta.

Atualizado 14 de outubro de 2026