Dockerize a starter Angular app, Deploy to Google Kubernetes add a CI CD pipeline with Cloud Build.

Trevor (Al Rashid)
8 min readMar 23, 2020

--

This article is for DevOps beginners but with prior knowledge about Building Docker images and Deployment on Kubernetes on Google Cloud. What may seem new is just simple: Creating a CD pipeline with Cloud Build, this enables flexible change of code from your git repo, then your image is updated and so your deployment in just few minutes. This saves a lot of time which would be spent repenting building & deploying steps, hence one can concentrate on improving his/her code in your editor.

Checkout this projects’ Github repo: Link here …

Let's break this in parts so we can fully understand each process:
1. Creating a simple Angular app
2. Creating a Docker image of the app
3. Pushing the image to Google Cloud Registery & Docker Hub
4. Create the app deployment & service in the Kubernetes cluster
5. Push code to Github repo & Cloud Source Repository
6. Create the CD pipeline with cloud build
7. Taste the pipeline, observe the changes on your already running app

  1. Creating a simple Angular app

When getting started with Angular development, you will first need to install NodeJS and NPM. For my case, while writing this blog, my NodeJS version is v12.0.0. I would recommend switching to this version incase your following this blog or you will need to make a few changes in the code ```Dockerfile``` to your node version.
check your node & npm version:

$ node --version
$ npm --version

You also need angular CLI, since you have npm you can add it:

$ npm install -g @angular/cli

Now that we have installed the Angular CLI, we can generate our Angular application. Navigate into your desired directory and run this: ‘angular-docker` is the name of my app, change it your desired one

$ ng new angular-docker

Navigate into the root directly of the app and run the app. You can now access the application via http://localhost:4200

$ ng serve

2. Creating a Docker image of the app

We start by creating a ‘Dockerfile’ in the root directory of the app. It contains 2 parts (stages). Both starting with the ‘FROM’ tag.
The first one is the stage that will just be used for building the Angular application. The final stage will only contain a webserver and does not require build tools like Node

FROM node:12.0.0-alpine AS builder
COPY . ./angular-docker
WORKDIR /angular-docker
RUN npm i
RUN $(npm bin)/ng build --prod
FROM nginx:1.15.8-alpine
COPY --from=builder /angular-docker/dist/angular-docker/ /usr/share/nginx/html

Now that we have all configuration in place, we can build the Docker image by executing the following command:

$ docker build --rm -t angular-docker:1.0 .

The ‘–rm’ flag is used to automatically remove the intermediate containers once the image has been built successfully. The ‘-t’ flag is used to provide a tag name of the Docker image. This tag name is 1.0 which helps me to identify the different versions of builds, also is used when we run the image

Confirm your image has been built by listing all the Local Docker images, then we run it with the other command.

$ docker image list$ docker run --rm -d -p 90:80/tcp angular-docker:1.0

Again, the ‘–rm’ flag is used to automatically clean up (remove) the container once it’s stopped. The ‘-d’ flag Is used to start the container in detached mode. Finally, we will connect port 90 of the host system to TCP traffic on port 80 within the image. Port 80 is the default port used by Nginx.

When you browse to http://localhost:90, you will now see the application which is running from Docker!

3. Pushing the image to Google Cloud Registery & Docker Hub

Luckily, I had written about this in my other blog entitled: “ Manage your Docker images ” By the end of the blog ensure you have your image in the Google Cloud Registry as will be deploying it in the next step.
For DockerHub it's also another place to keep your images in case you may need to share it to the public or for your future use.

Check out the image on my DockerHub: Link here …

4. Create the app Deployment & Service in the Kubernetes cluster

At this step, I assume you have a running Kubernetes cluster on GCP with atleast 2 nodes in your default node pool.

I always create my deployments with the yaml file on my computer then just run the the ‘create’ command

apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "angular-frontend"
namespace: "default"
labels:
app: "angular-frontend"
spec:
replicas: 1
selector:
matchLabels:
app: "angular-frontend"
template:
metadata:
labels:
app: "angular-frontend"
spec:
containers:
- name: "angular-docker-sha256-1"
image: "gcr.io/kubernets-271416/angular-docker@sha256:92dbf946aa671cf80b6b0888844d000a854183ae09b0a3a5da2776399d5b62a3"

Above is a sample of my frontend-angular.yaml file. I indicate the kind which is a Deployment, For Labels: app- points to the app-name which will be used by the service to map to it. Then lastly is the image which I simply copied from the GCR by picking the specific image I would like to deploy. So ran the command below to create a deployment in your cluster.
NB: since you are on the command like I assume your Cloud SDK is configured to your clusters’ project and you have credentials to your clusters

kubectl create -f frontend-angular.yaml

After the above command, visit the workloads page on GCP, you should be able to see it with OK status.

Let's create the deployment service …This directs the traffic to a pod.

apiVersion: "v1"
kind: "Service"
metadata:
name: "angular-frontend-service"
namespace: "default"
labels:
app: "angular-frontend"
spec:
ports:
- protocol: "TCP"
port: 90
targetPort: 80
selector:
app: "angular-frontend"
type: "LoadBalancer"
loadBalancerIP: ""

This similarly refers to exposing our app to the world through a load balancer.
Referring to the way we ran the app locally on Docker 90:80/tcp our protocol is tcp and specified the port to 90, & targetPort 80: this is the actual port on which your application is running inside the container. Create the service by with just create command:

kubectl create -f frontend-angular-service.yaml

After the above command, visit the services & ingress page on GCP, you should be able to see it with OK status, type Loadbalancer has an endpoint which is an IP address where you access your app on the browser.

Woow! great work now you have your app running in the Kubernetes cluster!
However, we would not need to repeat all these steps from building the image every time we make new changes to our app! Ofcoz I mean you would like to customise your app from this default design… so how do we go about this !?

It's now that we bring in the CI-CD pipeline magic to help us deal with updating the image and then our deployment in just a few minutes.
Ofcoz there are many tools like Jenkins that we do best the job for you but this time lets use Cloud Build.
C
loud Build is already integrated with other services on GCP so getting started with it is just easy. Cloud Build is a service that executes from Cloud Source Repositories & GitHub, executes a build to your specifications, and produce artifacts such as Docker, then executes your build as a series of build steps, where each build step is run in a Docker container.

Lets start with setting up our code source repos…

5. Push code to Github repo & Cloud Source Repository

First, create a git Repo and push your code. Refer here… for git beginners

So we need to create a mirror repo of our git repo, in cloud source repositories, this is the repo referred to by Cloud Build our CD tool.
- On the GCP navigation menu, scroll down and select Source Repositories, in the right corner select Add Repository, then select connect external Repository, next your asked of your project id and the external Hub hosting your code, either Github or Bitbucket. I used Github, so a list of all your repos are listed and then your select the Git Repo we created in the first step which contains our app code.
By doing this as you update git hub repo, the cloud source repo too is automatically updated… this initiates the pipeline… magic.

6. Create a CD pipeline with Cloud build

This has two different approaches: However, we will take the straight forward one. Navigate back to your workloads page, you will see a prompt ‘Set up an automated pipeline for this workload ’ as below:

Click on setup, aside form ‘Automate deployment’ shows up:

For source repo: We select Cloud Source Repositories, then the repo name: select the one we mirrored from Github in the previous step.
Build configurations leave as default.
For Automated deployment config, you will be required to provide a deployment-configuration.yaml file, it tracks changes of your deployment.

However has been already created for you! so copy the YAML file by clicking on ‘ VIEW GOOGLE-RECOMMENDED YAML’ copy the code, go to your git repo and create a file then paste that code. When you view your Cloud Source Repo, it has already been updated too. Click UPDATE. Booom! you have now a CD set for you that will be doing for you all the whole repetitive work.

7. Taste the pipeline, observe the changes on your already running app

Now you no longer need to worry about whatever is happening on GCP, your task is to get back to your editor and concentrate on modifying your app, making it better, then by simply pushing the code and committing to your GitHub repo.
For my case, I just modified the app’s heading and the build was automatically done with a successful message displayed. Upon refreshing my app: the changes were done!

From the screenshot above, you can see the Build summary occurs in 5 steps: Build, push, prepare to deploy, configs saving and then Applying the deployment.

Thanks for reading! Keep Learning, keep sharing

--

--

Trevor (Al Rashid)

Cloud Engineer | Educator | Entrepreneur | Champion Innovator at Google Cloud Innovators 🎖️