Deploy a Node.Js Cloud Native Application to Amazon EKS
Tags: aws, kubernetes, node, docker
Published: 2023-05-21 10:30:59

In this article, I show how to deploy a Cloud Native Node.js application to Amazon EKS via the AWS CLI. Amazon Elastic Container Registry(ECR) is used to store the built docker images.

## Prerequisites

To better follow along with this article, you would need the following:

* [Node.js](https://nodejs.org/en/) 12 or above

* NPM

* AWS CLI configured on your local machine

* An [AWS](https://aws.amazon.com/console/) account

* Docker installed on your local machine

* Knowledge of Kubernetes

## Amazon EKS

**Amazon** **Elastic Kubernetes Service** (**EKS**) is a managed Kubernetes service to run Kubernetes in the AWS cloud and on-premises data centers. As an AWS-managed service, it makes it easy to use Kubernetes on AWS without needing to install and operate the Kubernetes control plane.

We would make use of EKS to deploy the cloud-native app we use in this article.

## Setting up the Project

Here we set up the project, dockerize it and run it locally to make sure everything works as expected.

### Basic Node.js project

We would proceed to clone an already existing application found [here](https://github.com/kkohtaka/webapp-nodejs). It spins up an express server that serves some dummy content.

    # Clone this repository
    $ git clone https://github.com/kkohtaka/webapp-nodejs.git
    # Go into the repository
    $ cd webapp-nodejs

### Containerizing the project

To containerize the project, we would make use of [Docker](https://www.docker.com/). First, we create a Dockerfile for the application.

In the root folder, create a file named Dockerfile and add the following content within it:

    FROM node:14
    WORKDIR /app
    COPY package.json ./
    RUN npm install 
    COPY . .
    EXPOSE 3000
    CMD ["npm", "start"]

Next, create a .dockerignore file:

    node_modules

To build the docker image for the application run the following command

    docker build -t demo/webapp-nodejs .

To verify the image is built well, spin up a container to test by running the built docker image:

    docker run -p 3000:3000 demo/webapp-nodejs

This command above enables us to test the application in a local browser by visiting [http://localhost:3000](http://localhost:3000/). The image below confirms it works as expected.

![Running app](https://cdn-images-1.medium.com/max/2000/1*m1phkTDlMnvQd9Hg0wS1Qw.png)

## Pushing image to Amazon Elastic Container Registry(ECR)

In other to make the built docker image publicly available, we need to push it to a central repo. We would make use of [Amazon ECR](https://aws.amazon.com/ecr/) to store the image.

First, create the Amazon ECR registry where we would store the image. Run the command below to do that

    aws ecr-public create-repository --repository-name webapp-nodejs-repo --region us-east-1

The command connects to AWS using the default AWS profile we have configured and creates the repository. It outputs a JSON-like response containing the details of the newly created repository:

![](https://cdn-images-1.medium.com/max/2556/1*SK9qbhzyKwnF-FXjDTvawQ.png)

Next, authenticate our local machine docker client to the Amazon ECR registry. This gives access to the registry for up to 12hrs, read more about this [here](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html)

    aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws

Proceed to tag the local docker image with the ECR Registry.

Replace REPO_URI with Repository URI gotten from ECR when the registry was created. In my case it is: public.ecr.aws/d5d5p5r5/webapp-nodejs-repo

    docker tag demo/webapp-nodejs:latest <REPO_URI>:latest

Finally, push the image to the ECR repository:

    docker push <REPO_URI>

![docker push](https://cdn-images-1.medium.com/max/3092/1*i-1ZZEeZUeqJjs6N6AjoPg.png)

**Note**: We can also configure the Default region name using **aws configure** for the default profile to be us-east-1 instead of having to include it in every command.

## Provisioning an EKS Cluster

Now that the image has been deployed to ECR, creating an EKS cluster where the app would be deployed is the next thing to do.

We make use of the eksctl CLI to create the cluster in EKS, eksctl which is a simple command-line tool for creating and managing Kubernetes clusters on Amazon EKS.

First, we need to install this CLI to be able to use it, head over to this [page](https://docs.aws.amazon.com/eks/latest/userguide/eksctl.html) to learn how to install it based on your device. After, run the command below to confirm if you have it all set up.

    eksctl version

If you get a version shown, then all is well, else go back to the referenced page to identify any step you may have missed.

Now we have configured eksctl, we now provision our first cluster(creating the cluster in the us-east-2 region):

    eksctl create cluster --name webapp-nodejs-cluster --region us-east-2

![eksctl create cluster](https://cdn-images-1.medium.com/max/3536/1*XI-3v7HykYuZkvBpslph_g.png)

Finally, configure kubectl to enable it to connect to the EKS cluster by updating the kubectl config (update-kubeconfig) with the cluster endpoint.

    aws eks update-kubeconfig --name webapp-nodejs-cluster --region us-east-2

## Deploying to EKS Cluster

At this stage, we have an image in ECR and an empty EKS Cluster running, the last step is to run the application within this EKS Cluster.

To deploy the application, create a Deployment.yml file containing the deployment details. The deployment creates a [Pod](https://kubernetes.io/docs/concepts/workloads/pods/), where the application runs in a single container using the Docker image.

Replace the image “public.ecr.aws/d5d5p5r5/webapp-nodejs-repo” with your ECR URI:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: webapp-nodejs
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: webapp-nodejs
      template:
        metadata:
          labels:
            app: webapp-nodejs
        spec:
          containers:
          - name: webapp-nodejs
            image: public.ecr.aws/d5d5p5r5/webapp-nodejs-repo:latest
            ports:
              - containerPort: 3000

Next, apply the deployment to create it:

    kubectl apply -f Deployment.yml

To verify if it works, run the command below:

    kubectl get deployments

![](https://cdn-images-1.medium.com/max/2208/1*ZUnqrM_1K1H3LYyhX4Bzhw.png)

We now need to expose the pods running within the cluster to the outside world to be accessible. To do this we need to create a Service with the type of **Load Balancer** to expose the port the application is listening to.

    kubectl expose deployment webapp-nodejs --port=80 --target-port=3000 --type=LoadBalancer

To verify if it works, run the command below:

    kubectl get services

![get services](https://cdn-images-1.medium.com/max/3656/1*Kitw3LAcCi4vMivr6OU4Dg.png)

## Testing

Finally, to confirm everything works as expected, copy the exposed **EXTERNAL-IP **address shown in the previous command and visit a browser:

![](https://cdn-images-1.medium.com/max/3196/1*0q54Iivhzsn3FzlNMCPMoA.png)

Great! it works as expected!

## Conclusion

In this article, you learned how to Dockerize a Node.js application, push the built image to **Amazon Elastic Container Registry (ECR)**, created an **Amazon Elastic Kubernetes Service (EKS)** cluster, deployed the application within the cluster, and finally exposed the deployment so we could test it.

Amazon EKS makes it easy and super fast to deploy cloud native applications, try using it for your next deployment!