Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

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.

Rodolfo Mori5 min de 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:

bash
docker volume create dc-pedidos-aula
dc-pedidos-aula

Esse 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:

bash
docker volume inspect dc-pedidos-aula --format 'Nome={{.Name}} | Driver={{.Driver}} | Escopo={{.Scope}}'
Nome=dc-pedidos-aula | Driver=local | Escopo=local

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:

bash
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')"
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:

bash
docker rm dc-gravador
dc-gravador

Agora use outro contêiner, criado da mesma imagem, apenas para ler:

bash
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())"
pedido 42: dois cafés

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:

bash
docker volume ls --filter name=dc-pedidos-aula --format 'Nome={{.Name}} | Driver={{.Driver}}'
Nome=dc-pedidos-aula | Driver=local

É 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:

bash
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')"
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:

bash
sed -n '1p' bind/recado.txt
pedido 42: suco sem açúcar

O 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:

bash
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: EROFS: read-only file system, open '/dados/novo.txt'

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:

bash
docker volume rm dc-pedidos-aula
dc-pedidos-aula

Antes 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.

  • docker
  • volumes
  • bind mount
  • persistencia
  • armazenamento
  • terminal

Perguntas frequentes

Volume Docker é um backup?
Não. Um volume separa o dado do ciclo de vida do contêiner, mas continua sujeito a exclusão, corrupção e falha do host. Dados importantes ainda precisam de backup testado e guardado em outro lugar.
Posso montar o mesmo volume em dois contêineres?
Pode, mas a aplicação e o formato de dados precisam suportar acesso simultâneo. Compartilhar a pasta interna de um banco entre duas instâncias sem suporte para isso pode corromper os dados.
Volume e bind mount funcionam no Docker Desktop?
Sim. Volumes ficam na máquina Linux administrada pelo Desktop; bind mounts atravessam o compartilhamento de arquivos entre o host e essa máquina. Por isso permissões e desempenho podem diferir do Linux nativo.
O que acontece com volume anônimo ao usar --rm?
Os volumes anônimos ligados ao contêiner são removidos com ele quando --rm é usado. Volumes nomeados não são removidos automaticamente.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

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

  1. Docker Docs — Storage overview — docs.docker.com
  2. Docker Docs — Volumes — docs.docker.com
  3. Docker Docs — Bind mounts — docs.docker.com
  4. Docker Docs — tmpfs mounts — docs.docker.com

Continue por aqui