Uma imagem Docker de 1,2GB carrega compiladores, gerenciadores de pacote e devDependencies para servir uma aplicação que precisa de 90MB. Multi-stage builds resolvem isso separando compilação de execução: você constrói em um estágio e copia só o artefato para o estágio final. O app Express deste exemplo caiu de 1,1GB para 150MB com Alpine e para 90MB com distroless, sem mudar uma linha de código.
O que sobra dentro de uma imagem single-stage?
O estágio único mistura o que constrói com o que executa. node_modules completo com devDependencies, gcc, curl e cache do pip entram em produção junto. Cada pacote extra aparece no relatório do Trivy e amplia a superfície de ataque; pulls de 1GB em cada nó do cluster custam minutos por deploy.
Como funciona a anatomia de um multi-stage build?
O Dockerfile declara dois FROM. O estágio builder instala tudo e compila; o estágio runtime parte de uma base limpa e recebe só o resultado com COPY --from=builder /app/dist ./dist. Essa diretiva carrega o truque inteiro: camadas do builder jamais chegam à imagem final.
Qual base image escolher para o runtime?
Variantes Alpine encolhem a imagem, e musl libc quebra módulos nativos compilados contra glibc; teste antes de migrar. Imagens distroless shipam sem shell e sem gerenciador de pacotes, então não existe ferramenta para um atacante explorar. A tag :debug devolve busybox e salva o incident response quando você precisa executar algo dentro do pod.
Como acelerar o build com layer caching?
A ordem das instruções define o cache. Copie package.json antes do código-fonte, rode a instalação de dependências e só então copie o resto. Uma alteração de código reaproveita as camadas de dependência e transforma builds de minutos em segundos.
O que muda em cada linguagem?
- Node: rode
npm ci --omit=devno estágio final e copie a saída do tsc do builder - Go: compile com
CGO_ENABLED=0e suba um binário estático de ~10MB sobre scratch - Python: mantenha as dependências de build do pip no builder e copie as wheels para o estágio slim
Como endurecer a segurança da imagem?
Adicione um usuário non-root com USER, fixe a base por digest (node@sha256:...) em vez de tag móvel e use COPY --chown para evitar arquivos owned pelo root. Em Kubernetes, monte o root filesystem como read-only. Nenhuma dessas medidas exige mudança no código.
Como verificar o resultado?
dive inspeciona camada por camada e aponta desperdício; docker history expõe segredo colado em ARG ou RUN. O Trivy roda no CI e bloqueia o deploy quando CVE alta aparece na imagem final.
O ganho composto aparece no pipeline: pulls dez vezes mais rápidos, scan enxuto e menos pacote para patchear na próxima emergência. Comece pelo Dockerfile mais antigo do monorepo; o de 1,2GB sempre existe.
Curtiu o conteúdo?
Construo produtos web e soluções com IA do jeito certo — arquitetura sólida, código sustentável e entrega real.
Vamos conversar