How to Deploy a Multi-Container Application to Kubernetes

4335 VIEWS

· ·

This guide will teach you how to deploy a multi-container application to Kubernetes. A multi-container application consists of multiple containers running at the same time. A Docker container is an executable package of applications that is lightweight. It contains all the system tools, libraries, source code, and files required to run an application. Containers run in isolated environments and are easily shareable between teams.

In this guide, we will create a multi-container application with a back-end server and a front-end web application. We will create a front end using React.js. It is one of the most popular frameworks for creating a single-page web application. 

We will create a back-end using Express.js. Express.js is a Node.js framework for building APIs and back-end servers. 

Note: These two simple applications are for demonstration purposes. If you have another React.js and Node.js application, you can use it as you follow this guide.

Requirements for This Tutorial

This tutorial assumes that the reader understands Docker and how to build Docker Containers. It also assumes you know how to build a simple React.js and Node.js application. Before you continue, ensure you install the following:

Objective of This Guide

You will learn how to deploy the two simple multi-container applications to Kubernetes. Kubernetes is a powerful tool that helps in container orchestration. We will use Kubernetes to manage and deploy the two containers to a Kubernetes cluster. A Kubernetes Cluster has master and worker nodes that control the deployed multi-container application. A Kubernetes Cluster also has computing resources such as CPU cores that will host and run the multi-container application. 

We will use Minikube to create and run a Kubernetes Cluster on our local computer. Minikube is a platform for creating a simple Kubernetes Cluster with only a single node. 

NOTE: You can not run Docker Containers on Minikube while in a production environment. It is for developing and testing simple Kubernetes applications. 

To communicate with Minikube, we will require Kubectl. It is a command-line tool interface that will enable developers to deploy the multi-container application. Let’s start by setting up the two simple applications.

Setting Up a Simple Node.js Application

To set up a simple Node.js application, apply the steps described below:

  1. Create a new folder and name it ‘multi-container-application’. This folder will contain all the files for the two applications. This folder will be the project working directory.
  2. In the ‘multi-container-application’ folder, create a new folder and name it ‘server’. This folder will contain all files for the Node.js application.
  3. While in the `server` folder, initialize the Node.js application using the following `npm` command:
    npm init --y
  4. Installing the Node.js application dependencies/libraries. To install the dependencies/libraries, apply the following ‘npm’ command:
    npm install express

    The installed library is a Node.js framework for building our backend server and API routes.

  5. In the `server` folder, create a file and name it `index.js`. Open the file and add the following content:
    #express for building the API routes and back-end server
    const express = require('express')
    # cross-origin resource sharing package from Node.js runtime
    const cors = require('cors')
    
    const app = express()
    #using the cross-origin resource package
    app.use(cors())
    
    app.get('/', (req, res) => {
      res.json([
        {
          "id":"1",
          "title":"Title 1"
        },
        {
          "id":"2",
          "title":"Title 2"
        },
        {
          "id":"3",
          "title":"Title 2"
        }
      ])
    })
    
    app.listen(4000, () => {
      console.log('Backend Server started on port 4000')
    })

The Node.js code will create and start a ‘get’ route. React.js will fetch resources (titles) from this route. To run the application, use the following ‘npm’ command:

npm run dev

It gives the output below:

Next, type ‘http://localhost:4000’ in your browser to view the application:

The Express API routes and server is running. Let’s set up the simple React.js application. 

Setting Up a Simple React.js Application

To set up a simple React.js application, apply the steps below:

1. ‘cd’ into the ‘multi-container-application’ folder and run the following command to create a simple React app

npx create-react-app react-frontend

The command will create a new folder named ‘react-frontend’ in the ‘multi-container-application’ project folder. This folder will contain all the files for the React.js application.

2. Navigate through the ‘react-frontend’. You will find another folder named ‘src’. Open the ‘src’ folder you will find a file named ‘App.js’. You will modify this file using the following code:

import { useEffect, useState } from 'react'
import './App.css';

function App() {
  const [titles, setTitles] = useState([])
  useEffect(() => {
    fetch('http://localhost:4000/')
      .then(res => res.json())
      .then(data => setTitles(data))
  }, [])

  return (
    <div className="App">
      <header className="App-header">
        <h1>all Titles</h1>
        {titles && titles.map(title => (
          <div key={.id}>{.title}</div>
        ))}
      </header>
    </div>
  );
}

export default App;

Our react.js app will fetch resources (titles) from http://localhost:4000/ back-end. 

NOTE: Before you run and launch the simple React.js application in the browser, ensure the back-end server is still running. 

To run the application, use the following ‘npm’ command:

npm start

It gives the output below:

Next, type `http://localhost:3000` in your browser to view the application:

Our two applications are running. The next step is to build the Docker images for the multi-container application using Dockerfiles.

Writing the Dockerfile for the Node.js Application

A Dockerfile contains a list of commands that instructs or guides Docker on how to build the Docker image. We first create a Dockerfile for the Node.js application and then create the Dockerfile for the Node.js application. In the ‘server’ folder, create a ‘Dockerfile’ and add the following content:

# It will pull the node:18-alpine image from Docker Hub and use it as the parent image for the Node.js application container.
FROM node:18-alpine

# This command will install nodemon for monitoring the Express server
RUN npm install -g nodemon

# It will set the working directory `app` for the Docker container
WORKDIR /app

# It will copy all dependencies files from the package.json file to the container working directory
COPY package.json .

#It will install all the libraries and dependencies in the container working directory
RUN npm install

#It will copy all the files and source code to the working directory
COPY . .

#It will expose the Node.js application container on Docker
EXPOSE 4000

#It will start and run the Docker application container
CMD ["npm", "run", "dev"]

Let’s build the Docker image using this Dockerfile.

Building the Docker Image for the Node.js Application

To build the Docker image for the Node.js application using the Dockerfile, apply the following Docker command:

docker build -t ephraimnjoroge/server .

When building the Docker image, ensure you name the Docker image using your Docker Hub username. Docker will build the Docker image and give the following output:

The next step is to push the ‘ephraimnjoroge/server’ to Docker Hub. We will use the image to create a Node.js Docker container which we will deploy to the Kubernetes Cluster.

Pushing the Docker Image for the Node.js Application to Docker Hub

Before you push the Docker image to Docker Hub, ensure you login to Docker Hub from your terminal using the following ‘Docker’ command:

docker login

Then push the Docker image for the Node.js application to Docker Hub using the following Docker command:

docker push ephraimnjoroge/server

Running the Docker Image for the Node.js Application

When you run the Docker image for the Node.js application, it will launch/start a Node.js Docker container. To run the Docker image, apply the following ‘Docker’ command:

docker run -p 4000:4000 ephraimnjoroge/server

The command will start and run the Node.js application container on ‘http://localhost:4000’. This is the same Node.js application that was running locally. However, this time it is running as a Docker container:

The next step is to create the Dockerfile for the React.js application.

Writing the Dockerfile for the React.js Application

This file contains commands that Docker will use to build the Docker image for the React.js application. In the ‘react-frontend’ folder, create a ‘Dockerfile’ and add the following content:

FROM node:18-alpine

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

Let’s build the Docker image for React.js using this Dockerfile.

Building the Docker Image for the React.js Application

To build the Docker image for the React.js application using the Dockerfile, apply the following Docker command:

docker build -t ephraimnjoroge/react-frontend .

The Docker command will build the Docker image and give the following output:

The next step is to push the ‘ephraimnjoroge/server’ image to Docker Hub. We will use the Docker image to create a React.js Docker container which we will also deploy to the Kubernetes Cluster.

Pushing the Docker Image for the React.js Application to Docker Hub

To push the Docker image for the React.js application to Docker Hub, use the following Docker command:

docker push ephraimnjoroge/react-frontend

Running the Docker Image for the React.js Application

When you run the Docker image for the React.js application, it will launch/start a Docker container. To run the Docker image, apply the following ‘Docker’ command:

docker run -p 3000:3000 ephraimnjoroge/react-frontend

The command will start and run the React.js application on ‘http://localhost:3000’. This is the same React.js application that was running locally. However, this time it is running as a Docker container:

Our Docker Containers are up and running. The next step is to create a local Kubernetes Cluster using Minikube.

Creating a Local Kubernetes Cluster Using Minikube

Minikube is a powerful tool that enables developers to create and run a Kubernetes Cluster on a local computer. It’s free to use. The good thing about Minikube is that it comes with Docker. As long as you have Docker, you are ready to use this platform. 

To check the version of Minikube that came with Docker, run this ‘minikube’ command:

minikube version

To start and run Minikube locally, execute this `minikube` command:

minikube start

It gives the output below:

The image above shows our Minikube cluster is up and running. Next, we will install Kubectl to interact/communicate with the Minikube cluster from the terminal. The kubectl commands will also help us with the deployment process.

Installing kubectl

To install kubectl, run this Chocolatey command:

choco install kubernetes-cli

To check the installed kubectl version, run this `kubectl` command:

kubectl --version

For ‘kubectl’ to deploy the multi-container application to Minikube, it needs a YAML file. A YAML file contains the cluster configurations such as the number of container pods. It also shows the type of Kubernetes service that will run the Kubernetes application. 

We will create two YAML files for the multi-container application. The first file will contain the configuration for the Node.js application. The second file will contain the configuration for the React.js application. Let’s start with the YAML file for the Node.js application.

Writing the YAML File for the Node.js Application

In the ‘multi-container-application’ folder, create a new file and name it ‘server-deployment.yaml’. Open the file and add the following YAML content:

#For creating Kubernetes Deployment in the Minikube cluster
apiVersion: apps/v1
kind: Deployment
metadata:
  name: server-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: server
  template:
    metadata:
      labels:
        app: server
    spec:
      containers:
      - name: server
        image: ephraimnjoroge/server
        resources:
          limits:
            memory: "384Mi"
            cpu: "500m"
        ports:
        - containerPort: 4000

---
#For creating a Kubernetes Service in the Minikube cluster
apiVersion: v1
kind: Service
metadata:
  name: server-service
spec:
  type: LoadBalancer
  selector:
    app: server
  ports:
  - protocol: TCP
    port: 4000
    targetPort: 4000

Kubectl will use this file to deploy the Node.js application. This file is subdivided into Deployment and Service:

The first subsection of the file will instruct Kubernetes to create two container pods (replicas) in the Minikube cluster. It will use the ‘ephraimnjoroge/server’ from the Docker Hub to create the Node.js application container.

The second subsection shows the type of Kubernetes service that will run the Kubernetes application. It will use the ‘LoadBalancer’ Kubernetes service. 

Minikube will assign an External Ip address (URL) to this service. We will use the external IP address for this Kubernetes Service to access the Node.js application container. 

Next, let’s create the YAML file for the React.js application.

Writing the YAML File for the React.js Application

This file will be similar to the Node.js application YAML file. The only difference is the Docker image for creating the React.js application container. We will use the ‘ephraimnjoroge/react-frontend’ Docker image from Docker Hub. 

In the ‘multi-container-application’ folder, create a new file and name it ‘react-frontend-deployment.yaml’. Open the file and add the following YAML content:

#For creating the Kubernetes Deployment in the Minikube cluster
apiVersion: apps/v1
kind: Deployment
metadata:
  name: react-frontend-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: react-frontend
  template:
    metadata:
      labels:
        app: react-frontend
    spec:
      containers:
      - name: react-frontend
        image: ephraimnjoroge/react-frontend
        resources:
          limits:
            memory: "384Mi"
            cpu: "500m"
        ports:
        - containerPort: 3000

---
#For creating the Kubernetes Service in the Minikube cluster
apiVersion: v1
kind: Service
metadata:
  name: react-frontend-service
spec:
  type: LoadBalancer
  selector:
    app: react-frontend
  ports:
  - protocol: TCP
    port: 3000
    targetPort: 3000

Our two YAML files are ready. The next step is to apply the `kubectl` command to deploy the multi-container application to Minikube:

Applying the kubectl Deployment Command

We will apply the kubectl command on each of the files as follows:

kubectl apply -f server-deployment.yaml
kubectl apply -f react-frontend-deployment.yaml

The commands will create two Kubernetes Deployments and two Kubernetes services. To get the two deployments, run this command:

kubectl get deployments

The output for the Deployments:

Kubectl created two Deployments named ‘server-deployment’ and ‘react-frontend-deployment’.

To get the two services, run this command:

kubectl get service

Kubectl created two Deployments named ‘server-service’ and ‘react-frontend-service’. We will use these two services to access the multi-container application on the web browser.

Using the ‘server-service’

We will use the ‘server-service’ to access the Node.js application container. To launch this application, use this ‘minikube’ command:

minikube service server-service

The command will start the Node.js as shown below:

From the image above, the Node.js application is running on http://127.0.0.1:5003. Type your IP address (URL) in your web browser to view the Node.js application as shown below:

Our Node.js application is running in the Minikube Kubernetes Cluster. Let’s now use the ‘react-frontend-service’ to launch the React.js application container.

Using the ‘react-frontend-service’

To launch the React.js application container, use this ‘minikube’ command:

minikube service react-frontend-service

The command will start the React.js as shown below:

From the image above, the React.js application is running on http://127.0.0.1:12126. Type your Ip address in your web browser to view the React.js application as shown below:

There you go. The multi-container application is running on the Minikube Kubernetes Cluster. We have deployed the two simple multi-container applications to Kubernetes.

Conclusion

In this guide, we have learned how to deploy a multi-container application to Kubernetes. This guide teaches you how to leverage Docker and use it to create two containers. We created two simple Node.js and React.js applications. Then we used Docker to create containers for two applications. 

We also covered all the steps for setting up Minikube and Kubectl to communicate with the Kubernetes Cluster. We wrote the YAML file for the Node.js and React.js application. Finally, we applied the kubectl command to deploy the multi-container application to Minikube. The multi-container application was launched on the Kubernetes Cluster. You can read this article on Sweetcode on how to deploy Docker Containers to Kubernetes.


Ephraim is an experienced DevOps engineer and software engineer. He has experience in developing web front-end, back-end, and DevOps services in a variety of domains and tech stacks. His strongest skills are in MERN stack, Docker, and Kubernetes. He is passionate about making technology more accessible and easy to understand through writing.


Discussion

Leave a Comment

Your email address will not be published. Required fields are marked *

Menu
Skip to toolbar