Docker volumes: como persistir dados de containers

Por padrão, dados escritos dentro de um container são perdidos quando ele é removido. Para persistir dados, banco de dados, uploads, configs, você precisa de volumes. Volumes nomeados (managed pelo Docker) são a escolha certa para dados de aplicação como PostgreSQL e Redis. Bind mounts (diretório do host montado no container) são ideais para arquivos de configuração e código em desenvolvimento.

Volumes nomeados vs bind mounts

Os dois tipos de montagem têm usos distintos:

Volumes no docker-compose.yml

Declaração correta de volumes nomeados no Compose, note que a seção volumes: no topo nível é obrigatória:

yaml
services:
  postgres:
    image: postgres:16
    volumes:
      - pg_data:/var/lib/postgresql/data   # volume nomeado

  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro  # bind mount (read-only)
      - ./html:/usr/share/nginx/html           # bind mount (leitura e escrita)

  app:
    image: minha-app:latest
    volumes:
      - uploads:/app/uploads               # volume nomeado para uploads

# Declara os volumes nomeados
volumes:
  pg_data:
  uploads:

Inspecionar e gerenciar volumes

Comandos essenciais para trabalhar com volumes:

bash
# Listar todos os volumes
docker volume ls

# Ver detalhes de um volume (onde está no disco, quem usa)
docker volume inspect pg_data

# Ver qual container está usando o volume
docker ps --filter volume=pg_data

# Remover volumes não utilizados (cuidado — irrecuperável)
docker volume prune

# Remover um volume específico (container deve estar parado)
docker volume rm nome_do_volume

Backup de volumes

O método mais portável para backup de volumes Docker é criar um container auxiliar para comprimir os dados:

bash
# Backup de um volume para arquivo tar.gz no diretório atual
docker run --rm   -v pg_data:/source:ro   -v $(pwd):/backup   alpine tar czf /backup/pg_data-backup-$(date +%Y%m%d).tar.gz -C /source .

# Restaurar de um backup
docker run --rm   -v pg_data:/target   -v $(pwd):/backup   alpine tar xzf /backup/pg_data-backup-20260607.tar.gz -C /target

Permissões em volumes

Um problema comum: o processo dentro do container tenta escrever no volume mas não tem permissão. Acontece quando o UID do processo no container não bate com o dono do diretório no host:

bash
# Ver o UID do processo dentro do container
docker exec nome_container id

# Ajustar dono do diretório de bind mount para o UID correto
# (ex: UID 1000 para aplicações Node.js não-root)
chown -R 1000:1000 ./dados

# Ou inicializar o volume com as permissões corretas
docker run --rm -v meu_volume:/data alpine chown -R 1000:1000 /data

Não quer configurar manualmente?

Implante o Docker em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Volumes nomeados ficam em /var/lib/docker/volumes/<nome_do_volume>/_data. Você pode acessar diretamente como root, mas prefira usar docker run ou docker exec para interagir, acesso direto pode corromper dados se o container estiver rodando.

Não. docker compose down para e remove containers e redes, mas preserva volumes. Para remover volumes junto, use docker compose down -v. Isso é destrutivo, use apenas em ambientes de desenvolvimento.

Volume anônimo é criado com volumes: ["/caminho"] sem nome, o Docker gera um ID aleatório. São difíceis de gerenciar e referir. Volume nomeado (pg_data: no Compose) tem nome explícito, fácil de identificar, fazer backup e compartilhar entre containers.

Sim. Declare o mesmo volume nomeado nos dois serviços no Compose. Cuidado com escrita concorrente, banco de dados não suportam múltiplos processos escrevendo no mesmo diretório de dados simultaneamente.

Use um container auxiliar para copiar: docker run --rm -v volume_origem:/origem:ro -v volume_destino:/destino alpine sh -c "cp -av /origem/. /destino/". Pare os containers que usam os volumes antes de migrar para garantir consistência.