DEV Community

Victor Zarzar
Victor Zarzar

Posted on

# Otimizando Imagens Docker: Boas Práticas para Builds Eficientes

As imagens Docker são a base das aplicações containerizadas. No entanto, imagens grandes e ineficientes podem resultar em builds mais lentos, tempos maiores de implantação e aumento no uso de armazenamento. Otimizar imagens garante entregas mais rápidas, melhor desempenho e menor consumo de recursos.

Efeitos de Imagens Grandes e Ineficientes na Implantação

Imagens pesadas não apenas consomem mais espaço em disco, mas também aumentam o tempo de transferência na rede, o que é crítico em pipelines CI/CD e implantações em nuvem. Imagens eficientes tornam as operações mais ágeis e reduzem custos operacionais.

1. Uso de Imagens Base Slim

Escolhendo Imagens Mínimas (Alpine, Variantes Slim)

Comece com uma imagem base mínima ou "slim" para reduzir o excesso de pacotes. Por exemplo, em vez de usar python:3.10, considere python:3.10-slim ou alpine. Imagens mínimas removem pacotes e bibliotecas desnecessárias, resultando em imagens menores e mais seguras.

Reduzindo Dependências Desnecessárias

Instale apenas os pacotes e bibliotecas indispensáveis para sua aplicação. Evite incluir ferramentas de build ou arquivos de documentação na imagem final de runtime.

Equilibrando Tamanho e Funcionalidade

Embora imagens slim sejam pequenas, algumas aplicações podem exigir bibliotecas específicas. Escolha uma imagem base que equilibre tamanho reduzido e funcionalidade necessária, evitando erros em tempo de execução.

2. Multi-Stage Builds

O Que São Multi-Stage Builds

Multi-stage builds permitem separar o ambiente de build do ambiente de runtime. Essa técnica possibilita incluir ferramentas de compilação em uma etapa e copiar apenas os artefatos finais para a imagem final, reduzindo drasticamente o tamanho.

Separando Ambientes de Build e Runtime

No multi-stage:

Stage 1: compila ou constrói a aplicação com todas as dependências necessárias.

Stage 2: copia apenas o resultado final para uma imagem base menor, descartando ferramentas de build e arquivos intermediários.

Exemplo prático (Node.js + pnpm):

FROM node:22-alpine AS base

WORKDIR /app

COPY package*.json pnpm-lock.yaml* ./

RUN npm install -g pnpm \
    && pnpm install --frozen-lockfile

EXPOSE 3000

CMD ["pnpm", "run", "dev"]
Enter fullscreen mode Exit fullscreen mode

Este modelo reduz bastante o tamanho final, eliminando ferramentas de build e reaproveitando cache de dependências via pnpm.

Exemplo com Python Slim:

FROM python:3.12-slim

ENV PYTHONPATH=/app

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir --upgrade -r requirements.txt

COPY alembic.ini .

COPY ./entrypoint.sh .

COPY . .

EXPOSE 8000

ENTRYPOINT [ "./entrypoint.sh" ]

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
Enter fullscreen mode Exit fullscreen mode

A imagem final permanece extremamente pequena, contendo apenas o runtime necessário.

3. Como as Camadas Docker Afetam o Tamanho da Imagem

Cada instrução no Dockerfile (RUN, COPY, ADD) cria uma camada. Apesar do cache, muitas camadas pequenas podem aumentar o tamanho total da imagem.

Uma forma de otimizar é combinar comandos relacionados em um único RUN:

RUN apt-get update && \
    apt-get install -y curl git && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
Enter fullscreen mode Exit fullscreen mode

Isso gera uma única camada, mantendo a imagem menor.

Além disso, sempre remova caches e arquivos temporários dentro do mesmo comando RUN. Caso contrário, eles permanecem nas camadas anteriores e aumentam o tamanho final.

4. Otimização com .dockerignore

O arquivo .dockerignore impede que arquivos desnecessários sejam enviados ao contexto de build.

Exemplo básico:

node_modules
.next
.tests
__pycache__
__pytest__
builds/
venv
logs
Enter fullscreen mode Exit fullscreen mode

Isso reduz drasticamente o contexto enviado para o Docker, acelerando o build e evitando camadas desnecessárias.

5. Cache de Forma Eficiente

Podemos aproveitar o cache do Docker copiando primeiro os arquivos de dependências:

Para Node:

COPY package.json pnpm-lock.yaml ./
RUN pnpm install
Enter fullscreen mode Exit fullscreen mode

Para Python:

COPY requirements.txt .
RUN pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

As dependências só serão reprocessadas quando realmente mudarem.

6. Boas Práticas Gerais

  • Use tags como DOCKER_TAG=1.0.0 ou IMAGE_VERSION=1.0.0 para rastrear versões e evitar confusão entre builds

  • Faça auditorias periódicas com docker image ls e remova imagens antigas

  • Integre otimizações no pipeline CI/CD para garantir builds consistentes, menores e mais rápidos

  • Evite ferramentas de teste e documentação na imagem final de produção

  • Prefira imagens minimalistas sempre que possível

Conclusão

Adotar essas boas práticas eleva o desempenho das aplicações, reduz custos operacionais e garante imagens compactas e eficientes para ambientes modernos e escaláveis. Multi-stage builds, uso de imagens slim, limpeza de camadas e .dockerignore são pilares essenciais para criar imagens com alta performance e fácil manutenção.

Top comments (0)