Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 24

Data Persistence with Docker Volumes

Recommended resources

Olá! Bem-vindo à nossa última lição sobre armazenamento persistente no Docker.

Nas lições anteriores, exploramos os dois principais mecanismos para persistir dados: volumes e bind mounts. Vimos que os volumes são gerenciados pelo Docker e são ideais para dados de produção, enquanto os bind mounts são perfeitos para o desenvolvimento, permitindo, por exemplo, o hot-reload de uma API .NET ao mapear diretamente seu código-fonte para dentro de um contêiner.

Hoje, vamos consolidar esse conhecimento. Nosso objetivo é responder a uma pergunta fundamental na arquitetura de aplicações containerizadas: por que os volumes são a escolha correta e profissional para persistir os dados de um banco de dados? Esta lição focará na justificação e na tomada de decisão, comparando as duas abordagens em um dos cenários mais críticos que você encontrará.

A Natureza dos Dados de um Banco de Dados

Primeiro, vamos contextualizar o problema. Aplicações podem ser categorizadas como stateless (sem estado) ou stateful (com estado).

  • Stateless: Uma API web é um exemplo clássico. Você pode criar ou destruir várias instâncias dela sem perder informações, pois o estado (os dados) é armazenado em outro lugar.
  • Stateful: Um banco de dados (como PostgreSQL, SQL Server ou MySQL) é o exemplo por excelência. Os dados que ele gerencia são o estado. A perda desses dados é, na maioria dos casos, catastrófica.

Como os contêineres são efêmeros por padrão, garantir a persistência e a integridade dos dados de um banco de dados é uma prioridade máxima.


Volumes vs. Bind Mounts: A Justificativa Técnica

Embora tanto volumes quanto bind mounts possam tecnicamente persistir dados, a escolha correta para um banco de dados é, inequivocamente, o volume nomeado (named volume). Vamos analisar o porquê com base em quatro critérios essenciais.

Para uma excelente visão geral que aborda essa decisão, leia o seguinte artigo. Ele oferece uma árvore de decisão clara e cenários do mundo real.

Docker Storage Solutions: Volume vs Bind Mount Decision Guide

Este artigo do EastonDev blog, intitulado "Docker Storage Solutions: Volume vs Bind Mount Decision Guide", é um recurso fantástico para entender as nuances. Ele compara as duas abordagens e fornece uma justificativa clara para a escolha em diferentes cenários.

Leia as seções "Docker Data Management Basics", "Deep Dive: Three Mounting Methods" (focando em Volume), a tabela comparativa, e especialmente a seção "Scenario 1: MySQL Database". Preste atenção nos argumentos sobre desempenho, portabilidade e gerenciamento.

Com base no que você leu e em nosso conhecimento prévio, vamos estruturar a justificativa:

1. Gerenciamento e Portabilidade

  • Volumes: São gerenciados pelo Docker Engine. O Docker armazena os dados em uma área específica no sistema de arquivos do host (ex: /var/lib/docker/volumes/ no Linux), mas você, como usuário, não precisa saber ou interagir com esse caminho. Você gerencia tudo via comandos Docker (docker volume create, inspect, ls). Isso desacopla os dados do ambiente do host.
  • Bind Mounts: Mapeiam um caminho específico do host para o contêiner. Isso cria um acoplamento forte. Se você configurar um contêiner para usar um bind mount em C:\dev\db_data, essa configuração não funcionará em outra máquina sem esse caminho exato.

Justificativa para Bancos de Dados: A portabilidade é crucial. Você precisa que sua configuração de banco de dados funcione de forma consistente na sua máquina, na de seus colegas e nos ambientes de staging e produção. Os volumes garantem essa independência de localização.

2. Desempenho

  • Volumes: Oferecem desempenho próximo ao nativo em todas as plataformas. No Windows e macOS, onde o Docker é executado dentro de uma VM Linux, o Docker otimizou o sistema de arquivos para operações de I/O de alto desempenho dentro dessa VM, onde os volumes residem.
  • Bind Mounts: Embora rápidos no Linux, eles podem sofrer uma penalidade de desempenho significativa no Windows e macOS. Isso ocorre porque o compartilhamento de arquivos entre o sistema operacional do host (Windows/macOS) e a VM Docker envolve uma camada de tradução que pode ser lenta para operações de I/O intensivas, como as de um banco de dados (muitas leituras e escritas pequenas).

Justificativa para Bancos de Dados: O desempenho do banco de dados é crítico para a performance da aplicação. A degradação de I/O causada por bind mounts no Windows/macOS torna-os inadequados para essa tarefa. Os volumes oferecem um desempenho consistente e otimizado em todas as plataformas.

Docker Persistent Storage: Volumes vs Bind Mounts
Esta imagem ilustra a diferença conceitual. O Volume (à direita) é um recurso gerenciado pelo Docker, abstraído do sistema de arquivos do host, enquanto o Bind Mount (à esquerda) é um link direto para uma pasta específica no host.

3. Segurança e Isolamento

  • Volumes: Os dados são isolados dentro da área de gerenciamento do Docker. Isso protege os arquivos do banco de dados de serem modificados ou excluídos acidentalmente por outros processos no sistema do host.
  • Bind Mounts: Expõem uma parte do sistema de arquivos do host diretamente ao contêiner. Um contêiner comprometido poderia, teoricamente, afetar o host. Mais importante, qualquer processo no host pode acessar e modificar os arquivos do banco de dados, contornando o motor do banco de dados, o que é uma receita para a corrupção de dados.

Justificativa para Bancos de Dados: Os arquivos de dados de um banco de dados são altamente estruturados e não devem ser tocados por nada além do próprio processo do banco de dados. Os volumes fornecem o isolamento necessário para garantir a integridade dos dados.

4. Recursos Avançados e Ecossistema

  • Volumes: Suportam drivers de volume. Isso permite que o Docker armazene dados em sistemas de armazenamento externos, como compartilhamentos NFS ou armazenamento em nuvem (Amazon EBS, Azure Disk). Além disso, os volumes podem ser pré-populados com dados de uma imagem na primeira vez que um contêiner é iniciado.
  • Bind Mounts: São um mapeamento simples e não possuem um modelo de driver extensível.

Justificativa para Bancos de Dados: Para cenários de produção, a capacidade de usar drivers de volume para conectar-se a soluções de armazenamento gerenciadas, replicadas e de alta disponibilidade é fundamental. Os volumes são a porta de entrada para essa funcionalidade.


Demonstração Prática: Persistindo Dados do PostgreSQL

Agora, vamos ver como aplicar isso na prática com o PostgreSQL, um banco de dados que você usará mais adiante no curso.

O vídeo a seguir demonstra o processo completo com MySQL, mas os conceitos e comandos são idênticos para qualquer banco de dados. Ele mostra visualmente por que a persistência funciona.

How to Save Docker Data using Bind Mounts or Volumes

O vídeo "How to Save Docker Data using Bind Mounts or Volumes" do canal Database Star mostra, passo a passo, como usar um volume para garantir que os dados de um banco de dados sobrevivam à remoção do contêiner.

Assista à seção sobre volumes, de 02:02 a 08:46. Observe o fluxo: criar o volume, executar o contêiner com o volume, adicionar dados, remover o contêiner, criar um novo contêiner com o mesmo volume e verificar que os dados ainda estão lá.

Inspirados pelo vídeo, aqui estão os comandos para fazer o mesmo com o PostgreSQL:

  1. Crie um volume nomeado:

    docker volume create postgres-data
    
  2. Execute um contêiner PostgreSQL usando o volume:
    O diretório padrão de dados do PostgreSQL na imagem oficial é /var/lib/postgresql/data.

    docker run --name some-postgres -d \
      --mount type=volume,source=postgres-data,target=/var/lib/postgresql/data \
      -e POSTGRES_PASSWORD=mysecretpassword \
      postgres:16
    
    • --mount type=volume,source=postgres-data,target=/var/lib/postgresql/data: Mapeia nosso volume postgres-data para o diretório de dados dentro do contêiner.
  3. Simule um desastre: Pare e remova o contêiner.

    docker stop some-postgres
    docker rm some-postgres
    
  4. Verifique se os dados (o volume) ainda existem:

    docker volume ls
    

    Você verá postgres-data na lista. Seus dados estão seguros.

  5. Inicie um novo contêiner conectado ao volume existente:

    docker run --name new-postgres -d \
      --mount type=volume,source=postgres-data,target=/var/lib/postgresql/data \
      -e POSTGRES_PASSWORD=mysecretpassword \
      postgres:16
    

    Este novo contêiner carregará e servirá os dados existentes do volume postgres-data, como se nada tivesse acontecido.

Este artigo do dev.to reforça essa prática com exemplos e dicas valiosas.

Docker Volumes and Data Persistence: Managing State in Containers 💾

Para complementar, este post no dev.to, "Docker Volumes and Data Persistence", oferece um excelente resumo e uma seção de "Best Practices" que solidifica o que aprendemos.

Leia as seções "Bind Mounts vs. Named Volumes: Choosing the Right Option", "Real-World Examples" (especificamente o exemplo do PostgreSQL) e "Best Practices I've Learned". Isso ajudará a reforçar a decisão e as melhores práticas.

Test your understanding!

Você foi encarregado de containerizar uma aplicação legada que escreve logs importantes diretamente em /var/log/app.log no sistema de arquivos do host. A equipe de operações precisa ter acesso fácil e imediato a esses arquivos de log no host para monitoramento com ferramentas existentes.

Para containerizar essa aplicação, você usaria um volume ou um bind mount para o diretório /var/log? Justifique sua resposta com base nos critérios que discutimos.

Show answer

Neste caso específico, um bind mount seria a escolha mais apropriada.

Justificativa: O requisito principal é que processos externos ao Docker (ferramentas de monitoramento no host) precisam de acesso direto e imediato aos arquivos de log.

  • Gerenciamento e Acesso: Um bind mount mapeia diretamente [caminho_no_host]/logs para /var/log no contêiner. Isso torna os arquivos de log instantaneamente disponíveis no host em um local conhecido, satisfazendo o requisito da equipe de operações. Usar um volume exigiria etapas extras para acessar os dados de fora do Docker.
  • Portabilidade: Embora a portabilidade seja menor, o requisito de integração com ferramentas existentes no host já cria um acoplamento. O bind mount simplesmente atende a essa restrição de forma explícita.
  • Distinção do Banco de Dados: Diferentemente dos arquivos de um banco de dados, que não devem ser tocados externamente, os arquivos de log são frequentemente projetados para serem lidos por outros sistemas.

Este cenário ilustra que, embora os volumes sejam a regra para dados de estado como bancos de dados, os bind mounts têm casos de uso válidos onde a integração com o host é o objetivo principal.


Conclusão

Parabéns por concluir este módulo sobre redes e armazenamento! Hoje, você solidificou um dos conceitos mais importantes para executar aplicações robustas no Docker.

Principais Pontos:

  • Para aplicações com estado (stateful), como bancos de dados, a escolha padrão e correta para persistir dados é um volume nomeado (named volume).
  • A justificativa se baseia em quatro pilares: portabilidade (desacoplamento do host), desempenho (otimizado em todas as plataformas), segurança (isolamento dos dados) e funcionalidades (suporte a drivers).
  • Bind mounts são inadequados para bancos de dados devido ao acoplamento com o host, possíveis problemas de desempenho e riscos à integridade dos dados.

Até agora, gerenciamos nossos contêineres individualmente. No entanto, aplicações reais, como uma API .NET com um banco de dados PostgreSQL, são compostas por múltiplos serviços que precisam se comunicar. Na próxima lição, daremos um grande passo em frente e entraremos no Módulo 4: Aplicações Multi-Contêiner com Docker Compose. Você aprenderá a definir e gerenciar toda a sua stack de aplicação em um único arquivo de configuração, tornando o desenvolvimento e a orquestração muito mais simples.