
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:
- get the todo application by running
lb4 example todo
(assuming you have@loopback/cli
Node.js module installed) - get my Angular application from https://github.com/dhmlau/loopback4-example-todo-angular
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/appWORKDIR /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=3000EXPOSE ${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 appangular-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
- 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.
- 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