Como Persistir Dados em Volumes Docker no Linux

10 min de leitura Docker & Containers
Como Persistir Dados em Volumes Docker no Linux

A persistência de dados é um dos conceitos fundamentais para o uso profissional de Docker em ambientes de produção. Por padrão, os containers são efêmeros: quando eles param ou são removidos, todos os dados escritos nas camadas de leitura e escrita do container são perdidos. Para sysadmins, desenvolvedores e equipes de DevOps, isso significa que bancos de dados, logs de aplicação e arquivos de configuração precisam ser armazenados fora do ciclo de vida do container.

Neste tutorial técnico, vamos explorar como garantir a persistência de dados em ambientes Linux utilizando volumes Docker. Abordaremos desde a criação manual até o uso avançado com docker compose, explicando as diferenças entre bind mounts e volumes gerenciados pelo Docker, além de melhores práticas para infraestrutura estável.

O que são Volumes Docker?

Volumes são o mecanismo preferencial para persistir dados gerados e usados por containers Docker. Eles são diretórios (ou dispositivos) especiais que existem fora da hierarquia de arquivos do sistema de arquivos UnionFS do container. Isso oferece várias vantagens críticas em comparação com outras técnicas de montagem:

  • Persistência independente: Os dados continuam existindo mesmo se o container for removido.
  • Compartilhamento: Múltiplos containers podem montar o mesmo volume simultaneamente.
  • Gerenciamento: Volumes podem ser gerenciados usando comandos Docker, facilitando backups e migrações.
  • Performance: Em sistemas Linux, bind mounts (montagens de diretório) podem ter sobrecarga de performance em certos sistemas de arquivos (como NFS), enquanto volumes Docker utilizam o driver nativo do kernel, oferecendo geralmente melhor desempenho para operações de I/O intensivas.

Conceito 1: Bind Mounts vs. Volumes Gerenciados

Antes de executar comandos, é crucial entender a diferença entre as duas principais abordagens de persistência no Linux:

Bind Mounts: Montam um diretório específico do host Linux dentro do container. O caminho no host é absoluto e conhecido pelo administrador. Se você montar /home/user/logs no container, o Docker usa exatamente esse diretório no sistema de arquivos subjacente. Isso é ideal para desenvolvimento local ou quando a aplicação precisa acessar configurações específicas do servidor hospedeiro.

Volumes Gerenciados (Managed Volumes): O Docker cria e gerencia o diretório em um caminho interno, geralmente localizado em /var/lib/docker/volumes/. O administrador não sabe exatamente onde os dados estão fisicamente no disco do host sem consultar o Docker. Isso é ideal para bancos de dados e aplicações stateful em produção, pois isola a aplicação da estrutura de diretórios do servidor.

Passo 1: Criando e Usando Volumes Gerenciados

A maneira mais robusta de persistir dados em produção é criar volumes gerenciados explicitamente. Vamos usar o PostgreSQL como exemplo, pois ele exige persistência rigorosa para evitar perda de dados.

1.1 Criando um Volume via Linha de Comando

No terminal do seu servidor Linux, execute o comando abaixo para criar um volume nomeado chamado postgres-data:

docker volume create postgres-data

Você pode verificar se o volume foi criado listando todos os volumes disponíveis:

docker volume ls

A saída deve exibir algo como local postgres-data.

1.2 Executando o Container com o Volume

Agora, inicie um container PostgreSQL montando esse volume no diretório padrão onde o PostgreSQL armazena seus dados (/var/lib/postgresql/data):

docker run --name postgres-db -e POSTGRES_PASSWORD=senha_segura -v postgres-data:/var/lib/postgresql/data -d postgres:latest

Neste comando, a flag -v (ou --volume) associa o volume nomeado ao diretório interno do container. Note que não especificamos um caminho no host; o Docker cuida disso automaticamente.

1.3 Verificando a Persistência

Para testar, entre no container e crie um arquivo de teste:

docker exec -it postgres-db bash
touch /var/lib/postgresql/data/teste_persistencia.txt
exit

Agora, remova o container:

docker rm -f postgres-db

Se você criar um novo container usando o mesmo volume postgres-data, o arquivo teste_persistencia.txt estará lá. Isso confirma que os dados sobreviveram à remoção do container.

Passo 2: Utilizando Bind Mounts para Desenvolvimento e Configuração

Bind mounts são extremamente úteis quando você precisa editar arquivos de configuração diretamente no host ou compartilhar código fonte entre o host e o container durante o desenvolvimento.

2.1 Estrutura de Diretórios

Crie um diretório local no seu servidor Linux para armazenar os dados da aplicação:

mkdir -p /opt/meu-app/data
mkdir -p /opt/meu-app/config

2.2 Montando o Bind Mount

Inicie um container nginx simples, montando seus diretórios locais:

docker run --name nginx-bind \
  -v /opt/meu-app/data:/usr/share/nginx/html \
  -v /opt/meu-app/config/nginx.conf:/etc/nginx/nginx.conf:ro \
  -d nginx:alpine

Análise da flag -v:

  • /opt/meu-app/data:/usr/share/nginx/html: Monta o diretório local de dados no diretório padrão de conteúdo do Nginx.
  • /opt/meu-app/config/nginx.conf:/etc/nginx/nginx.conf:ro: Monta o arquivo de configuração com a flag :ro (read-only). Isso impede que o container tente escrever no arquivo de configuração, prevenindo erros de permissão e garantindo que as configurações sejam controladas apenas pelo host.

Se você criar um arquivo HTML em /opt/meu-app/data/index.html no host Linux, ele estará imediatamente disponível no endereço IP do container. Alterações no host são refletidas instantaneamente no container, o que é ideal para desenvolvimento rápido.

Passo 3: Orquestração com Docker Compose

Em ambientes reais, raramente usamos comandos docker run isolados. O docker compose é a ferramenta padrão para definir e executar aplicações multi-container. Ele utiliza um arquivo YAML (docker-compose.yml) para definir volumes, serviços e redes.

3.1 Estrutura do Projeto

Crie uma pasta para seu projeto e adicione o arquivo docker-compose.yml:

mkdir -p ~/projeto-webapp
cd ~/projeto-webapp
nano docker-compose.yml

3.2 Definindo Volumes no Compose

Insira o seguinte conteúdo no arquivo. Este exemplo define uma aplicação web (Node.js simulado) e um banco de dados MongoDB, ambos com persistência:

version: '3.8'

services:
  webapp:
    image: node:18-alpine
    container_name: app-container
    volumes:
      # Bind mount para código fonte (desenvolvimento)
      - ./src:/usr/src/app/src
      # Volume gerenciado para uploads do usuário
      - app-uploads:/usr/src/app/uploads
    depends_on:
      - database

  database:
    image: mongo:6
    container_name: mongo-db
    volumes:
      # Volume gerenciado para dados do MongoDB
      - mongo-data:/data/db
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: senha_forte

# Definição dos volumes no escopo raiz
volumes:
  app-uploads:
  mongo-data:

Explicação Técnica:

  1. No bloco volumes de cada serviço, especificamos as montagens.
  2. ./src:/usr/src/app/src é um bind mount relativo ao diretório do compose. Ideal para hot-reload.
  3. app-uploads: e mongo-data: referenciam volumes nomeados definidos no final do arquivo, sob a chave raiz volumes.

3.3 Iniciando a Stack

Rode o comando para iniciar os serviços em segundo plano:

docker compose up -d

O Docker criará automaticamente os volumes projeto-webapp_app-uploads e projeto-webapp_mongo-data (o prefixo é o nome da pasta do projeto). Verifique com:

docker volume ls

Passo 4: Gerenciamento e Manutenção de Volumes

Como sysadmin, você precisará gerenciar esses volumes ao longo do tempo. Isso inclui backups, limpeza de dados órfãos e migração.

4.1 Identificando Dados Órfãos

Volumes não utilizados por containers consomem espaço em disco. Para remover volumes que não estão associados a nenhum container ativo:

docker volume prune

Para remover volumes órfãos de containers já excluídos, use:

docker volume prune -f

Aviso: Sempre tenha certeza antes de rodar prune, pois isso apaga dados permanentemente.

4.2 Backup de Volumes

Uma prática essencial é backup regular dos volumes. O método mais seguro é usar um container temporário para ler o volume e compactá-lo em um arquivo tar no host.

Para fazer backup do volume mongo-data:

docker run --rm \
  -v mongo-data:/volume:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/mongo-backup.tar.gz -C /volume .

Este comando:

  1. Cria um container temporário baseado na imagem alpine.
  2. Monta o volume mongo-data em leitura apenas (:ro) no caminho /volume.
  3. Monta o diretório atual do host em /backup.
  4. Executa o comando tar para compactar todo o conteúdo de /volume e salvar como /backup/mongo-backup.tar.gz.

4.3 Restauração do Backup

Para restaurar, crie um novo volume e descompacte os dados nele:

docker volume create mongo-data-restored
docker run --rm \
  -v mongo-data-restored:/volume \
  -v $(pwd):/backup \
  alpine tar xzf /backup/mongo-backup.tar.gz -C /volume

Agora, você pode iniciar seu banco de dados apontando para mongo-data-restored.

Passo 5: Boas Práticas e Segurança

Para garantir uma infraestrutura Docker sólida no Linux, siga estas diretrizes:

  1. Use Volumes Gerenciados para Dados Críticos: Nunca armazene dados de bancos de dados em bind mounts diretos do host a menos que haja uma razão específica de compatibilidade. Os volumes gerenciados oferecem melhor isolamento e performance.
  2. Defina Permissões Adequadas: Ao usar bind mounts, certifique-se de que o usuário dentro do container (UID/GID) tenha permissão de escrita no diretório do host. Use chown ou chmod no host antes de iniciar o container para evitar erros de "Permission denied".
  3. Não Confie em Camadas do Container: Nunca assuma que dados salvos apenas na camada de escrita do container persistirão. Sempre use volumes explícitos.
  4. Mapeie Portas e Volumes Explicitamente: Em scripts de automação ou arquivos Compose, seja explícito sobre os nomes dos volumes. Isso facilita a leitura e manutenção por outros membros da equipe.
  5. Monitore o Uso de Disco: Volumes podem crescer rapidamente. Use comandos como docker system df para monitorar quanto espaço os volumes estão consumindo no seu servidor Linux.

Conclusão

A persistência de dados em Docker não é um detalhe secundário, mas sim a base da confiabilidade de seus containers. Ao dominar a diferença entre bind mounts e volumes gerenciados, e ao utilizar ferramentas como docker compose para orquestração, você garante que suas aplicações sejam portáveis, resilientes e fáceis de manter.

Lembre-se: containers são efêmeros, mas os dados devem ser eternos. Planeje sua estratégia de volumes desde o início do desenvolvimento para evitar dores de cabeça em produção.

Compartilhar: Link copiado!
Esse tutorial foi útil?

Comentários (0)

Seja o primeiro a comentar.

Deixe seu comentário

Seu comentário será analisado antes de ser publicado.

0/2000