Setting up Continuous Deployment on Google Cloud.
Published: 2024-02-10 20:27:06

I am a very big fan of automation. Since college, I wanted to learn stuff like CI/CD and build a pipeline which test and deploy code for me. In college I tried stuff like Travis CI which is actually a very good free tool but still not awesome when I am trying to work with private repositories.

Now I picked this curious topic again and learned some basics of deployment. I may learn more about this in future and will come back here to write more (so please bear with me if I am incorrect somewhere, I am still learning)

## Prerequisites
- Set up an account on [Google Cloud](https://console.cloud.google.com/).
- Install [Docker](https://docs.docker.com/engine/install/).
- [Learn](https://www.youtube.com/) Git (and GitHub) basics.
- Linux (Know how to test or at least run you application via CLI)
- Node installed (if you want to follow this tutorial)
- Be cool 😃

## Step 1: Create a hello world application

[Skip if you already have an application]

I have chosen a simple react application which I created using the following commands
```
npx create-react-app hello-world
# if the above command does not work, try
npm init react-app hello-world
```

## Step 2: Containerize your code using Docker
**Note:** You can choose not to containerize it, but here we will be pushing a docker image to [Cloud Run](https://cloud.google.com/run?hl=en).
- Create a file named `Dockerfile` and fill the following commands
```
# Let's use a node image based on alpine
# Alpine is a lightweight Linux distribution, that's why
FROM node:alpine
# Copy all the code present here to the docker
COPY . /code_app
# Change working directory to code_app
WORKDIR /code_app
# Run the following commands
RUN npm install
RUN npm run build
RUN npm install -g serve
CMD serve -s build
```
Let's test out what we built.

- We can build our image using `docker build -t "hello-world" .` 
You need to run this command in powershell or terminal and make sure your working directory is same as one with `Dockerfile`
With this command you have successfully build an image of your application.

- You see the list of all the images using `docker image ls`

- Now let's run the hello-world application on our port 3000. Remember that react will have the port on 8080, so we have to mention to expose 8080 port of docker container to 3000 port of our computer using `docker run -p 3000:8080 hello-world`

## Step 3: Create a Google Cloud Build configuration file.
We can create configuration file in YAML and JSON. You can follow the instructions [here](https://cloud.google.com/build/docs/configuring-builds/create-basic-configuration) if you wish to learn more or configure it by yourself. Here will be using YAML.
I usually name my file `googlecloudbuild.yaml`, you can name it anything you want.
```
steps:
# Install dependencies
- name: 'node'
  entrypoint: 'npm'
  args: ['install']
# Test the code
- name: 'node'
  entrypoint: 'npm'
  args: ['test']
# Build the container image.
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/$_BINARY_NAME:$COMMIT_SHA', '.']
# Push the container image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'gcr.io/$PROJECT_ID/$_BINARY_NAME:$COMMIT_SHA']
# Deploy container image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: gcloud
  args:
  - 'run'
  - 'deploy'
  - '$_BINARY_NAME'
  - '--allow-unauthenticated'
  - '--image'
  - 'gcr.io/$PROJECT_ID/$_BINARY_NAME:$COMMIT_SHA'
  - '--region'
  - '$_REGION'
images:
- 'gcr.io/$PROJECT_ID/$_BINARY_NAME:$COMMIT_SHA'
```

What are doing here?
**Note**- `$_REGION` , `$_BINARY_NAME` will be added by us later in the pipeline, `$COMMIT_SHA` will be provided by default.

- Step 1 and 2 are quite clear Installing dependencies and running tests.
- Step 3 is same step we did earlier to build the image.
- In Step 4, we push the created image to Container Registry which is a Docker repository storage on Google Cloud Platform (GCP)
- In Step 5, we create a deploy on Google Cloud Run for the same image we just created and stored.

**Note:** We used `--allow-unauthenticated` flag because this is a website and we want everyone to be able to access this.

## Step 4: Creating a trigger on Google Cloud Build

Maybe we can do this via CLI as well (I don't know, you can explore yourself).

**Creating a connection**

1. Go to [Cloud Build](https://console.cloud.google.com/cloud-build/dashboard) on Google Cloud Console.
2. Choose region to be us-central1 [This one worked for me]
3. Go to repositories in the left dashboard.
4. Choose 2nd Gen
5. Click on `+ CREATE HOST CONNECTION` and connect with your Github (or Gitlab)
6. Now, click on `LINK REPOSITORIES` and link hello world repository with the connection.

**Using the connection to create a trigger**

- Go to Triggers on the left dashboard
- Click on `+ CREATE TRIGGER`
- Fill data
- In Source, select 2nd Gen and choose repository and regex for the branch to which it will be applied to.
- Fill the following
```
Configuration- Cloud Build configuration file (yaml or json) 
Location- Repository 
Cloud Build configuration file location- googlecloudbuild.yaml
```
- In Advanced > Substitution Variables, add these two variables [we used them YAML file]
```
_BINARY_NAME : "hello-world"
_REGION: "us-central1"
```
- Leave Service account.
- Click on Create

## Step 5: Watch the magic
1. Submit the changes to branch above see a rollout in [History](https://console.cloud.google.com/cloud-build/builds)/[Dashboard](https://console.cloud.google.com/cloud-build/dashboard)
2. Go to [Cloud Run](https://console.cloud.google.com/run) to see you running website
3. Click on your service to find the URL to access your service.