Docker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa

  1. Início
  2. Blog
  3. DevOps

DevOps

Volumes Docker versus montagens Bind: Persistir dados de contêiner da maneira certa

Remova um contêiner e seus dados irão junto com ele, a menos que você o armazene em um lugar mais seguro. Aprenda a diferença entre volumes, montagens de ligação e tmpfs, quando usar cada um e como fazer backup do que é importante.

9 min de leitura
Volumes Docker versus montagens vinculadas: persista os dados do contêiner da maneira certa

Principais pontos

  • A camada gravável de um contêiner é excluída junto com o contêiner, portanto, dados importantes precisam ser montados.
  • Volumes nomeados são gerenciados pelo Docker e são a escolha usual para bancos de dados e dados de produção.
  • Montagens de vinculação mapeiam uma pasta host, o que as torna ideais para código ativo durante o desenvolvimento.
  • docker compose down -v exclui volumes, portanto use-o com cuidado e mantenha backups testados.

Você inicia um banco de dados em um contêiner, adiciona alguns dados, remove o contêiner e inicia um novo. Os dados desapareceram. Quase todo mundo aprende essa lição da maneira mais difícil. Volumes Docker e montagens de ligação existem para manter os dados ativos além da vida útil de qualquer contêiner.

Este guia explica como cada um funciona e como escolher. Os comandos e arquivos aqui são exemplos padrão, baseados no comportamento documentado do Docker, e não os executamos neste artigo, então experimente-os primeiro em dados descartáveis. Os detalhes podem diferir entre as versões do Docker e no Docker Desktop. Se você é novo em contêineres, comece com nosso tutorial do Docker para iniciantes.

Por que os dados do contêiner desaparecem

Uma imagem Docker é feita de camadas somente leitura. Quando um contêiner é iniciado, o Docker adiciona uma fina camada gravável na parte superior e todas as alterações vão para lá. Essa camada sobrevive a uma parada e reinicialização, mas é removida quando o contêiner é excluído.

docker run -d --name db -e POSTGRES_PASSWORD=devonly postgres:17
# ... create tables and add data ...
docker rm -f db
docker run -d --name db -e POSTGRES_PASSWORD=devonly postgres:17
# The data you added is not there

Isso ocorre intencionalmente, pois permite substituir contêineres livremente. Isso significa que tudo o que você precisa manter deve ficar fora do contêiner. Existem três maneiras de fazer isso:

Tipo Armazenado em Sobrevive à remoção do contêiner?
Volume nomeado Uma área gerenciada pelo Docker Sim
Vincular montagem Um caminho de host que você escolhe Sim
montagem tmpfs Memória hospedeira Não

Volumes Docker versus montagens vinculadas lado a lado

Aspecto Volume nomeado Vincular montagem
Gerenciado por Docker Você
Localização Área de armazenamento do Docker Qualquer caminho no host
Depende das pastas do host? Não Sim
Editando do host Estranho por design Fácil, as alterações aparecem instantaneamente
Alvo vazio pré-preenchido a partir da imagem? Sim Não, o caminho do host esconde isso
Comandos CLI do Docker Sim, docker volume Não
Drivers para armazenamento remoto Sim Não
Melhor para Bancos de dados, dados de produção Código fonte em desenvolvimento

Volumes nomeados

Um volume é um armazenamento criado e gerenciado pelo Docker. Você se refere a ele pelo nome e não precisa se preocupar com onde ele mora fisicamente.

docker volume create pgdata

docker run -d --name db \
  -e POSTGRES_PASSWORD=devonly \
  -v pgdata:/var/lib/postgresql/data \
  postgres:17

Agora os arquivos do banco de dados residem em pgdata. Exclua o contêiner e inicie um novo com o mesmo volume, e seus dados ainda estarão lá. No Linux, os volumes geralmente ficam em /var/lib/docker/volumes/, mas você não deve editar esses arquivos diretamente. No Docker Desktop, eles ficam dentro de uma máquina virtual, não em uma pasta normal.

O caminho dentro do container depende da imagem, então verifique a documentação da imagem. Montar no caminho errado é um erro clássico: tudo parece funcionar, mas os dados ainda estão sendo gravados na camada do contêiner. Versões principais mais recentes de uma imagem também podem alterar esse caminho, portanto leia as notas de lançamento antes de atualizar.

O Docker criará um volume nomeado automaticamente se ele não existir. Um volume anônimo, criado sem nome, também funciona, mas recebe um ID aleatório longo e é fácil de perder de vista. Sempre dê nomes aos seus volumes.

Vincular montagens

Uma montagem vinculada mapeia um caminho de host específico diretamente para o contêiner. Ambos os lados veem os mesmos arquivos imediatamente. Isso o torna perfeito para desenvolvimento, já que as edições em seu editor entram em vigor no contêiner em execução sem necessidade de reconstrução:

docker run -d --name web \
  -p 8080:80 \
  -v "$(pwd)/site:/usr/share/nginx/html:ro" \
  nginx:1.27

Edite um arquivo em site/, atualize o navegador e você verá a alteração. O :ro torna a montagem somente leitura dentro do contêiner, o que é um bom hábito quando o contêiner não precisa escrever lá.

As montagens de ligação vêm com algumas compensações:

  • Eles vinculam você ao host. O caminho deve existir em cada máquina, portanto as configurações são menos portáveis.
  • Eles ocultam o conteúdo da imagem. Se você montar sobre /app, o que quer que a imagem contenha ficará invisível. Um exemplo comum é node_modules desaparecer.
  • Eles expõem o host. Um contêiner com uma montagem gravável pode alterar ou excluir arquivos reais do host. Nunca monte caminhos sensíveis como / ou o soquete Docker, a menos que você compreenda totalmente o risco.
  • O desempenho pode variar. No Docker Desktop para macOS e Windows, o compartilhamento de arquivos ultrapassa os limites da virtualização e pode ser mais lento do que no Linux.

montagens tmpfs

Uma montagem tmpfs reside na memória do host e nunca é gravada na camada do contêiner. Ele desaparece quando o contêiner para, portanto é adequado para arquivos temporários, caches e dados confidenciais de curta duração:

docker run -d --tmpfs /app/cache:size=64m myapp:1.0

tmpfs está disponível em hosts Linux. Ele também pode acelerar bancos de dados em ambientes de teste descartáveis, onde você não se preocupa em manter os dados.

-v ou –mount?

Ambas as bandeiras funcionam. --mount é mais longo, mas é mais explícito, e muitas pessoas preferem isso em scripts:

# Short form
docker run -v pgdata:/var/lib/postgresql/data postgres:17

# Explicit form
docker run --mount type=volume,source=pgdata,target=/var/lib/postgresql/data postgres:17

# Bind mount, read-only
docker run --mount type=bind,source="$(pwd)"/site,target=/usr/share/nginx/html,readonly nginx:1.27

Há uma diferença significativa. Com -v, um caminho de host ausente é criado para você como uma pasta vazia, que pode ocultar um erro de digitação. Com --mount e um tipo de ligação, o Docker relata um erro. Além disso, com -v, o lado esquerdo decide o tipo: um nome significa um volume e um caminho significa uma montagem vinculada. Então -v data:/x e -v ./data:/x fazem coisas muito diferentes.

Volumes no Docker Compose

A maioria dos projetos reais declara o armazenamento em um arquivo Compose. Este usa os dois tipos, cada um para sua função adequada:

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ./src:/app/src      # bind mount: live code
    depends_on:
      - db

  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: devonly
    volumes:
      - pgdata:/var/lib/postgresql/data   # named volume: data

volumes:
  pgdata:

Os volumes nomeados devem ser declarados na seção de nível superior volumes. Compose prefixa o nome real com o nome do projeto. Consulte nosso tutorial do Docker Compose para um passo a passo completo.

Dica: docker compose down mantém os volumes nomeados, mas docker compose down -v os exclui junto com seus dados. Tenha especial cuidado com scripts e histórico de shell que incluem -v.

Comandos de volume úteis

Comando O que isso faz
volume da janela de encaixe ls Lista volumes
nome de criação do volume do docker Cria um volume
nome da inspeção do volume do docker Mostra detalhes, incluindo sua localização
nome do rm do volume do docker Exclui um volume e seus dados
remoção de volume do docker Remove volumes não utilizados
sistema docker df -v Mostra o uso do disco, incluindo volumes

Verifique o que prune irá remover antes de confirmar, pois isso não pode ser desfeito. Os volumes que nenhum contêiner usa atualmente ainda podem conter dados importantes.

Fazer backup e restaurar um volume

É possível fazer backup de um volume executando um contêiner de curta duração que monta o volume e uma pasta host:

# Back up
docker run --rm \
  -v pgdata:/data:ro \
  -v "$(pwd)":/backup \
  alpine tar czf /backup/pgdata.tar.gz -C /data .

# Restore into a new volume
docker volume create pgdata_restored
docker run --rm \
  -v pgdata_restored:/data \
  -v "$(pwd)":/backup \
  alpine tar xzf /backup/pgdata.tar.gz -C /data

Para um banco de dados ativo, copiar arquivos como esse pode capturar um estado inconsistente. Pare o contêiner primeiro, ou melhor, use a ferramenta do próprio banco de dados, como pg_dump para PostgreSQL. E um backup que você nunca restaurou é apenas uma esperança, então teste a restauração.

Permissões de arquivo

“Permissão negada” é o problema mais comum com montagens. Os arquivos mantêm seus IDs numéricos de usuário e grupo no Linux, portanto, se um contêiner for executado como usuário 1000 e a pasta host pertencer a outro usuário, as gravações falharão. Algumas maneiras de corrigir isso:

  • Execute o contêiner com um usuário correspondente: docker run --user "$(id -u):$(id -g)" ...
  • Configure a propriedade correta da sua imagem, conforme descrito em nossas práticas recomendadas do Dockerfile.
  • Prefira volumes nomeados para dados, pois um novo volume assume a propriedade da pasta da imagem quando é usado pela primeira vez.
  • Em sistemas que usam SELinux, as montagens de ligação podem precisar de um rótulo :z ou :Z.

Evite a tentação de chmod 777, como explica nosso guia de comandos do Linux.

Qual você deve usar?

Situação Usar
Dados do banco de dados Volume nomeado
Código-fonte de edição ao vivo Vincular montagem
Um arquivo de configuração do seu repositório Montagem de ligação somente leitura
Compartilhando dados entre contêineres Volume nomeado
Cache temporário ou arquivos temporários tmpfs
Banco de dados de teste descartável tmpfs ou sem montagem
Código do aplicativo em produção Construa-o na imagem

Essa última linha é importante. Na produção, o código pertence à imagem, então o que você testou é o que você executa. Em clusters, o armazenamento de dados funciona de maneira diferente novamente, por meio de volumes persistentes, que são abordados na documentação mais ampla do Kubernetes. Nosso guia Docker vs Kubernetes explica como os dois se relacionam.

Erros comuns

  • Montagem no caminho errado. Os dados ainda residem na camada do contêiner e desaparecem mais tarde.
  • Executando down -v casualmente. Isso exclui seus volumes nomeados.
  • Usando caminhos relativos com -v. Formulários como -v data:/x criam um volume em vez de um mapeamento de pasta.
  • Colocar segredos em montagens de ligação graváveis. Monte-os somente leitura ou use um recurso de segredos.
  • Apontar dois contêineres de banco de dados para um volume. Isso pode corromper os dados.
  • Não ter backups. Um volume não é um backup. Ele reside no mesmo disco.

Considerações finais

A regra geral é curta: volumes nomeados para dados, montagens de ligação para o código que você está editando e tmpfs para coisas que não devem durar. Experimente em um banco de dados descartável. Crie um volume nomeado, adicione uma linha, exclua o contêiner, inicie um novo e confirme se sua linha sobreviveu. Em seguida, pratique um backup e uma restauração antes de precisar de um.

Perguntas frequentes

Qual é a diferença entre um volume Docker e uma montagem vinculada?

Um volume é gerenciado pelo Docker e armazenado em uma área própria. Uma montagem vinculada mapeia um caminho de host específico que você controla diretamente no contêiner.

Parar um contêiner exclui seus dados?

Não. Os dados na camada gravável sobrevivem a uma parada e reinicialização. Ele é perdido quando o contêiner é removido, a menos que seja armazenado em um volume ou em uma montagem de ligação.

Os volumes do Docker persistem após a composição do docker?

Sim, os volumes nomeados permanecem após a composição do docker. Adicionar o sinalizador -v os exclui, junto com todos os dados que eles contêm.

Onde os volumes do Docker são armazenados?

No Linux, geralmente em /var/lib/docker/volumes. No Docker Desktop, eles residem dentro de uma máquina virtual. Use docker volume inspecionar para ver a localização.

Vários contêineres podem compartilhar um volume?

Sim, vários contêineres podem montar um volume. O aplicativo deve lidar com o acesso simultâneo com segurança e os bancos de dados geralmente não devem compartilhar arquivos de dados dessa maneira.

Continue aprendendo

Trabalhe com Stack Quora

Precisa de ajuda com testes, WordPress ou SEO?

Ajudamos as equipes a fornecer software melhor e a expandir seus sites. Conte-nos no que você está trabalhando e sugeriremos um próximo passo claro.

Continue lendo

Mais guias sobre testes, IA e desenvolvimento moderno

Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.

Inteligência artificial

Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las

Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…

Leia o artigo →
DevOps

Variáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos

Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…

Leia o artigo →
Desenvolvimento de software

Explicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429

Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…

Leia o artigo →
Automação de testes

Zombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem

Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…

Leia o artigo →
Teste de software

Cobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa

Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…

Leia o artigo →
Bancos de dados e SQL

DELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um

DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…

Leia o artigo →
Bancos de dados e SQL

Exibições SQL explicadas: crie, use e evite as armadilhas, com exemplos

Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…

Leia o artigo →
Desenvolvimento de software

Interface TypeScript vs tipo: diferenças reais, testadas com o compilador

Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…

Leia o artigo →
Desenvolvimento de software

Python *args e **kwargs explicados: funções flexíveis com exemplos claros

Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…

Leia o artigo →
Desenvolvimento de software

Funções Python Lambda: sintaxe, usos reais e quando não usá-los

Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …

Leia o artigo →
Inteligência artificial

O que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar

O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …

Leia o artigo →
DevOps

Monitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos

Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…

Leia o artigo →
DevOps

Docker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa

Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…

Leia o artigo →
Automação de testes

TDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um

TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…

Leia o artigo →
Desenvolvimento de software

Git merge vs rebase: diferenças, exemplos e quando usar cada um

Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.

Leia o artigo →
Desenvolvimento de software

List comprehension em Python: sintaxe, exemplos e quando evitar

List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.

Leia o artigo →
Bancos de dados e SQL

SQL JOIN explicado com exemplos (Inner, Left, Right, Full)

Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…

Leia o artigo →