Kubernetes Intro – Part 3 – Create, Dockerize and Push Into the Cluster

So here’s the story so far: In parts 1 and 2 of my Kubernetes intro story, we have set up a Minikube Kubernetes Cluster. We then deployed a container with an app inside, which was downloaded directly from the Kubernetes image hub, into our cluster. Our cluster is small, it only contains one worker node and the container we put into a pod was the only service running in our cluster. If you could follow this description you are now ready for part 3 of the story. Based on what we have done so far we now create our own app, create a Docker image in which the app can run and then deploy it into our Kubernetes cluster. In the end we will have two services running in the cluster: The Echoserver app from part 2 and the app we are going to put together in this episode.

A Bit of Preparation

In case your Kubernetes web dashboard is no longer open, open it again with ‘minikube dashboard’ from the command line. Before we go on and create our own app we want to deploy let’s first have a look at all the Docker containers running in our Minikube. To do this, we have to instruct the Docker runtime not to look into the standard Docker environment but into the extra Docker environment created by Minikube. We also need this step for later when we create a container with the Docker commands that runs in the Kubernetes cluster rather than in the standard Docker environment:

# Configure the Docker command to look inside the Minikube cluster
eval $(minikube docker-env)

# Now show all Docker containers running in the cluster
docker ps

‘docker ps’ will show quite a number of containers at this point. If you look closely you will see the ‘…hello-minikube…‘ pod/container that still runs in the cluster from the previous example.

Let’s Create An App

O.k. now, let’s get to the app we want to write and deploy in our cluster. Our app will run on top of a node.js web server and just create a web page with ‘hello world’ on it whenever that page is requested from a web browser. Only a few lines of code are necessary for this and we’ll create a new directory to hold all things we create in this little project. To be able to experiment a bit with the code outside the cluster first, we need to install the nodejs interpreter.

# Create a directory for our mini-project 'Hello world'
mkdir hellonode
cd hellonode

# Install the node.js interpreter
sudo apt install nodejs

# And now create/open a file in which we paste the code of our app.
nano server.js

And the code we are going to copy/paste into the server.js file looks like this:

var http = require('http');

var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.end('Hello World!');

var www = http.createServer(handleRequest);

Yes, it is a simple app. When the node.js web server receives a http request it calls this code. It will output an info to the log file, create a http 200 OK header and write ‘Hello World’ into the body of the response. At the end of the code, the actual server is crated and bound to TCP port 8080.

After closing the file, let’s run the code on the shell outside the Kubernetes cluster just to see that it works:

# Now run our code outside the cluster for a quick check.
# Use http://localhost:8080 in the browser to get the "Hello World"
node server.js

Let’s Create a Docker Image for Our App

If ‘Hello World’ has shown up on the web page we know our app works so we can now deploy it in the Minikube Kubernetes Cluster. CTRL-C stops our app. Before we can deploy the app, we have to ‘containerize’ it, i.e. we have to create a Docker image with the node.js server and our app. This is done by creating a Docker command file and paste the following commands into it. The file has to be called ‘Dockerfile’:

# Now let's containerize this (Node + the server.js script that creates the web page)
# Create a Docker command file with the following instructions and name it 'Dockerfile':

FROM node:6.9.2
COPY server.js .
CMD node server.js

The FROM line tells docker to grab the ‘node’ server image from Docker Hub. Once it has done this, the COPY command copies our app (server.js) into the image and the CMD line instructs Docker/Kubernetes to execute ‘node server.js’ whenever the container is started. The EXPOSE line declares which port the container has to expose to the outside world to make our server/app combination reachable. Close the file and create the container. Be careful NOT to miss the ‘.’ at the end of the command.

docker build -t hello-node:v1 .

Now Push The Image Into Kubernetes

Now that the image is built we can instruct Kubernetes to use our image to create a deployment and expose it to the world. The commands are identical to the commands in part 2 for the hello-minikube example.

Tip: If your screen is large enough, have both the shell window and the Kubernetes web page open side by side and navigate to the ‘deployment’ page before you enter the commands. This way you will see our new ‘node’ deployment appear a few seconds after the commands have been executed.

kubectl create deployment hello-world --image=hello-node:v1
kubectl expose deployment hello-world --type=NodePort --port=8080

Once our app is deployed and running, you could look up the TCP port at which it is available to the outside world in the Kubernetes dashboard or you can use the following command in the shell:

# Now have a look at the webpage
minikube service hello-world

Before going on let’s take a bit of time and explore the Kubernetes dashboard with two services running. I’ll let you do that on your own!

Update The App and Replace The Old Version in the Cluster

Now let’s go on and do what everybody does all the time: Do a software update and deploy it. Our update will be small, just change the text ‘Hello World’ into something else. Once done, use the Docker build command to create a new Docker image with v2 of our app:

docker build -t hello-node:v2 .

Notice that instead ov v1 the command contains v2 as an image identifier. And now deploy it into the Cluster. If you can, have the Kubernetes dashboard open when you issue the command so you can see things changing.

kubectl set image deployment/hello-world hello-node=hello-node:v2

When you reload the hello world page in the web browser, you should now see the new text. Has a software update ever been so painless?

And finally, all things have to come to an end. When you are at this point you can remove the service and the deployment of your app from the cluster as follows:

# And finally, remove the service and the deployment again

kubectl delete service hello-world
kubectl delete deployment hello-world

To summarize

I was really amazed at this point how little it takes to write a small app, create a Docker container for it and deploy it in a Kubernetes cluster. If you have made it up to this point I hope you feel the same way. If the blog comments below are still open, I would appreciate if you left a quick comment about your impressions.