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:
- Docker Desktop.
- Node.js javascript runtime.
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:
- 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.
- 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.
- While in the `server` folder, initialize the Node.js application using the following `npm` command:
npm init --y
- 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.
- 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.