Deploy Angular and LoopBack Applications to IBM Cloud Kubernetes Cluster

Diana Lau
5 min readSep 30, 2020
Photo by Noel Broda on Unsplash

Previously in the blog post https://medium.com/@MobileDiana/building-a-frontend-application-with-loopback4-and-angular-e15c6fb48971, I have some REST APIs coming from LoopBack 4 application (the todo application) and created an Angular application to display the todo list. In this blog, I’m going to share what I’ve done and learned to deploy both applications to IBM Cloud Kubernetes cluster.

To follow along, you can:

What if I am not familiar with LoopBack or IBM Cloud Kubernetes Service?

If you’re not familiar with LoopBack, you can get started by following this tutorial: https://loopback.io/doc/en/lb4/todo-tutorial.html. For IBM Cloud Kubernetes service, I’d recommend to follow this tutorial first: https://cloud.ibm.com/docs/containers?topic=containers-cs_cluster_tutorial.

Create Dockerfile for Angular Application

The very first step is to create a Dockerfile for the Angular application at the root of the project folder. I found a good reference in https://mherman.org/blog/dockerizing-an-angular-app/.

Here is what my Dockerfile look like:

# Using Dockerfile from https://mherman.org/blog/dockerizing-an-angular-app/ 
# base image
FROM node:10-slim
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY package.json /app/package.json
RUN npm install
RUN npm install -g @angular/cli
# add app
COPY . /app
# start app
CMD ng serve --host 0.0.0.0

You will also need a .dockerignore to specify files/folders that are not needed to build the docker image. Here is my .dockerignore file:

node_modules
.git
.gitignore

Create Dockerfile for LoopBack Application

When you’re scaffolding a LoopBack 4 application, if you pick all the defaults, a Dockerfile should be created for you automatically.

If you didn’t select the docker option during application creation, here is the Dockerfile:

# Check out https://hub.docker.com/_/node to select a new base image
FROM node:10-slim
# Set to a non-root built-in user `node`
USER node
# Create app directory (with user `node`)
RUN mkdir -p /home/node/app
WORKDIR /home/node/app# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY --chown=node package*.json ./
RUN npm install# Bundle app source code
COPY --chown=node . .
RUN npm run build# Bind to all network interfaces so that it can be mapped to the host OS
ENV HOST=0.0.0.0 PORT=3000
EXPOSE ${PORT}
CMD [ "node", "." ]

And .dockerignore file:

node_modules
npm-debug.log
/dist
# Cache used by TypeScript's incremental build
*.tsbuildinfo

Build the Docker images and push it to IBM Cloud Container Registry

Make sure you’ve logged into IBM Cloud. If not, use theibmcloud login command. Create a namespace called todo .

ibmcloud cr namespace-add todo

I’m going to build 2 docker images:

  • loopback-todo : the todo LoopBack app
  • angular-todo: the Angular app that displays the todo list

Since I’ll be accessing the Todo LoopBack application endpoints from the Angular app, so I’m going to build/deploy everything for LoopBack app first. The steps for Angular app are similar.

$ ibmcloud cr build -t <region>.icr.io/todo/loopback-todo:1 .

Create Deployments

After the docker images are pushed successfully, we will create the deployments. Again with the similar naming convention, i.e. loopback-todo-deployment and angular-todo-deployment for the LoopBack and Angular app respectively.

$ kubectl create deployment loopback-todo-deployment --image=<region>.icr.io/todo/loopback-todo:1
deployment.apps/loopback-todo-deployment created

Exposing the deployment as a NodePort service

Next, create the service objects. The loopback-todo-service uses port 3000 .

$ kubectl expose deployment.apps/loopback-todo-deployment --type=NodePort --port=3000 --name=loopback-todo-service --target-port=3000

Accessing the LoopBack REST APIs and Angular Application

  1. Get the public IP address for the worker node in the cluster.
$ ibmcloud ks worker ls --cluster <cluster_name_or_ID>

You’ll get something like below. The Public IP is the one that you’ll be using to access the LoopBack app.

ID                                                       Public IP       Private IP       Flavor   State    Status   Zone    Versiontest-xxxx   169.xx.xxx.xx   10.xxx.xxx.xxx   free     normal   Ready    dal09   1.18.9_1528*

2. You can get information about the service to see which NodePort was assigned by running:

kubectl describe service loopback-todo-service

Take a look at the sample output below, NodePort is the port number for your application

$ kubectl describe service loopback-todo-service
Name: loopback-todo-service
Namespace: default
Labels: app=loopback-todo-deployment
Annotations: <none>
Selector: app=loopback-todo-deployment
Type: NodePort
IP: 172.xx.xxx.xxx
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31433/TCP
Endpoints: 172.xx.xx.xxx:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>

Modify the Endpoints in Angular App

In the angular app src/app/api/base-service.ts , we specify the root URL for the REST APIs is http://localhost:3000 . Now change it to the http://<PublicIP>:<NodePort> that we got in the previous section.

Build the Docker image and deploy to Kubernetes cluster

Following similar steps when deploying the LoopBack application.

  1. Build the docker image and push it to IBM Cloud Container Registry
$ ibmcloud cr build -t <region>.icr.io/todo/angular-todo:1 .

2. Create deployment object

$ kubectl create deployment angular-todo-deployment --image=<region>.icr.io/todo/angular-todo:1

3. Create the service object with port 4200

kubectl expose deployment.apps/angular-todo-deployment --type=NodePort --port=4200 --name=angular-todo-service --target-port=4200

4. Get the NodePort for the Angular app

kubectl describe service angular-todo-service

You’re all set! You should be able to see the same thing as you did when running everything locally.

Troubleshooting

Being a newbie to Kubernetes, I ran into a few issues, so I’m trying to capture the tips here, hopefully it would be of any help. You might find this kubectl cheatsheet comes in handy.

What if I need to push the docker image again?

If you created the deployment and service objects and then realize you need to make some changes in the application, remember to delete the deployment and service objects first.

$ kubectl delete deployment.apps/angular-todo-deployment
$ kubectl delete service angular-todo-service

Forget the deployment/service name? Use

kubectl describe deployment
kubectl describe service

Want to find out what get created/deployed visually?

You can take a look at the Kubernetes dashboard. From IBM Cloud dashboard, select Clusters > your-cluster-name. After you get to your cluster instance page, there is a Kubernetes dashboard button at the top right corner. Click that button and it will bring you to this:

What if I want to log into the container?

You can do the following:

$ kubectl get pod <--- get the pod name that you want to log in
$ kubectl exec -it angular-todo-deployment-xxxxx bash

Why ping and curl not working inside the container?

The Dockerfile we created at the beginning of this article uses the alpine docker image, so it doesn’t have ping and curl. You can install once you’ve logged into the container:

$ apt-get update
$ apt-get install iputils-ping <-- this one is for ping
$ apt-get install curl <-- this one is for curl

--

--