Kubernetes is currently the de-facto standard for deploying applications in the cloud. Every major cloud provider offers a dedicated Kubernetes service (eg. Google Cloud with GKE, AWS with EKS, etc.) to deploy applications in a Kubernetes cluster.
There are many reasons for choosing Kubernetes for deploying your React application:
- unified and standardized deployment model across the cloud providers
- robustness against downtime as several containers are deployed (horizontal scaling)
- handling peak traffic with auto-scaling
- zero-downtime deployments, canary deployments, etc.
- simple A/B testing
With this post, I'll demonstrate how to deploy a React application to a Kubernetes cluster with five easy steps. To follow the article you just need basic Docker knowledge.
As we all want quick feedback while learning a new topic I'll use a local Kubernetes cluster for this example. You can spin up this local Kubernetes cluster in minutes if you have a Docker engine with Kubernetes support installed on your machine. This is available since version 18.06.0 for both Docker Desktop for Windows/Mac.
Let's get started...
Step 1: Create the React application
I start off with a fresh React application created with create-react-app
from Facebook:
➜ node -v
v10.16.0
➜ npm -v
6.9.0
➜ npx create-react-app react-app-kubernetes
npx: installed 91 in 5.787s
Creating a new React app in /Users/rieckpil/Desktop/react-app-kubernetes.
Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...
...
Happy hacking!
This will create all the required configuration and files to start developing a new React application.
Make sure you are able to start and access the React application on your local machine at http://localhost:3000 using npm start
. For the further sections, we need the optimized production build of the React application which is created with:
➜ npm run-script build
> react-app-kubernetes@0.1.0 build /Users/rieckpil/Desktop/junk/react-app-kubernetes
> react-scripts build
Creating an optimized production build...
Compiled successfully.
File sizes after gzip:
36.44 KB build/static/js/2.b41502e9.chunk.js
762 B build/static/js/runtime~main.a8a9905a.js
602 B build/static/js/main.28647029.chunk.js
517 B build/static/css/main.2cce8147.chunk.css
...
If you have an existing React application you can skip this section and continue with the next one. Just make sure you have the production build of your application available at build/
.
Step 2: Dockerize the React application
For deploying the React application to Kubernetes, we need to package it inside a container. Kubernetes supports several container engines, but Docker is currently the most adopted one.
To create a Docker container we need a Dockerfile
at the root level of our React application folder. This file defines what OS is used, how it is configured and what other applications are running inside this container.
For this example, I'm using nginx to serve the content of the React application and the simplest Dockerfile
looks like the following:
FROM nginx:1.17
COPY build/ /usr/share/nginx/html
Our Docker container inherits everything from the official nginx:1.17
Docker image and just copies the React production build to the container.
To speed up the creation of the Docker container, make sure you add a .dockerignore
to your project to exclude the node_modules
from being sent to the Docker context:
node_modules
Once you have your React production build in place, start your Docker engine and execute the following command to create the Docker image:
➜ docker build -t my-react-app .
Step 1/2 : FROM nginx:1.17
1.17: Pulling from library/nginx
fc7181108d40: Pull complete
d2e987ca2267: Pull complete
0b760b431b11: Pull complete
Digest: sha256:96fb261b66270b900ea5a2c17a26abbfabe95506e73c3a3c65869a6dbe83223a
Status: Downloaded newer image for nginx:1.17
---> f68d6e55e065
Step 2/2 : COPY build/ /usr/share/nginx/html
---> 35d48f28a918
Successfully built 35d48f28a918
Successfully tagged my-react-app:latest
For a more production-ready Docker container, make sure you customize the nginx configuration for your needs.
Step 3: Connect to your Kubernetes cluster
To start your local Kubernetes cluster, open the Docker Desktop preferences and switch to the Kubernetes tab:
Here you can enable the Kubernetes support. If you enable it for the first time, the cluster creation may take some time, as several Docker images are downloaded in the background.
Once your local Kubernetes cluster is running, connect to it via kubectl
(if missing, download here):
➜ kubectl config use-context docker-for-desktop
Switched to context "docker-for-desktop".
➜ kubectl get nodes
NAME STATUS ROLES AGE VERSION
docker-for-desktop Ready master 3d v1.10.11
➜ kubectl cluster-info
Kubernetes master is running at https://localhost:6443
KubeDNS is running at https://localhost:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
With this Kubernetes support of Docker Desktop you'll get a local single node cluster which is nice for evaluation and learning purposes.
If you want to deploy your React application to a Kubernetes cluster in the cloud, start here:
- Google Kubernetes Engine (GKE) quickstart
- Azure Kubernetes Engine (AKS) quickstart
- AWS Kubernetes Engine (EKS) quickstart
- Oracle Container Engine for Kubernetes (OKE) quickstart
Step 4: Upload the Docker image to your container registry
To be able to pull the Docker image within the Kubernetes cluster, we need to upload the image to a Docker registry. For a cloud deployment, you usually get a dedicated registry from the cloud provider to upload your image. As we are deploying the application to a local cluster, we need a local Docker registry.
You can create a local Docker registry with the following statement:
➜ docker run -d -p 5000:5000 --restart=always --name registry registry:2
For uploading our previously created React Docker image, we have to tag the image with the hostname and port of the registry:
➜ docker tag my-react-app localhost:5000/my-react-app
And can now finally push the image to our Docker registry:
➜ docker push localhost:5000/my-react-app
The push refers to repository [localhost:5000/my-react-app]
9d9745936581: Pushed
d2f0b6dea592: Pushed
197c666de9dd: Pushed
cf5b3c6798f7: Pushed
latest: digest: sha256:66c94bdba6b06d1964a764cd14dc97d8adf202b02ab6e6fbd10b23ad4a8554a1 size: 1158
Now we are ready to deploy the application to the Kubernetes cluster.
Step 5: Deploy the React application
Usually, every Kubernetes object (service
, pod
, deployment
, etc.) is described in a .yaml
file but .json
is also possible.
For deploying the React application to Kubernetes we need a so-called deployment
. This Kubernetes entity makes sure our application will have as many replicas (parallel pods) as we define. In addition, we can define the Docker image we want to use, what ports are used and further metadata for our application:
kind: Deployment
apiVersion: apps/v1
metadata:
name: my-react-app
spec:
replicas: 2
selector:
matchLabels:
app: my-react-app
template:
metadata:
labels:
app: my-react-app
spec:
containers:
- name: my-react-app
image: localhost:5000/my-react-app
imagePullPolicy: Always
ports:
- containerPort: 80
restartPolicy: Always
With just the deployment
we wouldn't be able to access our application from outside. To expose applications, Kubernetes offers a so-called service
. Using a service
we can define which ports to expose to the cluster/outside.
There are several different types of a Kuberntes service
and I'm choosing the simplest one for your example: NodePort
. This type will expose a defined port on every node in our Kubernetes cluster (with the local Kubernetes cluster, we just have one node) and map it to an application's port:
kind: Service
apiVersion: v1
metadata:
name: my-react-app
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
protocol: TCP
nodePort: 31000
selector:
app: my-react-app
Both the service
and deployment
can be added to a single .yaml
file with a ---
for separation. In our example, I've created one deployment.yaml
file to store both:
kind: Deployment
apiVersion: apps/v1
# more ...
---
kind: Service
apiVersion: v1
# more ...
You can now use this file to deploy your application to Kubernetes with:
➜ kubectl apply -f deployment.yaml
deployment.apps "my-react-app" created
service "my-react-app" created
And can check that everything is running using:
➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-react-app-6c8b5c4759-fgb2q 1/1 Running 0 7m
my-react-app-6c8b5c4759-jrzzj 1/1 Running 0 7m
➜ kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
my-react-app 2 2 2 2 7m
➜ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d
my-react-app NodePort 10.99.224.141 <none> 80:31000/TCP 7m
Once everything is up and running, visit http://localhost:31000 on your machine and you should see your React application, now served from a Kubernetes cluster:
To remove the React application from your Kubernetes cluster, just run
➜ kubectl delete service,deployment my-react-app
service "my-react-app" deleted
deployment.extensions "my-react-app" deleted
You can find the whole codebase for this example on GitHub.
For further React related posts, visit my blog:
- Preview PDF files with React
- MicroProfile JWT Authentication with Keycloak and React
- Up- and download files with React and Spring Boot
Have fun deploying your React applications to Kubernetes,
Phil
Top comments (4)
Hey great tutorial. In step 3, I believe an update is necessary to change the command from
$ kubectl config use-context docker-for-desktop
to
$kubectl config use-context docker-desktop
Also in the deploying to the cloud step, including deploying on OCI via: docs.cloud.oracle.com/en-us/iaas/C...
would make this tutorial even more overarching.
thanks for your comment. Which Docker for Desktop version are you using? For me both
docker-for-desktop
anddocker-desktop
work in step 3.Regarding OCI: I wanted this post to focus on deploying it to a local cluster. Including now one cloud provider would require including all common providers (to be balanced). I guess each cloud provider has great documentation about how to deploy applications to their Kubernetes solution.
But indeed Oracle was missing in the quickstart links and I added it, thanks for the catch!
Important info: if you are using minikube, you need to replace "localhost" by the minikube ip.
To discover it, run on terminal
minikube ip
.Hey,
Great article!
Could'nt find any more simpler steps to deploy apps on Kubernetes.