Volumes Docker: persistir dados e usar bind mounts
Faça dados sobreviverem à remoção do contêiner, compare volume e bind mount e reproduza uma gravação bloqueada por montagem somente leitura.
Um volume Docker guarda dados fora da camada gravável do contêiner. Assim você pode remover e recriar a aplicação sem apagar pedidos, uploads ou arquivos do banco. Nesta lição a gente vai provar a persistência com dois contêineres diferentes e comparar volume com bind mount.
O ponto de partida é a lição de Dockerfile para Node, onde a imagem virou um pacote imutável. Agora a pergunta muda: o que precisa continuar existindo quando uma execução desse pacote vai embora?
O armário continua depois da troca de turno
Imagine a cozinha de um restaurante com funcionários em turnos. Cada pessoa usa uma bancada durante o expediente, mas os pedidos importantes ficam num armário identificado da cozinha. Trocar a pessoa não esvazia o armário. O contêiner é o turno, sua camada gravável é a bancada temporária e o volume nomeado é o armário administrado pelo prédio.
Na mesma cozinha há uma janela que dá acesso direto à mesa do escritório. Isso representa o bind mount: um caminho escolhido no host aparece dentro do contêiner. O volume é gerenciado pelo Docker; o bind mount aponta para uma pasta que você administra.
A comparação termina aí. Tecnicamente ambos são montagens no sistema de
arquivos do contêiner. O processo acessa um caminho como /dados, mas o conteúdo
vem de fora da camada gravável. Remover o contêiner não remove automaticamente
um volume nomeado nem a pasta do host.
Um volume nomeado tem identidade própria
Crie o volume usado pelos pedidos da cantina:
docker volume create dc-pedidos-aulaEsse comando é idempotente para o mesmo nome: se o volume já existe, Docker devolve o nome em vez de apagar ou zerar conteúdo. Inspecione metadados sem entrar no diretório interno do daemon:
docker volume inspect dc-pedidos-aula --format 'Nome={{.Name}} | Driver={{.Driver}} | Escopo={{.Scope}}'local é o driver de armazenamento do teste; local no escopo significa que o
volume pertence a este daemon. A documentação recomenda interagir com os dados
por uma montagem, não editando o diretório interno do Docker diretamente.
O primeiro contêiner grava e pode desaparecer
Monte o volume em /dados e grave um arquivo com Node:
docker run --name dc-gravador --mount type=volume,src=dc-pedidos-aula,dst=/dados node:24-alpine node -e "require('node:fs').writeFileSync('/dados/pedidos.txt','pedido 42: dois cafés\n'); console.log('gravado')"--mount descreve três partes: tipo volume, origem dc-pedidos-aula e destino
/dados. O destino é o caminho visto pelo processo dentro do contêiner.
O comando Node termina, então dc-gravador fica parado. Remova esse contêiner:
docker rm dc-gravadorAgora use outro contêiner, criado da mesma imagem, apenas para ler:
docker run --rm --mount type=volume,src=dc-pedidos-aula,dst=/dados node:24-alpine node -e "console.log(require('node:fs').readFileSync('/dados/pedidos.txt','utf8').trim())"Essa saída é a prova central da lição. O primeiro contêiner não existe mais; o
arquivo continua porque pertence ao volume. --rm remove o leitor ao final,
mas não remove o volume nomeado.
Confira que o objeto permanece no inventário:
docker volume ls --filter name=dc-pedidos-aula --format 'Nome={{.Name}} | Driver={{.Driver}}'É esse comportamento que protege o dado numa recriação de contêiner. Ele não
protege contra docker volume rm, docker compose down -v, defeito no disco ou
erro da aplicação. Persistência e backup resolvem problemas diferentes.
Bind mount liga um caminho conhecido do host
No desenvolvimento, você frequentemente quer editar no host e ler dentro do
contêiner. Crie a pasta bind e peça ao próprio contêiner para escrever nela:
mkdir -p bind
docker run --rm --mount type=bind,source="$PWD/bind",target=/saida node:24-alpine node -e "require('node:fs').writeFileSync('/saida/recado.txt','pedido 42: suco sem açúcar\n'); console.log('arquivo criado no bind mount')"O source é um caminho real da máquina. $PWD evita depender do nome da pasta,
mas exige executar o comando no diretório certo. O target é onde essa pasta
aparece para o processo.
Leia pelo host, fora de qualquer contêiner:
sed -n '1p' bind/recado.txtO mesmo arquivo tem dois caminhos: .../bind/recado.txt no host e
/saida/recado.txt no contêiner. Não são duas cópias; são duas visões da mesma
origem.
Bind mount é adequado para código-fonte e arquivos que você precisa manipular com ferramentas do host. Volume costuma ser a escolha mais segura para dados da aplicação, especialmente bancos. Essa separação reaparece no Docker Compose.
Somente leitura transforma intenção em regra
Uma montagem pode ser marcada readonly. O processo continua lendo, mas o
kernel rejeita gravação. Reproduza no volume que já contém o pedido:
docker run --rm --mount type=volume,src=dc-pedidos-aula,dst=/dados,readonly node:24-alpine node -e "try{require('node:fs').writeFileSync('/dados/novo.txt','x')}catch(error){console.error(error.code+': '+error.message);process.exit(1)}"EROFS significa read-only file system. Em português simples, o caminho
existe, mas foi montado sem permissão de escrita. Não é problema do fs do Node
nem arquivo ausente. A correção depende da intenção: retire readonly se a
aplicação precisa gravar; mantenha e corrija o código se ela deveria apenas ler.
Montar configuração como somente leitura reduz alterações acidentais. Ainda assim, não entregue ao contêiner uma pasta inteira do host quando ele precisa de um único arquivo. Bind mounts concedem acesso direto ao caminho indicado.
--mount ou -v: escolha clareza
As duas formas conseguem montar volumes. -v dc-pedidos-aula:/dados é curta;
--mount type=volume,src=...,dst=... explicita cada papel e costuma produzir
erros mais claros. Nesta trilha a gente usa --mount para você enxergar origem
e destino.
Há também tmpfs, armazenamento mantido apenas na memória do host Linux. Ele serve para dados temporários que não devem persistir em disco. Não use tmpfs como atalho para banco: ao parar o contêiner, o conteúdo desaparece.
Missão: provar persistência sem confiar no nome
Crie um volume dc-missao-volume, monte-o num contêiner e grave três linhas
num arquivo estoque.txt. Remova o gravador. Use outro contêiner para contar as
linhas. O critério de sucesso é a saída 3 depois que o primeiro contêiner já
não aparece em docker ps -a.
Faça então a mudança controlada: monte o mesmo volume como readonly e tente
acrescentar uma quarta linha. A missão termina quando você recebe EROFS e
consegue explicar que o volume existe, mas aquela montagem bloqueia escrita.
Quando não precisar mais dos dados descartáveis desta aula, remova pelo nome:
docker volume rm dc-pedidos-aulaAntes de remover um volume de projeto, confirme o nome e tenha backup. A próxima lição troca armazenamento por comunicação: vamos ligar processos isolados com redes Docker. O guia de Docker mantém o mapa das duas decisões.
Perguntas frequentes
Volume Docker é um backup?
Posso montar o mesmo volume em dois contêineres?
Volume e bind mount funcionam no Docker Desktop?
O que acontece com volume anônimo ao usar --rm?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Docker Engine 29.5.3, Docker Compose 5.1.4 e Node 24.19.0 (node:24-alpine) no macOS ARM64, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- Docker Docs — Storage overview — docs.docker.com
- Docker Docs — Volumes — docs.docker.com
- Docker Docs — Bind mounts — docs.docker.com
- Docker Docs — tmpfs mounts — docs.docker.com


