Developers may find building on Cloud Run Services challenging, but it can be overcome with proper understanding and usage. I encourage you to go through the documentation so that you know exactly what is required of you, and if you really need Cloud run.
I required Cloudrun services to deploy my .NET8 MVC API and connect it to a Firebase Web App hosted on GCP. However, I faced a challenge where I initially thought that I needed to separate the code. However, due to the Firestore integration, I realized that both the App and the API had to be on one cloud project.
If you can create a container image using any programming language of your preference, then you can use Cloud Run. Google provides support for various programming languages for this purpose, which include:
- Go
- Node.js
- Python
- Java
- Kotlin
- .NET
- Ruby
- PHP
If you don't have experience writing Controller APIs, I suggest using the link in Step 2. I utilized Visual Studio Code for my development.
Build $ dotnet publish -c Release
Sample Controller Code
using Material.Model;
using Material.Service;
using Microsoft.AspNetCore.Mvc;
using Response;
using Response.Model;
namespace ProjectName.API.Space.Controllers;
[ApiController]
[Route("api/[controller]")]
public class MaterialController(IMaterialServices materialServices) : ControllerBase
{
private readonly IMaterialServices _materialService = materialServices;
[HttpGet]
public async Task<IResponseDataModel<IEnumerable<MaterialModel>>> GetAllMaterials()
{
try
{
var result = await _materialService.GetAllMaterial();
return result.Success.Equals(true) ? new ResponseDataModel<IEnumerable<MaterialModel>>
{
Success = true,
Data = result.Data
} : new ResponseDataModel<IEnumerable<MaterialModel>> { Success = false };
}
catch (System.Exception)
{
throw;
}
}
}
Sample Service Code
using Google.Cloud.Firestore;
using Material.Model;
using Response;
using Response.Model;
namespace Material.Service
{
public interface IMaterialServices
{
//CRUD Operations
Task<IResponseDataModel<IEnumerable<MaterialModel>>> GetAllMaterial();
}
public class MaterialServices : IMaterialServices
{
private static readonly FirestoreDb _firestoreDb = FirestoreDb.Create("PROJECT_ID");
private static List<MaterialModel> _cffMaterial = [];
public async Task<IResponseDataModel<IEnumerable<MaterialModel>>> GetAllMaterial()
{
try
{
Query allMaterialQuery = _firestoreDb.Collection("material");
QuerySnapshot allMaterialQuerySnapshot = await allMaterialQuery.GetSnapshotAsync();
foreach (DocumentSnapshot documentSnapshot in allMaterialQuerySnapshot.Documents)
{
var dictionaryMaterial = documentSnapshot.ToDictionary();
_cffMaterial?.Add(new MaterialModel
{
Name = (string)dictionaryMaterial["name"],
PercentagePrice = (long)dictionaryMaterial["percentagePrice"],
Pros = (List<object>)dictionaryMaterial["pros"],
Cons = (List<object>)dictionaryMaterial["cons"],
});
}
var result = _cffMaterial;
return result != null
? new ResponseDataModel<IEnumerable<MaterialModel>> { Success = true, Message = "Got Material!!", Data = result }
: new ResponseDataModel<IEnumerable<MaterialModel>> { Success = true, Message = "No Material!!" };
}
finally
{
_cffMaterial = [];
}
}
}
}
Follow these steps to containerize a .NET application. Ensure that Docker is installed on your
machine. Feel free to reach out if you encounter any issues.
Next: build the docker image
$ docker build -t IMAGE_NAME -f Dockerfile .
Artifact Registry provides a single location for storing and managing your packages and Docker container images
Before you can push or pull images, configure Docker to use the Google Cloud CLI to authenticate requests to Artifact Registry.
To set up authentication to Docker repositories in the region of your choice, here we will useus-central1
, run the following command:
$ gcloud auth configure-docker us-central1-docker.pkg.dev
You now have a repository where you can store the image that you created
in Step 3.
Run the following command to tag a version, the tag at the end is optional and the default is latest.
$ docker tag us-central1-docker.pkg.dev/PROJECT/REPO_NAME/quickstart-image
Run the following command to Push the image to the Artifact Registry.
$ docker push us-central1-docker.pkg.dev/PROJECT/quickstart-docker-repo/quickstart-image
Step 5: Deploy to Cloud Run Service
$ gcloud run deploy SERVCE_NAME --image=us-central1-docker.pkg.dev/PROJECT_ID/REPO_NAME/IMAGE_NAME
And follow the prompts of selecting where the source is or Region if you have not
set defaults.
Wait for the build and deploy to complete. When finished, a message similar to this one is displayed:
Service [my-app] revision [my-app-00000-xxx] has been deployed and is serving 100 percent of traffic. Service URL: https://my-app-texampleq-uc.a.run.app
Tip: To make it easier for you, prepare a Shell Scrip file to help running the command. For Example
deploy.sh
echo "package for deployment to docker container"
dotnet publish -c Release
echo "Building image locally"
docker build -t IMAGE_NAME -f Dockerfile .
echo "Tagging image"
docker tag us-central1-docker.pkg.dev/PROJECT/REPO_NAME/quickstart-image
echo "Publishing image"
docker pushus-central1-docker.pkg.dev/PROJECT/quickstart-docker-repo/quickstart-image
echo "Deploy new services and new revisions to Cloud Run"
gcloud run deploy SERVICE_NAME
--image=africa-south1-docker.pkg.dev/cff-v2/cffapi-docker-repo/cffapi-image
NOTE: Replace PROJECT, REPO_NAME, SERVICE_NAME, IMAGE_NAME with your setting preferences.
I hope this revised version is clearer for you!
May God Bless you. Romans 10:9-10
SHALOM!