A estratégia copy-on-write (CoW)
Copy-on-Write é uma técnica de otimização onde múltiplos processos/containers compartilham os mesmos dados até que alguém tente modificá-los. Só então é feita uma cópia.
Princípio: “Por que copiar algo que ninguém vai modificar?”
Como Funciona em Containers
Section titled “Como Funciona em Containers”1. Camadas de Imagem (Image Layers)
Section titled “1. Camadas de Imagem (Image Layers)”Imagens Docker são compostas por camadas empilhadas, cada uma somente leitura:
┌─────────────────────────┐│ Container Layer (R/W) │ ← Camada gravável (CoW ativo aqui)├─────────────────────────┤│ Layer 3: app files │ ← Somente leitura├─────────────────────────┤│ Layer 2: dependencies │ ← Somente leitura├─────────────────────────┤│ Layer 1: base OS │ ← Somente leitura└─────────────────────────┘2. Compartilhamento Entre Containers
Section titled “2. Compartilhamento Entre Containers”Múltiplos containers da mesma imagem compartilham as camadas base:
Container A ──┐Container B ──┼──→ [Mesmas camadas base compartilhadas]Container C ──┘Economia: Se a imagem tem 500 MB e você tem 10 containers, não ocupa 5 GB, mas ~500 MB + pequenas diferenças individuais.
Funcionamento do CoW em Ação
Section titled “Funcionamento do CoW em Ação”Cenário 1: Leitura de Arquivo
Section titled “Cenário 1: Leitura de Arquivo”Container lê /etc/config.conf ↓Lê diretamente da camada base (compartilhada)Nenhuma cópia é feitaCenário 2: Modificação de Arquivo
Section titled “Cenário 2: Modificação de Arquivo”Container modifica /etc/config.conf ↓1. Sistema detecta tentativa de escrita2. Copia o arquivo para a camada do container3. Modifica a cópia (não o original)4. Outros containers continuam vendo o originalExemplo Prático
Section titled “Exemplo Prático”Suponha um arquivo app.py de 1 MB na imagem base:
Estado Inicial:├── Layer base: app.py (1 MB) [compartilhado]├── Container 1: [vazio] → lê app.py da base├── Container 2: [vazio] → lê app.py da base└── Container 3: [vazio] → lê app.py da base
Após Container 1 modificar app.py:├── Layer base: app.py (1 MB) [compartilhado]├── Container 1: app.py (1 MB) [cópia modificada] ← CoW acionado├── Container 2: [vazio] → ainda lê da base└── Container 3: [vazio] → ainda lê da baseExemplo de Dockerfile e Camadas
Section titled “Exemplo de Dockerfile e Camadas”FROM ubuntu:22.04 # Layer 1 (base)RUN apt-get update # Layer 2 (+ metadata de pacotes)RUN apt-get install python3 # Layer 3 (+ Python)COPY app.py /app/ # Layer 4 (+ seu código)CMD ["python3", "/app/app.py"] # Metadata (não cria layer)Cada instrução RUN, COPY, ADD cria uma nova camada imutável.
CoW em Prática: Verificando
Section titled “CoW em Prática: Verificando”Ver camadas de uma imagem:
docker image inspect nginx:latest | grep -A 20 LayersVer uso de disco por container:
docker ps -s- size = camada gravável do container
- virtual size = tamanho total (incluindo imagem base)
Melhores Práticas
Section titled “Melhores Práticas”1. Minimize camadas
Section titled “1. Minimize camadas”Agrupe comandos RUN:
# ❌ Ruim - 3 camadasRUN apt-get updateRUN apt-get install -y curlRUN apt-get clean
# ✅ Bom - 1 camadaRUN apt-get update && \ apt-get install -y curl && \ apt-get clean2. Use .dockerignore
Section titled “2. Use .dockerignore”Evite copiar arquivos desnecessários
3. Multi-stage builds
Section titled “3. Multi-stage builds”Reduza o tamanho final:
FROM golang:1.20 AS builderCOPY . .RUN go build -o app
FROM alpine:latestCOPY --from=builder /app /app # Só copia o binário4. Volume para dados mutáveis
Section titled “4. Volume para dados mutáveis”Dados que mudam frequentemente devem estar em volumes:
docker run -v /host/data:/container/data minhaimagem:latestResumo Visual
Section titled “Resumo Visual”┌─────────────────────────────────────────┐│ Container Filesystem (Union Mount) │├─────────────────────────────────────────┤│ R/W Layer (Container-specific) │ ← CoW acontece aqui│ ├── modified_file.txt (cópia) ││ └── new_log.txt (novo arquivo) │├─────────────────────────────────────────┤│ R/O Layer 3 (App layer) │ ← Compartilhado│ ├── app.py ││ └── requirements.txt │├─────────────────────────────────────────┤│ R/O Layer 2 (Dependencies) │ ← Compartilhado│ └── /usr/lib/python3/* │├─────────────────────────────────────────┤│ R/O Layer 1 (Base OS) │ ← Compartilhado│ └── /bin, /etc, /lib, etc. │└─────────────────────────────────────────┘Conclusão
Section titled “Conclusão”Copy-on-Write é fundamental para a eficiência de containers, permitindo que centenas de containers rodem em um único host sem duplicar todo o sistema de arquivos. Esta técnica é um dos pilares que torna a conteinerização tão eficiente em termos de recursos.