Introdução: por que nível avançado?
\nA containerização de aplicações C# baseadas em .NET deixou de ser apenas uma tendência — é um padrão industrial. No nível inicial, um Dockerfile básico com FROM mcr.microsoft.com/dotnet/aspnet é suficiente. No entanto, em ambientes de produção, surgem desafios que exigem um entendimento mais profundo: minimização do tamanho da imagem, segurança, arquitetura multi-contêiner, gerenciamento eficiente de configuração e depuração.
Este artigo é destinado a desenvolvedores que já conhecem os fundamentos do Docker e C#, mas desejam avançar para o próximo nível. Abordaremos técnicas avançadas que permitirão criar imagens leves, seguras e facilmente escaláveis para suas aplicações .NET.
\n\n1. Compilação multi-estágio (Multi-stage build): a arte das imagens leves
\nUm problema clássico — as imagens do .NET SDK pesam mais de 1,5 GB. Levá-las para produção é inútil e perigoso. A compilação multi-estágio resolve esse problema, separando a etapa de compilação da etapa de execução.
\n\nDockerfile avançado com multi-stage
\nEm vez de simplesmente copiar os arquivos binários, usamos as imagens oficiais do SDK para compilar e, em seguida, copiamos o resultado para a imagem mínima aspnet.
# Etapa 1: Compilação\nFROM mcr.microsoft.com/dotnet/sdk:8.0 AS build\nWORKDIR /app\n\n# Copiamos apenas os arquivos do projeto (otimização de cache)\nCOPY src/MyApp.csproj .\nRUN dotnet restore\n\n# Copiamos o restante do código\nCOPY src/ .\nRUN dotnet publish -c Release -o /app/publish\n\n# Etapa 2: Runtime\nFROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime\nWORKDIR /app\n\n# Adicionamos um usuário não privilegiado\nRUN adduser --disabled-password --gecos '' appuser\nUSER appuser\n\nCOPY --from=build /app/publish .\n\nEXPOSE 8080\nENV ASPNETCORE_URLS=http://+:8080\nENTRYPOINT ["dotnet", "MyApp.dll"]\nO que é importante aqui:
\n- \n
- Cache de camadas: primeiro copiamos apenas o
.csproje executamosdotnet restore. Enquanto as dependências não mudarem, o Docker usará o cache para esta camada. \n - Usuário não privilegiado:
appuser— é criticamente importante para a segurança em produção. \n - Porta 8080: no .NET 8, a porta padrão é 8080, alinhada com os padrões modernos de nuvem. \n
Dica: Compilação Trimmed e AOT
\nPara reduzir ainda mais o tamanho, use Trimming (remoção de código não utilizado) ou Native AOT. Isso permite obter imagens de 10 a 30 MB.
\n# Para ReadyToRun (R2R) e Trimming\nRUN dotnet publish -c Release -r linux-x64 --self-contained true \\\n -p:PublishTrimmed=true \\\n -p:PublishSingleFile=true \\\n -o /app/publish\nImportante: AOT impõe restrições à reflexão e ao carregamento dinâmico de assemblies. Antes de usar, certifique-se de que seu código é compatível.
\n\n2. Gerenciamento de configuração e segredos
\nArmazenar strings de conexão e chaves de API dentro da imagem é um erro grave. No nível avançado, usamos Docker Secrets, variáveis de ambiente e integração com appsettings.json.
Sobrescrevendo appsettings via Docker
\nO .NET possui um mecanismo interno de prioridades de configuração. Podemos passar configurações através de variáveis de ambiente, que são mapeadas automaticamente para as seções de configuração.
\n// No código C#\nvar builder = WebApplication.CreateBuilder(args);\nbuilder.Configuration\n .AddJsonFile("appsettings.json", optional: false)\n .AddEnvironmentVariables(); // Sobrescreve valores do JSON\nExecutamos o contêiner:
\ndocker run -d -p 8080:8080 \\\n -e "ConnectionStrings__DefaultConnection=Server=db;Database=myapp;User Id=sa;Password=MyPass123!" \\\n -e "Logging__LogLevel__Default=Warning" \\\n