Continuous deployment to Cloud Run with Cloud Build

Ishaan Ohri
ADGVIT
Published in
6 min readJul 13, 2021

What exactly are Cloud Run and Cloud Build?

Cloud Run is a highly scalable Serverless product provided by Google Cloud. It provides us with the ability to run Docker images in a serverless container environment. Currently, it’s one of the easiest and most powerful cloud products. On the other hand, Cloud Build is a Serverless product for CI/CD. The use of these two products together makes the task much easier and efficient.

What we’ll be doing?

We’ll be deploying a simple Node.js server written in TypeScript using Cloud Run and would be integrating Cloud Build for CI/CD. We’ll first do this using a Dockerfile, then we’ll look into creating a cloudbuild.yaml, which offers much more flexibility and customizability.

Let’s get started

Here the focus is not the creation of the Node.js server, so I have created a basic one already, which I’ll be using throughout this blog. The reason to go ahead with TypeScript is just to demonstrate how you can incorporate the steps to build the project so that it gives you the idea as to how to add custom steps in CI/CD.

You can simply clone the project as we’ll be using the same hereafter.

You will notice that the repository has 2 Dockerfiles, one in the home directory and another in src. The one in the home directory runs the project using TypeScript and the one inside the src is for running the project using JavaScript after the build process. Step 1 below makes use of the Dockerfile in the home directory and Step 2 makes use of the other one.

Node.js + TypeScript

1. Creating a Cloud Run Service

In the Navigation Menu on the left, under the Compute section, choose the Cloud Run option. After that choose the Create Service option on top.

Under Service settings, for Service Name, give a unique name, in my case it is demo.

For Deployment platform, choose Cloud Run (fully managed) and for the Region, choose any which supports triggers. I have left it default — us-central (lowa).

Click Next.

Service settings

Under Configure the service’s first revision, choose Continuously deploy new revisions from source repository and click on Setup with cloud build.

Enable the Cloud Build API, if not enabled already. Choose the Repository Provider, in this case, GitHuband select the repository from the drop-down. Ensure that the GitHub Repo name has only lowercase alphanumeric characters, no uppercase characters or special characters. This causes an error otherwise.

For Branch, select the suitable branch through which you want to trigger the CI/CD, in this case, it is ^main$. Ensure the RegEx. For Build Type, choose Dockerfile and for Source Location, choose the location of the Dockerfile, in this case, /Dockerfile. Click Save.

Under Advanced settings, go to Variables section and add the required environment variables. For this add HOST with value 0.0.0.0

Click Next.

Configure the service’s first revision

Under Configure how this service is triggered, for Authentication, choose
Allow unauthenticated invocations. Click Create.

Configure how this service is triggered

This creates the Cloud Run service along with a trigger in Cloud Build. To view the created trigger, from the Navigation Menu on the left, under the Tools section choose Cloud Build > Triggers. You can view the build history under Cloud Build > History. You can open the build and view the progress as well.

On the Cloud Run page, click on the service name to view the Service Details. Once you see the green tick, it means it has been deployed on the mentioned URL.

Service details

Upon opening the URL, you would see the following screen:

Currently, the service is being run using TypeScript itself. I’ll cover the build to JavaScript and deploy portion in the next step.

You can view the generated Docker image under the Tools section in Container Registry > Images.

Now any Push to the specified branch will trigger a build using the auto-created trigger. This will change the deployed revision, which can be seen in the Service details of the Cloud Run service.

2. Using cloudbuild.yaml

Using the Dockerfile method explained in Step 1, it builds the docker image, pushes it to GCR (Google Cloud Repository) and then deploys it to Cloud Run.

But what if we wanted to add some custom steps to this, example: building the TypeScript project to JavaScript and then generating the docker image?

This is the exact use case of using the cloudbuild.yaml.

From the Navigation Menu on the left, under the Tools section choose Cloud Build > Triggers. Click on the trigger associated with the service.

Scroll down to the Configuration section. For Type choose Cloud Build configuration file (YAML or JSON) and for Location choose Repository. Leave the path as default — cloudbuild.yaml. Click on Save.

Now the trigger will perform the steps in the cloudbuild.yaml upon any Push to the repository. So create a file cloudbuild.yaml in the path specified in the Location field (home directory in this case).

So now I’ll just explain how the file is written.

Every on level 1 indentation under steps means a new step. Every step generally has 3 parameters — name, id and args. name is the name of the container image to execute your task (also called cloud builders). You can get more info about then from here or here. id is just an identifier, basically a name to the step. args is the actual args to the command that is executed.

In the file above Step 0 installs the packages, Step 1 runs the build script, Step 2, 3 and 4 run a bash command to copy package.json, package-lock.json and ./src/Dockerfile into the generated build folder respectively. Step 5 generates the docker image. $SOMETHING like $_GCR_HOSTNAME, $PROJECT_ID, $REPO_NAME and $COMMIT_SHA are variables. The ones starting with _ are specific to the trigger, which can be viewed or modified in the Advanced section of the trigger. The rest are the ones which cannot be modified. Step 6 pushes this docker image to GCR and Step 7 deploys it to Cloud Run. Last 3 steps are the same as performed by default when we used the Dockerfile method. In substitutions, the things are self explanatory.

Commit this new file to the repository. Now go to the History section in Cloud Build and open the last executed build. Here you can see every step that is being executed and its output as well.

By this way, we can make continuous deployment to Cloud Run using Cloud Build.

Below is the repository which I used through this article:

--

--

Ishaan Ohri
ADGVIT
Writer for

Executive Head @ ADG VIT | Node JS Developer | Android Developer