Guia de deploy .NET em produção
Um passo a passo direto para tirar sua aplicação do ambiente local e publicar com mais segurança, previsibilidade e observabilidade — usando containers, variáveis de ambiente, health checks e pipeline automatizado.
Visão geral
O que um deploy .NET “de verdade” precisa ter
Publicar uma aplicação em produção não é só fazer dotnet publish
e subir os arquivos em algum servidor. Um deploy saudável precisa considerar
empacotamento, configuração por ambiente,
health checks, logs, métricas,
rollback e um fluxo confiável de entrega.
Neste guia, vamos usar como referência uma aplicação ASP.NET Core ou Blazor hospedada em container, com pipeline automatizado e boas práticas para rodar em uma plataforma moderna como a FoundryShip.
A ideia é simples: deixar sua aplicação repetível, observável e fácil de operar. Menos improviso em produção e menos susto quando o tráfego começar a subir.
Antes de começar
Pré-requisitos mínimos para um deploy limpo
Projeto organizado
Tenha um projeto compilando localmente sem warnings críticos, com dependências explícitas e separação clara entre aplicação, infraestrutura e configuração.
Configuração por ambiente
Connection strings, chaves e endpoints não devem ficar hardcoded. Produção precisa consumir variáveis de ambiente ou secrets gerenciados.
Pipeline reproduzível
O mesmo fluxo que gera a imagem local deve ser capaz de gerar a imagem em CI/CD, com versionamento e possibilidade de rollback.
Passo a passo
1. Prepare a aplicação para rodar fora da sua máquina
Seu app precisa partir do princípio de que o ambiente de produção é efêmero: container sobe, desce, escala horizontalmente e pode ser recriado a qualquer momento.
Isso significa evitar dependência de arquivos locais, diretórios temporários persistidos manualmente e qualquer configuração que só funcione na sua máquina de desenvolvimento.
- Use variáveis de ambiente para segredos e configuração sensível.
- Grave arquivos persistentes em object storage, não no disco local do app.
- Mantenha o app stateless sempre que possível.
- Se usar sessão, prefira um cache distribuído.
Containerização
2. Empacote sua aplicação em uma imagem de produção
O caminho mais previsível para deploy moderno em .NET é publicar a aplicação como container. Isso padroniza build, execução, rollback e escala.
Exemplo de Dockerfile multi-stage
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet publish src/MyApp.Api/MyApp.Api.csproj -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final
WORKDIR /app
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.Api.dll"] Esse modelo separa build e runtime, gerando uma imagem final menor e mais limpa para produção.
Se você preferir, também pode usar a publicação de containers com
dotnet publish,
mas o Dockerfile multi-stage continua sendo uma opção excelente quando você quer mais controle
sobre a imagem e o processo.
- Evite copiar arquivos desnecessários para a imagem final.
- Defina uma porta clara para o app escutar.
- Não embuta segredos no Dockerfile.
- Prefira imagens oficiais da Microsoft para runtime e SDK.
Configuração
3. Tire segredos do código e passe a configurar por ambiente
Produção não é lugar para connection string em appsettings.json
versionado, token em código-fonte ou URL fixa de serviço.
O ideal é deixar o app pronto para ler tudo de variáveis de ambiente ou de um serviço de secrets.
- Banco: ConnectionStrings__Default
- Cache: Redis__ConnectionString
- Storage: S3__Endpoint, S3__AccessKey, S3__SecretKey
- Mensageria: Nats__Url, Nats__Token
Exemplo em Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Configuration
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
var connectionString =
builder.Configuration.GetConnectionString("Default")
?? throw new InvalidOperationException("Connection string não configurada."); Confiabilidade
4. Exponha health checks desde o primeiro deploy
Se sua plataforma não consegue saber se o app está vivo ou pronto para receber tráfego, você está operando no escuro.
Exemplo simples com ASP.NET Core
using Microsoft.Extensions.Diagnostics.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy())
.AddNpgSql(
builder.Configuration.GetConnectionString("Default")!,
name: "postgres");
var app = builder.Build();
app.MapHealthChecks("/health/live");
app.MapHealthChecks("/health/ready");
app.MapGet("/", () => "OK");
app.Run(); Em ambientes orquestrados, separar liveness e readiness ajuda bastante: uma sonda indica se o processo está vivo; a outra diz se ele está pronto para receber tráfego.
Isso evita mandar requisições para um app que ainda está subindo, migrando banco, carregando configuração ou reconectando dependências.
- /health/live: processo subiu e não travou.
- /health/ready: app já consegue atender de verdade.
- Inclua dependências importantes, como banco e serviços críticos, com critério.
Observabilidade
5. Publique com logs, métricas e traces desde o início
Logs estruturados
Não dependa de prints improvisados. Use logs com contexto, níveis corretos e correlação por requisição.
Métricas básicas
Acompanhe latência, taxa de erro, consumo de CPU/memória, reinícios e tempo de resposta.
Tracing distribuído
Se o app conversa com banco, cache, fila e APIs externas, traces ajudam a enxergar onde a requisição degrada.
Dica prática
Se você estiver usando .NET Aspire, os service defaults ajudam a centralizar telemetria, service discovery e health checks com menos repetição entre serviços.
CI/CD
6. Automatize o build e o deploy com GitHub Actions
Exemplo de workflow
name: deploy-api
on:
push:
branches: [ "main" ]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0.x"
- name: Restore
run: dotnet restore
- name: Test
run: dotnet test --no-restore --configuration Release
- name: Build image
run: docker build -t myapp:\${{ github.sha }} .
# aqui entra push para seu registry e etapa de deploy O pipeline mínimo ideal deve fazer quatro coisas:
- Restaurar dependências
- Executar testes
- Gerar a imagem
- Publicar e disparar o deploy
Se quiser subir o nível, inclua também:
- scan de vulnerabilidade na imagem;
- tag semântica além do commit SHA;
- gates por ambiente;
- deploy gradual ou manual approval em produção.
Erros comuns
7. O que mais costuma quebrar em deploy .NET
App depende do ambiente local
Caminhos fixos, arquivos soltos, diretório temporário usado como persistência e credenciais locais costumam explodir na primeira subida.
Sem health checks reais
O processo sobe, mas o app ainda não está pronto. Sem readiness, a plataforma manda tráfego cedo demais.
Secrets no repositório
Connection string em JSON versionado, token em código ou chave em workflow é convite para incidente.
Zero observabilidade
Quando falha em produção, ninguém sabe se foi banco, fila, timeout, CPU, memória ou uma regressão no código.
Aplicando isso na FoundryShip
Como esse fluxo fica em uma cloud especializada em .NET
App Runtime
Sua API ou app Blazor roda em uma stack pensada para workloads .NET, com deploy previsível e operação mais simples.
Serviços acoplados
Banco, cache, storage, mensageria e secrets ficam no mesmo ecossistema, reduzindo fricção operacional.
Infra nacional
Menos latência para o público brasileiro e um caminho mais direto entre build, deploy e operação.
Checklist final
Checklist rápido antes de publicar em produção
- ✓ Aplicação compilando em modo Release sem dependência do ambiente local
- ✓ Imagem de container reproduzível e versionada
- ✓ Segredos fora do código e do repositório
- ✓ Health checks configurados
- ✓ Logs e métricas mínimos já disponíveis
- ✓ Pipeline automatizado com build, teste e publicação
- ✓ Plano de rollback simples e rápido
Quando esse checklist está em ordem, deploy deixa de ser um evento tenso e passa a ser só mais uma etapa confiável do seu fluxo de engenharia.
Entre para a lista de Founders
Cadastre seu e-mail para receber o link de abertura primeiro e ter prioridade na fila.
Sem cartão nesta etapa — você só decide no lançamento.
Você pode cancelar a qualquer momento. Nenhum pagamento é feito nesta etapa.