DEV Community

Cover image for Do localhost à produção: deployando Worker Services .NET como Windows Service, container Linux e Docker
Paulo Walraven
Paulo Walraven

Posted on

Do localhost à produção: deployando Worker Services .NET como Windows Service, container Linux e Docker

Seu Worker Service roda lindamente com F5. Mas "roda na minha máquina" não processa pedido nenhum às 3h da manhã. Em produção, um worker é uma aplicação de longa duração que precisa iniciar sozinha, sobreviver a reinícios e se recuperar de falhas — sem ninguém apertando botão.

Neste post você vai ver os três caminhos para colocar um Worker Service .NET em produção — Windows Service, container Docker e Linux — e, mais importante, os requisitos de produção que realmente importam por trás de cada comando.

Por que worker não é API

Antes do "como", vale lembrar o que torna um worker diferente de uma aplicação web. Diferentemente de uma API, um Worker Service não responde a requisições HTTP — ele executa continuamente em background.

Isso muda os requisitos de hosting. O worker precisa:

  • Iniciar automaticamente, sem intervenção manual.
  • Se recuperar de falhas sozinho.
  • Rodar sem supervisão o tempo todo.

É por isso que como você hospeda o worker importa tanto. Vamos aos três modelos.

Opção 1: rodando como Windows Service

O .NET torna trivial rodar um worker como Windows Service. Primeiro, adicione uma linha ao builder no program.cs:

builder.Services.AddWindowsService();
Enter fullscreen mode Exit fullscreen mode

Vai aparecer um erro na hora — falta uma dependência. Instale o pacote NuGet:

dotnet add package Microsoft.Extensions.Hosting.WindowsServices
Enter fullscreen mode Exit fullscreen mode

O que isso faz é dizer ao host que ele deve se integrar com a infraestrutura de serviços do Windows.

Depois, publique o executável (via CLI ou pela GUI do Visual Studio, em configuração Release):

dotnet publish -c Release
Enter fullscreen mode Exit fullscreen mode

Por fim, registre o serviço no Windows com o utilitário SC.exe, num prompt de comando como administrador, apontando o binPath para o executável publicado:

SC create MyJobProcessor binPath= "C:\caminho\para\MyJobProcessor.exe"
Enter fullscreen mode Exit fullscreen mode

Se aparecer SC create service success, está feito. Abra o Services do Windows, procure por MyJobProcessor e você pode iniciar, parar, configurar para subir automaticamente no boot ou desabilitar — tudo que se espera de um Windows Service típico.

Opção 2: rodando dentro de um container (a abordagem moderna)

Em muitos sistemas hoje — especialmente em ambientes cloud — os workers rodam dentro de containers. É a abordagem que costumo recomendar sempre que possível.

Você pode escrever o Dockerfile à mão, mas o Visual Studio tem um atalho ótimo: clique com o botão direito no projeto → AddDocker Support. Ele gera o Dockerfile para você (escolha Linux como OS do container, que é o mais comum sob o capô).

Com o Dockerfile no lugar, construa a imagem pela CLI:

docker build -t myjobprocessor .
Enter fullscreen mode Exit fullscreen mode

💡 Dois tropeços comuns aqui: a tag da imagem deve ser minúscula (myjobprocessor, não MyJobProcessor) e cuidado com espaços no caminho. Erros nesses dois pontos são fáceis de cometer.

E rode o container:

docker run myjobprocessor
Enter fullscreen mode Exit fullscreen mode

Você verá os logs do worker chegando no terminal. Se parar o container, a aplicação desliga junto — exatamente o comportamento esperado. A partir daí, você pode publicar a imagem para um registry (Docker Hub, um repositório privado, etc.) e deployá-la onde precisar.

Por que essa é a abordagem moderna? Containers são muito escaláveis e cross-platform: a mesma imagem roda em Linux, em Windows nativo, ou onde quer que você precise empurrá-la. Essa flexibilidade é uma das principais vantagens dos Worker Services.

O que realmente importa: os requisitos de produção

Os comandos são a parte fácil. O que separa "deployado" de "confiável" são três requisitos que você leva de qualquer modelo de hosting.

Restart e resiliência

Independentemente de como o worker foi hospedado, ele precisa reiniciar com segurança. Isso significa:

  • não perder o rastro do trabalho que estava fazendo,
  • não deixar o sistema em estado inconsistente.

É justamente por isso que, num sistema real, você persiste os jobs e rastreia o estado deles — para que um restart no meio do caminho não jogue trabalho fora.

Configuração por ambiente

Em produção, workers tipicamente rodam em múltiplos ambientes: desenvolvimento, staging e produção. E cada um tem seus próprios valores — connection strings, polling intervals, feature flags.

A boa notícia: como o Worker Service usa o mesmo .NET host do ASP.NET, a configuração funciona exatamente igual. Você usa appsettings.json, user secrets ou variáveis de ambiente, sem nenhuma cerimônia extra.

Escalabilidade

Por enquanto, focamos em rodar uma única instância. Mas o aprendizado fundamental é que um worker é um processo independente — pode ser deployado e gerenciado separadamente da sua API. Isso abre caminho, mais à frente, para rodar múltiplos workers e distribuir o trabalho entre eles.

Conclusão

Levar um Worker Service para produção é menos sobre o comando de deploy e mais sobre a mentalidade: uma vez no ar, o worker vira parte da infraestrutura do seu sistema — espera-se que rode continuamente, se recupere de falhas e se comporte de forma previsível. Windows Service, Docker ou Linux são só o "onde"; restart seguro, configuração por ambiente e independência da API são o "porquê".

É isso que separa processamento em background de um script solto. Qual modelo de hosting faz sentido para o seu cenário — Windows Service ou container? Se puder containerizar, eu sempre aconselharia. Teste os dois caminhos e veja qual encaixa na sua infra.

Top comments (0)