Most of the React projects are built using Create React App, and there is a lot of documentation and articles that helps a lot when it comes to deploy to some platforms.
Recently I worked in a couple of projects that used Google Cloud Run, and it was interesting to know that this product is kind of recent, it was released about just 2 years ago. It’s super easy to use and you don’t even have to worry about the infrastructure management.
Cloud Run is a managed compute platform that enables you to run stateless containers that are invocable via web requests or Pub/Sub events. Cloud Run is serverless: it abstracts away all infrastructure management, so you can focus on what matters most — building great applications.- Cloud Run Documentation 2021
Also I’ve been working using Gitlab CI/CD for a while and despite some recent minor issues related to shared runners not taking jobs, I think it is a pretty simple and straightforward way to automate the delivery of an application.
Let’s start a React project
Since the easiest and fastest way to start is using Create React App. Let’s do so:
npx create-react-app my-awesome-react-app
We will not focus on React development, since in this story we are focusing on deploying using GCP and Gitlab CI/CD. So we are going to start with the pipeline configuration of the project. For this case we are going to consider just three stages:
- Install dependencies
- Test the application
- Deploy to GCP
So we must create
.gitlab-ci.yml file at the root of our project, and it should look like:
This is a sample deployment configuration file that creates a cache for the node_modules directory, so you just have to install them once for the whole pipeline. If you want to know more about Gitlab CI/CD configuration, please refer to its documentation. Or you can check this article that explains this with more detail.
Until here we have 2/3 stages covered. So, how am I supposed to deploy to GCP Cloud Run?
1st step: Creating a Cloud Run service
Assuming that we already have the project created at Google cloud. We must first create our Cloud Run Service.
Just look for Cloud Run in the products that offers our console and then create a new service:
Make sure to put a pretty name to your service.
For the meantime we choose the example container provided by the platform.
Then we must allow unauthenticated invocations. I mean, it’s a public site we will be deploying, so it must be like this.
We click on CREATE and we are ready to go! Let’s wait a couple of minutes for the container to deploy and we will have our example site.
You can check your application URL in the main page of the service:
Okay, so I have an app and I have a Cloud Run service. What’s the next step?
2nd step: Creating a service account
Let’s go to IAM & Admin > Service Accounts > Create Service Account. We input any name we want and in the second step, we must assign the following roles:
- Cloud Build Service Agent: So the account can be used to build the container using the cloud build service.
- Storage Object Creator: So the account can be used to store the containers in a bucket.
- Storage Object Viewer: So the account can be used to view the containers in a bucket. (Optional)
Now that we have our account, we must find a way to tell the CLI to use it, for that purpose we need a key. To manage keys we must click on the actions button in the new account row.
We can upload existing keys, but in this scenario we are creating a new one.
A dialog will prompt and we just keep the JSON radio selected and then click on Create. A JSON file will be downloaded, that’s our key and we must store it carefully because this may allow anyone to do stuff with your GCP project. We will use this JSON file for the next stage.
Now we are ready to go back to our React project.
3rd step: Enabling Cloud Run Admin
You must enable the Cloud Run Admin role so the container can be built, to do so we just need to go to Cloud Build > Settings and change the “Cloud Run Admin” role to ENABLED.
We already had a
.gitlab-ci.yml file that had missing the deployment scripts. Now we are ready to work with that and to achieve this, we are going to make the following changes.
We need to use the image google/cloud-sdk, so we can use the gcloud CLI tool. This is needed to create our image and submit it to our cloud service and then deploy it.
Also we need our previous downloaded JSON key file from Google, because it’s necessary to create an environment variable that contains its value.
Why an environment variable? Because you must NOT put this JSON file content in your code for security reasons. Remember that this key will grant access to do some stuff to your google cloud project.
Additional to our key, we must create other variables to set our project.
To set our environment variables we need to go to our Gitlab project page and go to Settings > CI/CD, just as the following image:
Then we expand the “Variables” section, here we can add ours. We need to create the following ones:
- GCP_PROJECT_ID: Your GCP project id
- GCP_SERVICE_KEY: The content of the JSON key we downloaded previously
- GCP_SERVICE_NAME: The name of your Cloud Run service
NOTE: You can change this variable names, you just need to change them wherever they are required.
Now, we must have a configuration for the build, that’s why we will create a file called
cloudbuild.yml that looks like this:
We pass the COMMIT_SHA and SERVICE_NAME through substitutions, this lets us to use variables that comes from the root environment. We use them to set our artifact name and tag, so we can identify which changes in the code are involved in the image.
You can find more information about in this documentation section.
We need also a
Dockerfile is needed to define our application image configuration:
Since React is only for front, it can’t serve itself. To solve this we can use
nginx to serve the application. One important thing is that the default port for the app to run properly in Cloud Run should be 8080, you can change it in the console. The basic configuration for nginx is the following one.
If you want to change the port, its necessary to change the
listen value to the port you want to use.
It’s important to note that
.gitlab-ci.yml for this scenario, should be in the root of our project. You can change their paths, but you must also change them wherever they are needed.
Once all this stuff is set, we are ready to run our pipeline. When we push all this changes to our repository, the pipeline will run automatically and after a while we will find our application deployed.