In this tutorial, we will learn how to use Docker, minikube, and kubectl to deploy a React application to Kubernetes. Let’s take a closer look at these tools to learn about why they are the best choice for deploying containerized React applications.
Docker is an open source software containerization platform that allows you to package applications into standardized, isolated units called containers. These containers combine the applications source code with the operating system libraries and dependencies required to run that code in any environment.
Docker allows you to build, test, deploy, and scale applications quickly. Its development speed, scalability, and ecosystem richness are some of the many reasons why we will use it to containerize a React application. Please keep in mind that using Docker to containerize is also known as “dockerizing” in the developer community.
Kubernetes is an open source tool that allows you to automate the deployment, scaling, and management of containerized applications. We are going to use it to deploy and manage our dockerized React app.
Next, minikube is a tool that sets up a local Kubernetes cluster on macOS, Linux, and Windows. We are going to use this tool to run Kubernetes locally instead of using a cloud provider.
Finally, kubectl is the Kubernetes command-line tool that allows us to run commands against Kubernetes clusters. We will use this tool to deploy our dockerized React application, and inspect and manage our local Kubernetes cluster resources.
In order to follow this tutorial you will need a machine with the following tools installed:
Along with the tools mentioned above, you will also need a Docker Hub account.
In this section, we will create the project directory structure to store our application files. After that, we’ll create a React application with Create React App, test the application, and build it for production.
Create the project directory and navigate into it like so:
mkdir react-docker-kubernetes cd react-docker-kubernetes
Create a directory called K8s
to store your Kubernetes files, and another named react-docker
to store your React application and Docker files:
mkdir K8s mkdir react-docker
Run the following command to create a new React application in the react-docker
directory, then navigate into it and start the application:
npx create-react-app react-docker
You can manually navigate to your application by navigating to the following URL: http://localhost:3000/
The application should look like this:
When you start running the application with npm start
, by default the application will run on port 3000
if there isn’t an application running there already. You can change this behavior by creating a .env
file and manually setting the port inside it.
Close the process running your React app, then create a .env
and add the following content to it to set the port to 3002:
PORT=3002
Let’s build our application for production with the following command:
npm run build
When the command above finishes executing, the files of our production-ready application will be available in a directory named build
.
In this section, we will create a Docker image of our React application, run and test a container created from the application image, then push it to a Docker Hub account.
Before we can proceed, you need log in to your Docker Hub account.
To do so, run the following command:
docker login
You will be asked to enter your Docker Hub account’s username and password, and if you are successful, you will see the following message:
Login Succeeded
In order to create a Docker image, we have to create two important files: Dockerfile
and .dockerignore
. A Dockerfile
is a text document that contains all the commands a user could call on the command line to assemble an image. A .dockerignore
file is a text document that contains a list of files and directories that a user wants to ignore while assembling an image.
In the root directory of your project, enter the following code into Dockerfile
:
FROM nginx:stable-alpine COPY build/ /usr/share/nginx/html
In the code above, we are pulling the base image for our dockerized application, which contains Nginx
running on Alpine Linux. Nginx
is an open-source web server that can also be used as a reverse proxy, load balancer, mail proxy, and HTTP
cache.
After pulling the base image, you are copying the directory that contains the files of our React application to a directory where Nginx
will be able to access them and serve the application.
Now, add the following code to .dockerignore
:
npm-debug.log .dockerignore **/.git **/.DS_Store **/node_modules
In the code above, we declared the files and directories that we wish to exclude from our Docker image.
Now that we have created Dockerfile
and .dockerignore
, we are ready to build the Docker image of our React application.
Run the following command to build the image:
docker build -t your_docker_username/react-docker .
With the command above, we created the image and set its name to react-docker
. Replace your_docker_username
with your Docker Hub account’s username.
Now, run the dockerized application with the following:
docker run -d -p 3000:80 your_docker_username/react-docker
The command above starts a Docker container with your image in detached mode, and maps our machine port 3000
to the container port 80
where our Docker container is running.
Open your preferred browser and navigate to http://localhost:3000/
, and you should see your React application page.
After testing the application, make sure you stop all containers with the following command:
docker stop $(docker ps -a -q)
Now that you have successfully tested that the container runs, use the following command to push your image to your Docker Hub account:
docker push your_docker_username/react-docker:latest
When the command above finishes executing, anyone with Docker installed will be able to pull your dockerized React application.
In this section, we will start a local Kubernetes cluster, configure the cluster, then deploy our dockerized application to the cluster and scale it.
To begin, navigate to the K8s
directory like so:
cd ../K8s
Start your local Kubernetes cluster with minikube:
minikube start
Then, use kubectl to create a new namespace called react-docker
:
kubectl create namespace react-docker
Now, set react-docker
as the default context:
kubectl config set-context --current --namespace=react-docker
Create a file called deployment.yaml
and add the following code to it:
kind: Deployment apiVersion: apps/v1 metadata: name: react-docker spec: replicas: 2 selector: matchLabels: app: react-docker template: metadata: labels: app: react-docker spec: containers: - name: react-docker image: your_docker_username/react-docker ports: - containerPort: 80
In the deployment.yaml
file above, we set the name of our app deployment to react-docker
and the number of pods
to 2
.
Next, we specified the image that we want to use to build your app as your_docker_username/react-docker
. Now, replace your_docker_username
with your actual Docker Hub username.
Lastly, we specified that the container is running on port 80
.
Deploy the application with the following:
kubectl apply -f deployment.yaml
And monitor the status of the deployment with the following command:
kubectl get deployment -w
After running the command above, you should see an output similar to this:
NAME READY UP-TO-DATE AVAILABLE AGE react-docker 0/2 2 0 18s react-docker 1/2 2 1 23s react-docker 2/2 2 2 29s
To access your app from outside the cluster, you will need to create a service. This service will be a load balancer.
Create a file load-balancer.yaml
file and add the following code to it:
apiVersion: v1 kind: Service metadata: name: load-balancer labels: app: react-docker spec: type: LoadBalancer ports: - port: 80 targetPort: 80 protocol: TCP nodePort: 31000 selector: app: react-docker
Here, we set the name of the service to load-balancer
.
We also specified the service type, made the service accessible on port 80
, and set the nodePort
to 31000
. This nodePort
is the port on which we will be able to access the application. Finally, we indicated that this service is for the react-docker
app.
Now, we can deploy the service like so:
kubectl apply -f load-balancer.yaml
And we can monitor the status of the service with the following command:
kubectl get services -w
We should get an output similar to the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE load-balancer LoadBalancer 10.101.114.62 <pending> 80:31000/TCP 50s
The application will be accessible on the following URL:
http://your_minikube_ip:31000
Next, use the following command to get the minikube IP address:
minikube ip
Replace your_minikube_ip
with the IP address returned by the minikube ip
command.
Navigate to the URL and you will be able to access the dockerized application running on Kubernetes.
Now, we can scale up our application by increasing the number of pods to ten with the following command:
kubectl scale deployment react-docker --replicas=10
Monitor the status of the deployment like so:
kubectl get deployment -w
You should see that we now have ten pods running the React application:
NAME READY UP-TO-DATE AVAILABLE AGE react-docker 5/10 10 5 39m react-docker 6/10 10 6 40m react-docker 7/10 10 7 40m react-docker 8/10 10 8 40m react-docker 9/10 10 9 40m react-docker 10/10 10 10 40m
We can also scale down the application by decreasing the number of pods. In the this case, three:
kubectl scale deployment react-docker --replicas=3
We can monitor the status of the deployment exactly as we did before, and you should see that we now have three pods running the application:
NAME READY UP-TO-DATE AVAILABLE AGE react-docker 3/3 3 3 41m
In this tutorial, we learned how to create a React application and build it for production. After building the application, we learned how to dockerize and push it to your Docker Hub account. Finally, we learned how to create and configure a local Kubernetes cluster, deploy the dockerized React application to the cluster, and how to scale the application.
For more information on how to dockerize applications and how to deploy them to a Kubernetes cluster make sure you read the Docker and Kubernetes documentation.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.