Configurar BuildKit garbage collection e systemd timers para limpeza automática de imagens e volumes Docker em VPS: tutorial prático

Docker & Containers · Por · Publicado em · 9 min de leitura

Trecho de código HTML/CSS em editor no monitor, sintaxe colorida e foco seletivo
Editor mostrando código HTML/CSS, transmite tema técnico e profissional Foto: Bibek ghosh / Pexels

Este tutorial mostra como configurar BuildKit garbage collection e systemd timers para limpeza automática de imagens e volumes Docker em VPS. Você vai aplicar políticas seguras, usar labels para exceções e criar services/timers do systemd para controlar cache de build, imagens antigas e volumes temporários, evitando surpresas em produção.

Pré‑requisitos e o que será automatizado

A rotina combina o GC do BuildKit (cache de build) e a remoção controlada de artefatos do Docker (containers parados, imagens antigas e volumes rotulados). O objetivo é reduzir uso de disco sem afetar serviços em execução.

Antes de seguir, confirme que você tem acesso sudo, Docker e systemd ativos. Faça um snapshot/backup se houver dados críticos. Alguns passos removem dados antigos ou temporários.

Para segurança, imagens ativas não são removidas, e volumes só são excluídos quando marcados com uma label de autoclean e sem uso. Se você ainda vai preparar o host, veja como instalar Docker e Compose em Linux em este guia.

  • Docker Engine e buildx instalados
  • Acesso sudo para criar services/timers
  • Espaço livre temporário para rodar a limpeza
  • Backups ou snapshot do host
Alvo Comando principal Critérios Observações
Cache de build (BuildKit) docker buildx prune -af --keep-storage 20GB Manter N GB de cache Não toca imagens/volumes; só cache de build
Imagens docker image prune -a -f --filter 'until=240h' Idade > 10 dias e não usadas Pode excluir versões antigas não referenciadas
Containers parados docker container prune -f --filter 'until=240h' Idade > 10 dias e parados Libera camadas e logs antigos
Volumes docker volume rm $(docker volume ls -q --filter 'label=autoclean=true' --filter 'dangling=true') Apenas com label autoclean e sem uso Evita apagar dados importantes por engano

O que o BuildKit realmente limpa com GC?

O GC do BuildKit remove apenas cache de build (camadas e artefatos temporários gerados em builds). Ele não remove imagens publicadas, containers, volumes ou networks. Usaremos docker buildx prune com limite de armazenamento para manter um cache útil e estável.

Para imagens e volumes, criaremos rotinas separadas com filtros de idade e labels. Assim, cada alvo tem regras claras e independentes.

Como ver o consumo de cache, imagens e volumes agora?

Antes de automatizar, meça onde está o consumo. O buildx du mostra o uso do cache de build por repositório/estágio. O docker system df detalha imagens, containers e volumes. Liste volumes dangling para identificar candidatos à limpeza sem risco.

# Uso do cache de build (BuildKit)
docker buildx du --verbose

# Uso geral de disco (imagens, containers, volumes)
docker system df -v

# Volumes sem uso (dangling)
docker volume ls --filter dangling=true

Configurar BuildKit GC com systemd timers (política por armazenamento)

Vamos agendar docker buildx prune para manter o cache de build dentro de um teto (keep-storage). A execução via systemd garante logs e retomada se o host estiver desligado no horário.

Se você usa um builder dedicado (driver docker-container), ajuste o alvo do builder com a flag apropriada ao seu ambiente. Boas práticas de timers estão em migrar cron para systemd timers. Para acelerar builds com cache remoto, veja o guia de cache remoto com BuildKit.

# Service e timer para GC do BuildKit (cache de build)
# Crie os arquivos abaixo

sudo tee /etc/systemd/system/buildkit-prune.service >/dev/null <<'EOF'
[Unit]
Description=BuildKit cache prune (docker buildx)
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
# Ajuste o limite conforme seu disco (ex.: 10GB, 20GB, 50GB)
ExecStart=/usr/bin/docker buildx prune -af --keep-storage 20GB
Nice=10
IOSchedulingClass=idle
EOF

sudo tee /etc/systemd/system/buildkit-prune.timer >/dev/null <<'EOF'
[Unit]
Description=Run BuildKit cache prune weekly

[Timer]
OnCalendar=Sun *-*-* 03:15:00
RandomizedDelaySec=30m
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now buildkit-prune.timer

Script seguro para limpar imagens e volumes por idade e labels

O script abaixo remove containers parados antigos, limpa imagens não usadas e apaga apenas volumes sem uso marcados com label autoclean=true. Revise os filtros antes de ativar em produção. Para proteger imagens críticas, use uma label keep=true e o filtro do prune irá preservá-las.

# Dica: rotule recursos para controle fino (exemplos):
# docker volume create --label autoclean=true tmp_cache
# docker build -t minhaimg:latest --label keep=true .

sudo tee /usr/local/sbin/docker-gc-safe.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
log() { echo "[$(date -Is)] $*"; }

if ! docker info >/dev/null 2>&1; then
  log "Docker não está acessível; saindo."
  exit 0
fi

# 1) Containers parados antigos (ex.: >10 dias)
log "Pruning containers parados (>10d)"
docker container prune -f --filter "until=240h" || true

# 2) Imagens não usadas antigas, preservando as rotuladas com keep
log "Pruning imagens antigas não usadas (>10d), exceto label keep"
docker image prune -a -f \
  --filter "until=240h" \
  --filter "label!=keep" || true

# 3) Volumes sem uso e rotulados para autoclean
log "Removendo volumes sem uso com label autoclean=true"
mapfile -t VOLS < <(docker volume ls -q \
  --filter "label=autoclean=true" \
  --filter "dangling=true") || true
if ((${#VOLS[@]} > 0)); then
  docker volume rm "${VOLS[@]}" || true
else
  log "Nenhum volume elegível encontrado"
fi

log "Limpeza concluída"
EOF

sudo chmod +x /usr/local/sbin/docker-gc-safe.sh

Como agendar o script de limpeza com um systemd timer?

Crie um service oneshot e um timer diário com atraso aleatório para evitar colisões com janelas de backup. O Persistent=true executa a tarefa atrasada se o host ficou desligado.

Se você usa Docker rootless, crie units no systemd de usuário (systemctl --user) e armazene o script no seu $HOME/bin. Para integrar com sua estratégia de proteção, considere agendar snapshots e uploads para object storage usando timers, como neste guia de LVM+Restic em S3 passo a passo.

sudo tee /etc/systemd/system/docker-gc.service >/dev/null <<'EOF'
[Unit]
Description=Rotina de limpeza segura de Docker (containers, imagens e volumes com label)
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/docker-gc-safe.sh
Nice=10
IOSchedulingClass=idle
EOF

sudo tee /etc/systemd/system/docker-gc.timer >/dev/null <<'EOF'
[Unit]
Description=Agendar limpeza segura de Docker diariamente

[Timer]
OnCalendar=daily
RandomizedDelaySec=45m
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now docker-gc.timer

Como confirmar que funcionou e onde ver logs?

Confirme timers ativos, leia os logs e meça a redução de espaço com docker system df e buildx du. Se uma execução foi perdida, o Persistent=true reexecuta na volta do host. Isso ajuda a manter BuildKit garbage collection e systemd timers confiáveis na sua VPS.

# Timers ativos
systemctl list-timers '*buildkit*' '*docker-gc*'

# Logs da última execução
journalctl -u buildkit-prune.service -u docker-gc.service --since "-2d" -e

# Medir economia de espaço
docker system df -v
docker buildx du --verbose

Problemas comuns e ajustes finos

Alguns cenários pedem ajustes nos filtros. Priorize rótulos para exceções e revise janelas de idade em ambientes com baixa taxa de deploy. Em registros privados extensos, rode imagens semanalmente e cache diariamente.

  • Imagens críticas sumindo: adicione label keep=true ao build e preserve com --filter label!=keep.
  • Cache de build insuficiente: aumente --keep-storage (ex.: 30GB).
  • Volumes removidos cedo: rotule autoclean=true somente em volumes temporários; nunca em volumes de banco de dados.
  • Docker rootless: crie timers com systemctl --user e garanta o serviço do Docker de usuário ativo.
  • Concorrência com backups: ajuste OnCalendar para fora da janela de snapshot/backup.
  • Sem espaço para rodar prune: limpe primeiro apenas dangling (docker image prune -f) e, se preciso, mova volumes grandes para outro disco seguindo este tutorial de migração de volumes Docker passo a passo.

Perguntas frequentes

É seguro rodar prune automaticamente no Docker?

Sim, quando você define filtros conservadores e usa labels para exceções. Aplique idade (until=...) para containers e imagens e remova apenas volumes sem uso com label autoclean=true. Tenha snapshots ou backups recentes antes da primeira execução.

Qual a diferença entre docker system prune e buildx prune?

docker system prune remove recursos do Docker (containers parados, imagens não usadas, redes e volumes anônimos). Já docker buildx prune remove somente o cache de build do BuildKit. Combine ambos com critérios distintos e agendamentos separados.

Com que frequência devo executar o GC e os timers?

Diariamente para cache de build e containers parados, e semanalmente para imagens antigas costuma equilibrar espaço e desempenho. Ajuste a janela de idade e o keep-storage conforme sua taxa de deploy e o tamanho do disco.

Como impedir que imagens críticas sejam removidas?

Rotule-as com keep=true no build e adicione o filtro --filter label!=keep ao docker image prune. Versões marcadas ficam preservadas mesmo se forem antigas e não referenciadas por containers.

Posso usar isso em Docker rootless?

Sim. Crie o service e o timer no systemd de usuário (systemctl --user) e garanta que a sessão de usuário esteja habilitada no login. O restante do fluxo (buildx prune, image prune, volume rm) funciona da mesma forma.

O timer executa se a VPS estiver desligada no horário?

Sim. Quando o timer tem Persistent=true, o systemd dispara a próxima execução pendente assim que o sistema volta. Os logs ficam acessíveis no journalctl para auditoria e troubleshooting.

Quer padronizar a limpeza sem riscos?

Precisa revisar filtros, labels e horários para seu ambiente? Descreva seu cenário e validamos juntos as políticas, com dry‑run e rollback seguro.

Falar sobre políticas de GC

Veja também