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
- Install Docker (Covered by previous story)
- 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
TODO: Will cover on future stories.
- Expose the application to internet through an Ingress
- Install and configure Helm
- 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
- Add Node.js Yum Repository
# yum install -y gcc-c++ make
# curl -sL https://rpm.nodesource.com/setup_10.x | sudo -E bash -
- Install Node.js
# yum install nodejs
- After installing node.js verify and check the installed version
# node -v
v10.15.0# npm -v
6.4.1
1.2 Create the Node.js app
- Create a new directory where all the files would live. And create a
package.json
file that describes app and its dependencies.
# mkdir nodeapp && touch package.json
- And edit the file
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”
}
}
- Then run
npm install
. If you are usingnpm
version 5 or later, this will generate apackage-lock.json
file which will be copied into the Docker image. - 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.
- Create a empty file called
Dockerfile
# touch Dockerfile
- Edit and add below lines to
Dockerfile
FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]
- Create a
.dockerignore
file in the same directory and add following contents to it.
node_modules
npm-debug.log
This will prevent your local modules and debug logs from being copied onto your Docker image.
- Build myApp 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)
- namespace.yaml file
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/
- configmap.yaml file
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/
- deployment.yaml file
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: