Deploy an API REST .Net 5 to Google Cloud Run using Github and Google Cloud Build
Tags: csharp, github, cloud, devops
Published: 2022-08-24 01:03:00

Create a new `ASP.NET Core Web API` project.

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

Give a name to the project and put it Github repo root folder.

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

Select .Net version.

> The version you choose here will reflect in dockerfile, so be free to change .net version but remember to adapt your dockerfile.

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

Select `webapi` option to run.

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

Run the project, make a GET resquet at `/weatherforecast` endpoint just to test if everthing its fine.

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

## Program.cs

Change your `Program.cs` to be like this code:

``` 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); });
            }
        }
    }
}
```

In this code, its importante to set up `0.0.0.0` IP when its running in a container, because when we use Google Cloud Run, we are running or code inside a container. In my case, I put it for every environment except the Delopment environment. 

## Dockerfile 

Create the `Dockerfile` file in the root folder of your repo. Check if all your project files are in the root, if not, move to the root folder.

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

Edit your Dockerfile with the following code:

``` 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"]
```

> Remember to change de DLL file name in the last line, this name must be exactilly the name of your project main .dll file.
> If your project you another folder structure, maybe you'll need make changes in your dockerfile.

Save all files and commit.

## GCP Cloud Run 

If you like, create a new project.

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

Search for `Cloud Run`, open Cloud Run product. Create a new service.

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

If you created a new project or is your first time using Cloud Build, maybe its necessary to Enable Cloud Build API, like me.

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

Select `Continuously deploy new revisions from a source repository` and click `Setup With Cluod Build`

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

> Important: I connected my Github account previously, therefore, I couldn't take prints in this step, but if its your first time, you need to connect your Github and GCP accounts.

Select your Github repository to be published.

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

Proceed to the second step and check Dockerfile option. In `Branch` field, keep the standard value `^main$`, this way every commit at branch main will trigger a new build at Cloud Build to be published in Cloud Run. Keep in mind that its possible to change to another branch.

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

Fill the `Service name`, I just kept default value. Choose a region, again I kept default.

At *Autoscaling* option I choose zero as minimum instances, because this reduces costs, but if you wish reduce latence and improve response time, keep in mind that probabily you will need at least one instance.

As well as minimum instances, to limit the cost I choose just 1 instance at maximum. If you wish improve availabillity and reliabillity, consider increase this number according with your traffic volume

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

Lastly, select Ingress and Authentication settings, for this tutorial I choose `Allow all traffic` and `Allow unauthenticated invocations`. But, for production applications, consider restrict your traffic and unauthenticated request.

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

Optional: Open `Container, Connections, Security` menu and ajust your container capacity.

For this deploy its not necessary to be concerned about this, and you can change this latter.

Save and create your service. Wait.

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

With everything done, you must get a result like bellow image:

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

The highlighted URL is provided by GCP and is the public URL to access your service. Try to access your `/weatherforecast` endpoint.

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)

## Conclusion

With this configuration, every new commit in your branch main in Github repository will trigger a new build at Google Cloud Build and if the build success, a new version of your application will be deployed in Google Cloud Run.

The Cloud Run has a resource called Reviews that allow us to rollback a version if the new one breaks our API.

In addition to allowing us to manage the traffic between version, witch allow us to deploy using canary method. Unfortunately, until now, I couldn't configure that canary to be automated with deploy, If you know how to automate traffic management during the deploy, please put in the comments.

Thank you for reading and I hold this was useful.