Como publicar uma API REST .Net 5 no Google Cloud Run usando Github e Google Cloud Build
Tags: csharp, github, cloud, devops
Published: 2022-08-24 00:28:00

Crie um novo projeto `ASP.NET Core Web API`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zuu8dh9giq05u1q041mj.png)

Nomeie o projeto e coloque-o dentro da pasta raiz do repositório do Github.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tfb3fg7fbdsv2qrcnohu.png)

Selecione a versão do .net.

> Aqui vale uma observação, a versão que você usar do .net vai influenciar como o arquivo dockerfile deverá ser configurado, se quiser escolher outra versão, fique à vontade, mas será necessário adaptar o dockerfile.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dwdounvqejkmmryo3k7d.png)

Selecione a opção `webapi` para execução.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/55md1pq0pv7vts9li4io.png)

Execute o projeto, faça um GET no `/weatherforecast` apenas para validar que está tudo funcionando.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4nmynhc0toc4ht8hqg2.png)

Vamos às adaptações necessárias no Program.cs

## Program.cs

Faça as alterações necessárias no seu `Program.cs` para ficar como o do código abaixo:

``` csharp
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace webapi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development";

            if (environment == "Development")
            {
                return Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
            }
            else
            {
                var url = new[]
                {
                    string.Concat("http://0.0.0.0:", port)
                };
                return Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>().UseUrls(url); });
            }
        }
    }
}
```

No código é importante notar o bloco do *else*, nele estamos dizendo que quando o ambiente não for "Development" a aplicação deverá subir usando o IP `0.0.0.0`, isso é necessário para que a aplicação fique visível fora do container quando publicarmos no Cloud Run.

## Dockerfile 

Crie o `Dockerfile` na raiz do repositório. Verifique se o seu projeto também está na raiz do repositório, se não tiver, mude para a raiz.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gflsvslmfj0fbvyo646x.png)


Preencha seu dockerfile com o código abaixo:

``` dockerfile
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
WORKDIR /app

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build-env /app/out .

ENV ASPNETCORE_ENVIRONMENT Production

ENTRYPOINT ["dotnet", "webapi.dll"]
```

> Importante alterar a última linha, o nome do arquivo .dll deve ser exatamente igual à DLL principal do seu projeto.
> Se seu projeto tiver uma estrutura de pastas diferente do meu, talvez precise alterar outros pontos do dockerfile.

Salve tudo e faça commit.

## Cloud Run no GCP

Se desejar, crie um projeto novo.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/331gd0othtdnux0uxi00.png)

Pesquise por cloud run na barra de pesquisa no meio da barra do  topo. Abra o produto Cloud Run. Crie um novo serviço.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qhaesbwsxwui2m9i0dd9.png)

Se você criou um projeto novo ou é a primeira vez que está usando o Cloud Build, talvez precise ativar o Cloud Build API.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t9yvto97mgahuchd9wil.png)
 

Selecione `Continuously deploy new revisions from a source repository` e clique em `Setup With Cluod Build`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eq9w0h3g5ip4cr89gshe.png)

> Importante: eu já tinha minha conta do Github conectada ao GCP, portanto, não consegui tirar prints dessa etapa, mas se for a primeira vez sua, você terá que vincular a sua conta do Github com o GCP.

Selecione o projeto que você quer publicar.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5opc9j2r9zkjrbzz9pjz.png)

Avance para segunda etapa e marque a opção Dockerfile. No campo `Branch` deixe o valor padrão `^main$` para que o Cloud Build seja acionado apenas quando houver commit na branch main do seu repositório, se quiser outra branch, fique à vontade.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmpmj6tcq1dzdb1vy5ie.png)

Preencha o `Service name`, eu deixei o valor padrão. Escolha uma região, para exemplo deixei a padrão.

Na opção de *Autoscaling* deixei a quantidade mínima de instâncias como zero, isso aumenta o tempo de resposta a um request, mas reduz custos, que no meu caso é mais importante. Se você quiser reduzir o tempo de resposta da sua aplicação deixe pelo menos 1 no mínimo e faça ajustes de acordo com a sua volumetria.

Assim como o mínimo, deixei o máximo em 1 instância, porque novamente o mais importante para mim não é performance e sim custo. Se quiser melhorar a performance avalie aumentar o limite máximo de instâncias, mas lembre-se que isso gerará custos.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5a4urrjmxq2n2qb7vfu3.png)

Por último, é preciso selecionar as configurações de Ingress e Authentication, para fins educativos deixei aberto para `Allow all traffic` e `Allow unauthenticated invocations`. Para aplicações em produção considere buscar mais informações para restringir o tráfego e as requisições sem autenticação.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vnoegaz1e1taq0nrcg6p.png)

Opcional: Abra o menu `Container, Connections, Security` e faça ajustes no seu container em relação à memória, timeout, requests máximos por container.

Para o deploy automático essas configurações são irrelevantes e você poderá alterá-las no futuro.

Crie seu serviço e aguarde.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93brft7x7augjgo41tvf.png)

Quando estiver concluído se tudo deu certo ficará como o da imagem abaixo. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kewrntok2zv84g4986kq.png)

O quadro em destaque na imagem acima é a URL pública gerada pelo GCP, com ela é possível acessar nossa API no endpoint `/weatherforecast`.

URL: [https://democsharpgcpcloudrun-lwy2plkqfa-uc.a.run.app/weatherforecast](https://democsharpgcpcloudrun-lwy2plkqfa-uc.a.run.app/weatherforecast)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vb90gf50o19il2jztm69.png)

## Conclusão

A partir de agora todo novo commit na main do seu repositório Github será publicado no Cloud Run

O Cloud Run tem um recurso chamado Revisões, com ele é possível fazer rollback caso uma nova versão quebre algum aspecto da sua API.

Além de permitir que você gerencie o tráfego entre duas ou mais versões, podendo fazer deploy canário. Infelizmente, até o momento não consegui configurar um deploy canário automático, se você souber como faz, coloca nos comentário, por favor.

Obrigado por ter ficado até o fim.