É uma abordagem avançada no Docker que utiliza múltiplos estágios (stages) dentro de um único Dockerfile. Suas vantanges são:
Sem o Multi-Stage a imagem pode ficar cheia de arquivos que não são necessários para rodar a aplicação em produção, como ferramentas de complicação, dependências usadas apenas no build e arquivos temporários. Com o Multi-Stage, esses arquivos não entram na imagem final
O que são stages?
A ideia do Multi-Stage Build é dividir o Dockerfile em múltiplos estágios (stages), onde cada estágio tem um propósito específico.
Cada estágio tem um propósito diferente:
- Build Stage (Compilação): Responsável por compilar o código e gerar os arquivos finais.
- Intermediate Stages (Intermediários - opcional): Pode ser usado para testes, minificação, otimizações.
- Final Stage (Runtime/Execução): Apenas os arquivos essenciais são copiados e a aplicação roda com uma imagem menor.
Cada estágio é identificado pelo comando FROM
, e podemos copiar arquivos entre eles usando COPY --from=<estágio>
.
Dockerfile sem Multi-Stage Build (Imagem pesada)
1. Criando o Dockerfile
# Usa a imagem do SDK do .NET (grande)
FROM mcr.microsoft.com/dotnet/sdk:8.0
# Define o diretório de trabalho
WORKDIR /app
# Copia todos os arquivos do projeto para dentro do contêiner
COPY . .
# Compila a aplicação e gera os arquivos de saída
RUN dotnet publish -c Release -o /out
# Define o diretório de trabalho para os arquivos compilados
WORKDIR /out
# Define o comando de entrada quando o contêiner for iniciado
ENTRYPOINT ["dotnet", "MinhaApi.dll"]
2. Construindo a imagem
docker build -t minhaapi:sem-multi-stage .
- Baixar a imagem do SDK .NET
- Copiar os arquivos para dentro do contêiner
- Compilar o código
- Criar a imagem final
Problema: Essa imagem fica grande porque contém o SDK inteiro, que só é necessário para compilar, não para rodar a API.
Rodando o contêiner
docker run -p 8080:80 minhaapi:sem-multi-stage
A API vai rodar na porta 8080
. Mas o contêiner está pesado (+1GB).
Dockerfile com Multi-Stage Build (Imagem otimizada)
Agora, vamos ver a versão otimizada que gera uma imagem menor e mais eficiente.
# Base para runtime (imagem mínima)
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 8080
# Estágio de build (compila o código-fonte)
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MinhaApi/MinhaApi.csproj", "MinhaApi/"]
RUN dotnet restore "MinhaApi/MinhaApi.csproj"
COPY . .
WORKDIR "/src/MinhaApi"
RUN dotnet build -c Release -o /app/build
# Estágio intermediário (rodando testes)
FROM build AS test
WORKDIR /src
RUN dotnet test --no-restore --verbosity normal
# Estágio de publicação (gera os arquivos finais)
FROM build AS publish
RUN dotnet publish "MinhaApi.csproj" -c Release -o /app/publish /p:UseAppHost=false
# Estágio final (imagem pronta para produção)
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MinhaApi.dll"]
Multi-Stage Build vs. Docker Tradicional
Característica | Docker Normal | Multi-Stage Build |
---|---|---|
Tamanho da Imagem | Grande, pois inclui dependências de compilação e ferramentas extras | Menor, pois só mantém o necessário na imagem final |
Etapas do Build | Tudo acontece em um único estágio | Divide em múltiplos estágios, reutilizando artefatos |
Segurança | Possui mais ferramentas e arquivos desnecessários na imagem final | Apenas o essencial é mantido, reduzindo superfície de ataque |
Complexidade do Dockerfile | Simples, mas menos otimizado | Um pouco mais complexo, mas mais eficiente |
Performance no Deploy | Mais lenta devido ao tamanho maior da imagem | Mais rápida, pois a imagem final é menor |
Top comments (0)