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.
- 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 -vexclui 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_modulesdesaparecer. - 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
:zou: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 -vcasualmente. Isso exclui seus volumes nomeados. - Usando caminhos relativos com
-v. Formulários como-v data:/xcriam 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
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.
Mais guias sobre testes, IA e desenvolvimento moderno
Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.
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 →DevOpsVariá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 softwareExplicaçã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 testesZombando 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 softwareCobertura 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 SQLDELETE 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 SQLExibiçõ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 softwareInterface 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 softwarePython *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 softwareFunçõ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 artificialO 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 →DevOpsMonitoramento 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 →DevOpsDocker 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 testesTDD 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 softwareGit 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 softwareList 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 SQLSQL 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 →