Docker Multi-Stage no Node.js permite usar uma etapa completa para instalar dependências e compilar a aplicação, copiando para a imagem final apenas os arquivos necessários em produção. O resultado costuma ser menor, mais rápido para distribuir e com superfície de ataque reduzida.
Dockerfile básico
FROM node:22-bookworm-slim AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM deps AS build
COPY . .
RUN npm run build
RUN npm prune --omit=dev
FROM node:22-bookworm-slim AS runtime
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /app/package.json ./
COPY --from=build /app/package-lock.json ./
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/server.js"]Por que separar etapas
Compiladores, caches e dependências de desenvolvimento não precisam estar no runtime. A etapa final recebe somente artefatos de execução.
Cache eficiente
Copie primeiro os manifests e execute npm ci antes de copiar o código. Assim, mudanças em arquivos da aplicação não invalidam a camada de dependências.
.dockerignore
node_modules
.git
coverage
.env
npm-debug.log
Dockerfile*Não envie segredos ou arquivos desnecessários ao contexto de build.
npm ci
Use o lockfile versionado para instalação reproduzível. Consulte Lockfile no Node.js.
Dependências nativas
Se pacotes compilam addons, mantenha compatibilidade entre a etapa de build e runtime. Copiar binários entre distribuições incompatíveis pode falhar.
Usuário não root
Execute a aplicação com usuário sem privilégios e garanta permissões corretas nos arquivos copiados.
Imagens fixadas
Evite depender somente de tags mutáveis. Registre versões e, quando necessário, fixe digest para builds reproduzíveis.
Segredos no build
Não use ARG ou ENV para tokens permanentes, pois podem aparecer no histórico. Use secrets do BuildKit quando o build realmente precisar de credenciais.
BuildKit cache mount
RUN --mount=type=cache,target=/root/.npm npm ciO cache acelera builds sem ser copiado para a imagem final.
Health e shutdown
O container deve responder a probes e encerrar de forma graciosa. Veja Graceful Shutdown no Node.js.
Inspeção
Compare tamanho, camadas e pacotes antes e depois. Um scanner de vulnerabilidades ajuda a identificar dependências do sistema operacional e bibliotecas incluídas.
Erros comuns
- copiar o repositório inteiro para runtime;
- incluir devDependencies;
- usar
npm installsem lockfile; - executar como root;
- misturar Alpine e glibc com addons nativos;
- colocar segredo em ARG;
- não definir .dockerignore.
Conclusão
Docker Multi-Stage no Node.js separa construção e execução, reduzindo imagem e dependências desnecessárias. Organize camadas para aproveitar cache, use usuário não root e copie apenas o artefato final.
Consulte a documentação de multi-stage builds do Docker e a documentação de boas práticas das imagens Node.js.




