Create a Kubernetes cluster from the scratch (On CentOS 7 / RHEL 7) and Deploy an application on the cluster and Expose to Internet — Complete Example PART — 02 (Docker)

Content

  • Create the cluster (on VM) (Covered by previous story)
  • Build Dockerized application — Covered on this story
  • Deploy the application on the cluster — Covered on this story

Previous story

TODO: Will cover on future stories.

  1. Expose the application to internet through an Ingress
  2. Install and configure Helm
  3. Deploy above application using Helm chart

Docker app source : https://github.com/el173/docker-node-app

Kubernetes deployment example : https://github.com/el173/kubernetes-examples

1.0 Build Dockerized application

Here I’m going to build a nodejs hello world app which is get app configurations as environment variables(Will explain later why we do this) on RHEL 7 (Same VM(s) which was used in my previous story PART-1)

First thing first

1.1 Install Node.js

# yum install -y gcc-c++ make
# curl -sL https://rpm.nodesource.com/setup_10.x | sudo -E bash -
# yum install nodejs
# node -v
v10.15.0
# npm -v
6.4.1

1.2 Create the Node.js app

# mkdir nodeapp && touch package.json
{ 
“name”: “docker_web_app”,
“version”: “1.0.0”,
“description”: “Node.js on Docker”,
“author”: “Hashith Karunarathne<hashithkarunarathne@gmail.com>”,
“main”: “server.js”,
“scripts”: {
“start”: “node server.js”
},
“dependencies”: {
“express”: “^4.16.1”
}
}
  • After that, create a server.js file that specify the web app using the Express.js framework.
# touch server.js

Edit and add following code to server.js file

'use strict';  const express = require('express');  const PORT = 8080; 
const HOST = '0.0.0.0';
const DB_HOST = process.env.DB_HOST;

app = express();
app.get('/', (req, res) => {
res.send('Hello world\n DB HOST : '+DB_HOST+'\n');
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

1.3 Build a Docker image of the app

Note: Before move to the docker image creation, Create a Docker Hub account.

# touch Dockerfile
FROM node:8  
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]
node_modules 
npm-debug.log

This will prevent your local modules and debug logs from being copied onto your Docker image.

Run following command on same directory where the Dockerfile contains.

Note: Replace all the place where el173 with your docker hub user name.

# docker build -t el173/node-hello:v0.1 .

Your image will now be listed by Docker

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
el173/node-hello v0.1 683cf97e4468 14 seconds ago 895 MB
node 8 55b43107a63d 39 hours ago 893 MB

Then run the docker image

# docker run -d -p 12345:8080 -e DB_HOST=1.1.1.1 el173/node-hello:v0.1

Test the docker image

To verify container created successfully run the below command

# docker ps

Output should like below,

CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS                     NAMES
39a41885f19e el173/node-hello:v0.1 "npm start" 3 minutes ago Up 2 minutes 0.0.0.0:12345->8080/tcp priceless_pare

To see the out put of the application

# curl -i localhost:12345
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 19
ETag: W/"13-VpSJg61R7DJwwGMhbMUNqUoKJcQ"
Date: Thu, 10 Jan 2019 18:15:27 GMT
Connection: keep-alive

Hello world
1.1.1.1

Now all good docker image of our app has been build successfully.

1.4 Push docker image to docker repository (This make easy the app deployment on Kubernetes)

First all, we need to login to our docker account on our app building environment.

# docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.

Then push your docker image to your Docker Hub repository.

# docker push el173/node-hello:v0.1

You can find the above example source code form this link

https://github.com/el173/docker-node-app

Now all ready to deploy our app on Kubernetes cluster (Which was created on my PART-1)

2.0 Deploy the application on the cluster

Before moving to the deployment please read this Understanding Kubernetes Objects

First create a separate namespace for our deployment. (It will easy to manage our app)

apiVersion: v1
kind: Namespace
metadata:
name: node-app

Create namespace

# kubectl create -f https://raw.githubusercontent.com/el173/kubernetes-examples/master/simple-node-app/namespace.yaml

Why we use configmap — It is the most convenient way to store our application configurations in kubernetes cluster.

Read more : https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/

apiVersion: v1
kind: ConfigMap
metadata:
name: node-app-config
namespace: node-app
data:
DB_HOST: "1.1.1.1"

Create config map

# kubectl create -f https://raw.githubusercontent.com/el173/kubernetes-examples/master/simple-node-app/configmap.yaml

Now all good to deploy our application on the kubernetes cluster.

MUST: Read before do the deployment — https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: node-app-deployment
namespace: node-app
labels:
app: node-app
spec:
selector:
matchLabels:
app: node-app
tier: node-app-tier
replicas: 2
template:
metadata:
labels:
app: node-app
tier: node-app-tier
spec:
containers:
- name: node-app-container
image: el173/node-hello
ports:
- name: http
containerPort: 80
envFrom:
- configMapRef:
name: node-app-config

Make the deployment

# kubectl create -f https://raw.githubusercontent.com/el173/kubernetes-examples/master/simple-node-app/deployment.yaml

Okay, we have successfully deployed our app on the cluster. Now we need to create a service to access our app.

MUST: Read before create the service — https://kubernetes.io/docs/concepts/services-networking/service/

service.yaml

apiVersion: v1
kind: Service
metadata:
name: node-app-service
namespace: node-app
labels:
app: node-app
tier: node-app-tier
spec:
type: NodePort
ports:
- port: 8080
selector:
app: node-app
tier: node-app-tier
# kubectl create -f https://raw.githubusercontent.com/el173/kubernetes-examples/master/simple-node-app/service.yaml

Once you created service. Retrieve all of your resources under node-app namespace, It should like below.

# kubectl get all -n node-app
NAME READY STATUS RESTARTS AGE
pod/node-app-deployment-556b878859-v57f2 1/1 Running 0 40h
pod/node-app-deployment-556b878859-wqk2p 1/1 Running 0 40h

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/node-app-service NodePort 10.103.112.204 <none> 8080:30814/TCP 40h

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/node-app-deployment 2/2 2 2 40h

NAME DESIRED CURRENT READY AGE
replicaset.apps/node-app-deployment-556b878859 2 2 2 40h

And now all good, You can check whether service is running.

Get service ip (cluster ip only available within the cluster)

# kubectl get svc node-app-service -o yaml -n node-app | grep clusterIP
clusterIP: 10.103.112.204

Get service port

# kubectl get svc node-app-service -o yaml -n node-app | grep port
ports:
port: 8080

Then curl and see your application output:

# curl 10.103.112.204:8080
Hello world
1.1.1.1

On next story we will look on kubernetes Ingress.

References:

--

--

el173 — Focus on BigPicture; Syntax doesn’t matter

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store