Trade-offs entre Distroless & Alpine
Escolha uma imagem base de contêiner com base na compatibilidade libc, tamanho da imagem e depurabilidade - não por hábito.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
# Padrão: Debian slim (glibc) - melhor compatibilidade npm
FROM node:24-bookworm-slim AS prod
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY dist ./dist
USER node
CMD ["node", "dist/main.js"]Quando usar isso: APIs Node.js Greenfield sem módulos nativos que exijam compilações específicas para musl. Este é o padrão da equipe.
Exemplo de Trabalho
Três opções de estágio final para a mesma API Express:
#syntax=docker/dockerfile:1
FROM node:24-bookworm-slim AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY tsconfig.json src ./
RUN npm run build
# Opção A: bookworm-slim (padrão recomendado)
FROM node:24-bookworm-slim AS slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/main.js"]
# Opção B: Alpine (menor, musl)
FROM node:24-alpine AS alpine
WORKDIR /app
RUN apk add --no-cache libc6-compat
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/main.js"]
# Opção C: Distroless (minimalista, sem shell)
FROM gcr.io/distroless/nodejs24-debian12 AS distroless
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=slim /app/node_modules ./node_modules
USER nonroot
CMD ["dist/main.js"]docker build --target slim -t api:slim .
docker build --target alpine -t api:alpine .
docker build --target distroless -t api:distroless .O que isso demonstra:
- Mesmo
dist/compilado em todos os três tempos de execução - Alpine pode precisar de
libc6-compatpara alguns binários pré-compilados - Distroless copia
node_modulesde um estágio de compilação glibc (nunca compile dentro do distroless)
Análise Profunda
libc: glibc vs musl
| Base | libc | Tamanho Típico | Módulos nativos npm |
|---|---|---|---|
bookworm-slim | glibc | ~180 MB | Melhor compatibilidade |
alpine | musl | ~120 MB | Problemas frequentes de reconstrução (sharp, bcrypt, prisma) |
distroless/nodejs24 | glibc | ~130 MB | Bom se compilado em estágio glibc |
O próprio Node envia binários pré-compilados para Linux glibc. Alpine frequentemente força npm rebuild ou compilações de origem.
Quando o Alpine Funciona
- Apenas dependências puras de JavaScript
- Você controla as dependências nativas e testa
npm cino Alpine em CI - O tamanho da imagem no registro importa (muitos pulls de edge)
Quando o Distroless Funciona
- API de produção sem depuração no contêiner
- Política de segurança proíbe shells e gerenciadores de pacotes em tempo de execução
- Você depura por meio de logs, métricas e pods de depuração efêmeros (K8s)
Trade-off de Depuração
# bookworm-slim: shell disponível
docker run -it --entrypoint bash api:slim
# distroless: sem shell - use pod de depuração ou copie core dumps para fora da caixa
kubectl debug pod/api-xyz -it --image=busyboxArmadilhas
sharpno Alpine - falha comum. Correção: use bookworm-slim ou a documentação oficial de instalação dosharppara Alpine com versões fixadas.- Compilando no Mac, executando Alpine - incompatibilidade de arquitetura e libc. Correção: sempre use
docker buildno alvo de CI Linux. prisma generateno estágio errado - ligações OpenSSL incorretas. Correção: gere no estágio de compilação glibc; copie os artefatos.- Distroless sem
USER nonroot- executa como root por padrão em algumas tags. Correção:USER nonrootexplícito. - Assumindo que menor sempre significa mais rápido - o alocador musl é diferente; teste de desempenho da sua carga de trabalho. Correção: teste de carga antes de mudar.
apkdo Alpine no Dockerfile de produção - incha as camadas. Correção: multi-estágio; o tempo de execução não tem gerenciador de pacotes.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| bookworm-slim | Padrão para APIs Node | Você precisa da imagem menor possível e testou o Alpine |
| Alpine | Implantações de edge sensíveis ao tamanho, stack JS puro | Uso pesado de módulos nativos |
| Distroless | Produção endurecida, K8s com ferramentas de depuração em outro lugar | A equipe depende de docker exec bash |
| Imagens Node Chainguard | Bases endurecidas de cadeia de suprimentos | Você não pode adotar um novo cadência de imagem base |
FAQs
Qual é o nosso padrão de equipe?
node:24-bookworm-slim, a menos que uma necessidade medida (tamanho, mandato do scanner de segurança) justifique Alpine ou distroless.
Como testar a compatibilidade do Alpine em CI?
Adicione um job de matriz: docker build --target alpine e execute testes de fumaça. Falhe o PR se os módulos nativos quebrarem.
Posso usar distroless com Fastify ou NestJS?
Sim. Compile em bookworm-slim, copie dist/ e node_modules para distroless. Nenhuma alteração de código necessária.
O distroless inclui npm?
Não. Todas as instalações acontecem em um estágio anterior. O tempo de execução apenas executa node.
Diferença de tamanho entre Alpine e slim?
Frequentemente economiza 40-80 MB, dependendo do node_modules. Meça com docker images após o npm ci de produção.
E o `node:24-alpine3.20` fixado?
Fixe versões menores do Alpine em ambientes regulamentados. Acompanhe as notas de lançamento do Node Docker para atualizações de imagem base.
Relacionado
- Builds Multi-Estágio - compile em imagem completa, execute em mínima
- Slimming de Imagem - tamanho sem risco de musl
- Contêineres Não-Root -
USER node/nonroot - Noções Básicas de Docker - primeiro Dockerfile
- Melhores Práticas de Docker - checklist da seção
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 e NestJS 11.