<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adeolu Oyinlola</title>
    <description>The latest articles on DEV Community by Adeolu Oyinlola (@deoluoyinlola).</description>
    <link>https://dev.to/deoluoyinlola</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F835858%2F958c2d5a-10d5-41e6-a23e-c32cb438e4fc.jpeg</url>
      <title>DEV Community: Adeolu Oyinlola</title>
      <link>https://dev.to/deoluoyinlola</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/deoluoyinlola"/>
    <language>en</language>
    <item>
      <title>Keep Calm! Kubernetes Cluster!! with helm file</title>
      <dc:creator>Adeolu Oyinlola</dc:creator>
      <pubDate>Sun, 25 Dec 2022 16:13:41 +0000</pubDate>
      <link>https://dev.to/deoluoyinlola/keep-calm-kubernetes-cluster-with-helm-file-1172</link>
      <guid>https://dev.to/deoluoyinlola/keep-calm-kubernetes-cluster-with-helm-file-1172</guid>
      <description>&lt;p&gt;Hi there.&lt;br&gt;
Thanks for the interest in this post, where we are going to be calmly deploying kubernetes cluster together with helmfile. Chance are that you are either a Cloud engineer, DevOps engineer, software developer or average techie who want to add to his/her body of knowledge. So I have decided to make it both beginner's friendly and a sort of refresher for the expert.&lt;/p&gt;

&lt;p&gt;While I know that this sort of effort has been done already by others, but I think that it's okay for people to have options. Like other of my posts (or are in the process of writing) they will remain a work in progress. Open to feedback, comment, expansion and improvement. Please feel free to provide your thoughts on ways that I can improve things. Your input would be much appreciated.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Contents&lt;/strong&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Project Objectives&lt;/li&gt;
&lt;li&gt;Pre-requisites&lt;/li&gt;
&lt;li&gt;
Demonstration

&lt;ul&gt;
&lt;li&gt;Part 1 - Provision cluster with eskctl&lt;/li&gt;
&lt;li&gt;Part 2 - Deploy Microservices with helmfile&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/deoluoyinlola/aws-eksctl-helm" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Project Objectives &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;By the end of each part of this project, we will know how to; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;provision scalable managed kubernetes(eks) cluster resources in AWS with the help of eksctl.&lt;/li&gt;
&lt;li&gt;deploy highly performant microservices applications with helmfile.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Pre-requisites &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;So that we all be on the same page, it will be nice to have following in our tool belt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Knowledge requirement
&lt;/h4&gt;

&lt;p&gt;Basic knowledge of how AWS, kubernetes, helm and yaml works.&lt;/p&gt;
&lt;h4&gt;
  
  
  Tools
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Tools&lt;/th&gt;
    &lt;th&gt;Official Links&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;AWS CLI&lt;/td&gt;
 &lt;td&gt;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;eksctl&lt;/td&gt;
    &lt;td&gt;https://eksctl.io/&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;helm&lt;/td&gt;
    &lt;td&gt;https://helm.sh/&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Back to Contents&lt;/p&gt;
&lt;h3&gt;
  
  
  Demonstration &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Part 1 - Provision cluster with eskctl &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: Install and configure kubectl, AWS CLI and eksctl. You can quickly look up the documentation for each to set up before proceeding with this demo. &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html" rel="noopener noreferrer"&gt;Link to How&lt;/a&gt;.
Also, careful to set and utilise profile name when working with multiple accounts in your machine.&lt;/li&gt;
&lt;li&gt;Step 2: Create programmatic access for the new user from AWS console management. We need to create new IAM User credential for this project, with policies to manage eks cluster. Avoid the use of root account for security reason and best practice consideration.&lt;/li&gt;
&lt;li&gt;Step 3: Creating cluster with (1.) a name (2.) version 1.22 (3.) nodegroup name, type and number in a specify region. Run the command;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eksctl create cluster --name ecommerce --version 1.22 --nodegroup-name clusternode --node-type t3.micro --nodes 2 --managed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Step 4: After some minutes, check the Cloudformation and eks from AWS management console.
With this single command, we have successfully create an eks cluster with 2 nodegroup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Configure kubectl to communicate with cluster
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Step 1; Configure your computer to communicate with your cluster. Run this command;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws eks update-kubeconfig --region us-east-1 --name ecommerce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Step 2; Confirm your context and test your configuration. Run these commands first to list your contexts and check your configuration
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl config get-contexts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get svc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Back to Contents&lt;/p&gt;
&lt;h4&gt;
  
  
  Part 2 - Deploy Microservices with helmfile&lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Let’s quickly remind ourselves that;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The microservices source code repository for this project is from this link; &lt;a href="https://github.com/GoogleCloudPlatform/microservices-demo" rel="noopener noreferrer"&gt;google-microservices-demo&lt;/a&gt;, containing 11 services we will deploy with this demo. Also, from the same repo, it was illustrated and visualized how these services are connected to each other including a 3rd party service for database - redis. Among the services, Frontend serves as an entrypoint for all the services receiving external requests from the browser. Meanwhile, the load generator deployment is optional, so in this demo we wouldn't bother deploying it.&lt;/li&gt;
&lt;li&gt;Image names for each Microservices, expected environment variables including which port each starts and decision on namespace depending on developer's access must be a collaborative effort between Dev and Ops team.&lt;/li&gt;
&lt;li&gt;Also, deployment options among few others includes imperative, declarative approach and templating engine with helm. In this demo, we are going to be exploring declarative approach with helmfile, but if you so desire to use kubernetes declarative approach you can check these following steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Deploy Microservices Declaratively - Alternative
&lt;/h5&gt;

&lt;p&gt;This is not best practice for more complex and dynamic projects. So be sure of the project requirements before trying out this option.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 1; Create a project folder and config yaml file from scratch containing;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch config.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;1) deployment configuration for each microservices and&lt;br&gt;
2) service configuration for each microservices.&lt;br&gt;
Where we appropriately adjust each service image name, pod label, image url, container port, target port, service port, environment variable and external IP(NodePort) for frontend service. You can clone the exact config code from my repo for this projects(link at the end of this project). If you want to explore this approach, be sure to have kubeconfig connect to the cluster. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 2; Deploy the microservices with the;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f config.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  Deploy Microservices Declaratively with helmfile
&lt;/h5&gt;

&lt;p&gt;Yeah, the main deployment approach for this demonstration. I admit that the initial configuration for helmfile can be challenging for a beginner but is actually a great alternative for complex microservices especially in a more dynamic environment. So let's get our hand dirty.&lt;/p&gt;
&lt;h5&gt;
  
  
  Create helm charts
&lt;/h5&gt;

&lt;p&gt;Before starting to carry out the steps accordingly, first install helm. Second, create a project folder that will contain another folder named charts. Inside the charts folder, we are going to create a shared helm chart for the 10 similar applications and another helm chart for redis service. In the case of redis, to persist the data, we are going to use the volume type of emptyDir and mount it into the container volume.&lt;br&gt;
Project folder &amp;gt; charts folder &amp;gt; common &amp;amp; redis&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: cd into charts folder and create shared helm chart for the 10 microservices by running this command;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm create common
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Which will auto generate a folder named after what we call our chart, containing; charts folder, template folder, Chart.yaml, values.yaml, .helmignore file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 2: Inside the template folder, you can clean up the default files and create another &lt;code&gt;deployment.yaml&lt;/code&gt; and &lt;code&gt;service.yaml&lt;/code&gt;, where we will define all our yaml blueprint for all the deployment and services respectively. For all the attributes we want to make configurable, we will use placeholders to enable dynamic input for the actual values, where the variable name will be defined inside the values.yaml.&lt;/li&gt;
&lt;li&gt;deployment.yaml code;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.appName }}
spec:
  replicas: {{ .Values.appReplicas }}
  selector:
    matchLabels:
      app: {{ .Values.appName }}
  template:
    metadata:
      labels:
        app: {{ .Values.appName }}
    spec:
      containers:
      - name: {{ .Values.appName }}
        image: "{{ .Values.appImage }}:{{ .Values.appVersion }}"
        ports:
        - containerPort: {{ .Values.containerPort }}
        env:
        {{- range .Values.containerEnvVars}}
        - name: {{ .name }}
          value: {{ .value | quote }}
        {{- end}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;service.yaml code;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.appName }}
spec:
  type: {{ .Values.serviceType }}
  selector:
    app: {{ .Values.appName }}
  ports:
  - protocol: TCP
    port: {{ .Values.servicePort }}
    targetPort: {{ .Values.containerPort }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Step 3: Set the -range built-in function for working with lists of environment variables; mostly use in the env attribute and also observe quote built-in function for working with string value.&lt;/li&gt;
&lt;li&gt;Step 4: Also in the &lt;code&gt;values.yaml&lt;/code&gt; file where we define the variable name in flat structure, set the default values for the template files. Meanwhile, in each template file, the .Values built-in object defined inside the template placeholder is passed into the template from the values.yaml file in the chart and not neither from user-defined nor parameter passed.&lt;/li&gt;
&lt;li&gt;Step 5; Create helm chart for redis. We are going to replicate same processes as above for redis, we intentionally didn't include it to the common chart because this third party service; (1.) is stateful and (2.) does not share same lifecycle with our Microservices. cd into the charts folder, then run;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm create redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Step 6; For better structure, we will create another folder named values at the root of project directory, that will contain config files for all the  microservice which will override the default value in the &lt;code&gt;values.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all these steps, we should have successfully parametize everything inside the config files. Do well to clone my repo for the exact config or expand on it as desire.&lt;br&gt;
Next, we are going to deploy the microservices into the cluster.&lt;/p&gt;
&lt;h5&gt;
  
  
  Deploy microservices to the cluster
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Step 1; To preview if the config files for each service defined are correct before actual deployment, run this command for each service file;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm template -f &amp;lt;path/to/the/file&amp;gt; &amp;lt;path/to/the/chart&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;this validate our manifest locally&lt;br&gt;
or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install --dry-run -f &amp;lt;path/to/the/file&amp;gt; &amp;lt;release-name&amp;gt;  &amp;lt;path/to/the/chart&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this send files to Kubernetes cluster to validate&lt;br&gt;
or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm lint -f &amp;lt;path/to/the/file&amp;gt; &amp;lt;path/to/the/chart&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Step 2; Individually check if microservices successfully deploy to the cluster. Here we are going to install a chart, overrides values from a file, give a release name and chart name with this command;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install -f &amp;lt;path/to/the/file&amp;gt; &amp;lt;releases-name&amp;gt; &amp;lt;path/to/the/chart&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Step 3; To list the deploy microservices  with this command;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we have about three option to deploy all microservices to the cluster; (1.) deploy each file with &lt;code&gt;helm install&lt;/code&gt; command, (2.) write and execute a script, the script basically contains lines of helm install for each services. (3.) deploy with helmfile. We are going to use the later;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 4; Install helmfile tool, with this command for macOS user;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install helmfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now use the helmfile command from the next step henceforth.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 5; Create and configure a helmfile at the root of project folder - &lt;code&gt;helmfile.yaml&lt;/code&gt;.
Containing the following code, which is basically release name, chart and value for each services;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;releases:
  - name: rediscart
    chart: charts/redis
    values: 
      - values/redis-values.yaml
      - appReplicas: "1"
      - volumeName: "redis-cart-data"

  - name: emailservice
    chart: charts/common
    values:
      - values/email-service-values.yaml

  - name: cartservice
    chart: charts/common
    values:
      - values/cart-service-values.yaml    

  - name: currencyservice
    chart: charts/common
    values:
      - values/currency-service-values.yaml   

  - name: paymentservice
    chart: charts/common
    values:
      - values/payment-service-values.yaml

  - name: recommendationservice
    chart: charts/common
    values:
      - values/recommendation-service-values.yaml

  - name: productcatalogservice
    chart: charts/common
    values:
      - values/productcatalog-service-values.yaml

  - name: shippingservice
    chart: charts/common
    values:
      - values/shipping-service-values.yaml

  - name: adservice
    chart: charts/common
    values:
      - values/ad-service-values.yaml

  - name: checkoutservice
    chart: charts/common
    values:
      - values/checkout-service-values.yaml

  - name: frontendservice
    chart: charts/common
    values:
      - values/frontend-values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Step 6; Declare the manifests into the cluster;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helmfile sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all went well, all the microservices should deploy after this command.&lt;br&gt;
We can as well check on browser through our IP address, if we are sure to configure the frontend service to NodePort. Which is our entry point to the microservices.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 7; Clean up the resources, so you don't get charge pls!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila! we have come to the end.&lt;/p&gt;

&lt;p&gt;I'd like to hear from you. &lt;br&gt;
&lt;a href="https://www.linkedin.com/in/deoluoyinlola/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait! a minutes, there's a good chance that if you ask me a technical question I may not know the answer immediately or might take few minutes to consult docs and stackoverflow. So please be gentle with your comments and request.&lt;br&gt;
Back to Contents&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>How I implement DevOps culture in a webapp - Part 1</title>
      <dc:creator>Adeolu Oyinlola</dc:creator>
      <pubDate>Wed, 25 May 2022 10:36:22 +0000</pubDate>
      <link>https://dev.to/deoluoyinlola/how-i-implement-devops-culture-in-a-webapp-part-1-3h5a</link>
      <guid>https://dev.to/deoluoyinlola/how-i-implement-devops-culture-in-a-webapp-part-1-3h5a</guid>
      <description>&lt;p&gt;In this post, am going to show you a real-world solution for setting up an environment that is using DevOps technologies and practices for deploying apps and cloud services/cloud infrastructure to AWS.&lt;br&gt;
I will break this series into two part, where this is going to be the first part, you will do well to search for the second part. However, I will drop the link to second part at the end of this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Full Disclosure -&lt;/em&gt; As a DevOps interns with permission, I did have to use ruralx.africa landing page source code and the initial DevOps practices and technologies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why DevOps?&lt;/strong&gt;&lt;br&gt;
Imagine you're currently working in an organization that is very monolithic. There is a ton of bare metal, virtualization, manual deployments of applications, and old school practices based on the current teams knowledge of IT.&lt;/p&gt;

&lt;p&gt;You're brought in to the company and team to make things more modern so the organization can not only succeed, but stay ahead of their competition. Management now understands the needs and complexity that comes with staying ahead of their competition and they know that they need to. Otherwise, the organization will fall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution?&lt;/strong&gt;&lt;br&gt;
The solution in this post is a real-world example of how to sprinkle a little DevOps on an existing source code - DevOps is a set of practices that combines software development and IT operations. It aims to shorten the systems development life cycle and provide continuous delivery with high software quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
I will be using the following technologies and platforms to set up a DevOps environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AWS&lt;br&gt;
AWS will be used to host the application, cloud infrastructure, and any other services we may need to ensure the ruralx app is deployed properly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS CLI&lt;br&gt;
The AWS CLI is a way for you to interact with all AWS services at a programmatic level using the terminal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub&lt;br&gt;
To store the application and infrastructure/automation code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nodejs&lt;br&gt;
Nodejs will be used for the webapp (it is written in JavaScript).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker&lt;br&gt;
Create a Docker image&lt;br&gt;
Store the Docker image in AWS ECR&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terraform&lt;br&gt;
Create an S3 bucket to store Terraform State files&lt;br&gt;
Create an AWS ECR repository with Terraform&lt;br&gt;
Create an EKS cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubernetes&lt;br&gt;
To run the Docker image that's created for the containerized ruralx app. Kubernetes, in this case, EKS, will be used to orchestrate the container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CI/CD&lt;br&gt;
Use GitHub Actions to create an EKS cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automated testing&lt;br&gt;
Testing Terraform code with Checkov&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prometheus&lt;br&gt;
An open-source monitoring system with a dimensional data model, flexible query language, efficient time series database and modern alerting approach.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this first part, I will show you how I apply DevOps practices in Continuous Development; using AWS, Docker and Terraform. Where in the last part, I will show you how I apply Continuous Integration and Continuous Deployment; using GitHub Action, Kubernetes and Prometheus.&lt;br&gt;
Let's get to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.0 AWS&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Install AWS CLI&lt;/strong&gt;&lt;br&gt;
The steps to install AWS is pretty simple and straight, follow each step from AWS documentation. Note that installation of basic tools like AWS, Text Editor, Docker and others are outside the scope of this post. Else, it will make this post unnecessarily long, so I will assume you have all the prerequisites knowledge mentioned above.&lt;br&gt;
For AWS CLI documentation, &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html" rel="noopener noreferrer"&gt;Here is the link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure Credentials To Access AWS At The Programmatic Level&lt;/strong&gt;&lt;br&gt;
The purpose is to configure IAM credentials on my local computer so that you can access AWS at a programmatic level (SDKs, CLI, Terraform, etc.).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open up the AWS management console and go to IAM
Sign in to the organization account, from your username tab at top right corner dropdown click Security Credential;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyzre5toqnathomrimu3u.PNG" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Create a new user or use existing AWS user
It is highly recommended to create a new user for this access. Particularly for organization project where each team have a distinct access to particular asset of the organization and controlled by root user. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click User from IAM menu bar at the top left;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m9cgiik2k42ixo37zru.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4m9cgiik2k42ixo37zru.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Give the user programmatic access&lt;br&gt;
From Security Credential dashboard, choose Access Key dropdown, then click on Create New Access Key;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u4t9rw7dv4ghl286pjw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u4t9rw7dv4ghl286pjw.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the access key and secret key&lt;br&gt;
It is important to note that once you exit out of the dialog box, you can not access that key again, so you need to copy the key or download and save the key. Though, you can always create a new one if lost;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs225pz7o0r8zcw3zuh52.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs225pz7o0r8zcw3zuh52.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Configure The AWS CLI&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open Terminal Window&lt;br&gt;
Try to test if aws is properly installed by running this command &lt;br&gt;
&lt;code&gt;aws --version&lt;/code&gt;&lt;br&gt;
If the display is different from example below, know that you need to re-install to avoid further complication;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi56nzwrlxnngtj4iq344.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi56nzwrlxnngtj4iq344.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run configure command&lt;br&gt;
To configure run &lt;code&gt;aws configure&lt;/code&gt;&lt;br&gt;
Fill the Access Key ID and Secret Access Key.&lt;br&gt;
If not sure of Default region name, just leave it as it is by pressing Enter button.&lt;br&gt;
For output format, I advice to use JSON, press Enter button.&lt;br&gt;
Yeah, that simple, we are done with configuring AWS.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqz0s3pstrcoz7acw2kt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqz0s3pstrcoz7acw2kt.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
However, if you need additional info on AWS CLI install and configure, I recommend this &lt;a href="https://www.youtube.com/watch?v=PWAnY-w1SGQ&amp;amp;t=347s" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2.0 VPC - Virtual Private Cloud&lt;/strong&gt;&lt;br&gt;
To create my cluster VPC with public and private subnets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the AWS CloudFormation console, type CloudFormation inside the service box.&lt;/li&gt;
&lt;li&gt;Choose Create stack.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1k4pjejf6zndsvp9prvg.PNG" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Select template is ready and, Amazon S3 URL. Then Paste the following URL into the text area and choose Next:
&lt;code&gt;https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/amazon-eks-vpc-private-subnets.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjxhi4dou5vlg12k6r9l.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjxhi4dou5vlg12k6r9l.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the Specify Stack Details page, fill out the following and Choose Next:&lt;/li&gt;
&lt;li&gt;Stack name: I choose a stack name for my AWS CloudFormation stack. For example, I call it ruralx-vpc.&lt;/li&gt;
&lt;li&gt;VpcBlock: Choose a CIDR range for my VPC. Each worker node, pod, and load balancer that I deploy is assigned an IP address from this block. The default value provides enough IP addresses for most implementations, but if it doesn't, then I can change it. For more information, see VPC and subnet sizing in the Amazon VPC User Guide. I can also add additional CIDR blocks to the VPC once it's created.&lt;/li&gt;
&lt;li&gt;PublicSubnet01Block: Specify a CIDR block for public subnet 1. The default value provides enough IP addresses for most implementations, but if it doesn't, then I can change it.&lt;/li&gt;
&lt;li&gt;PublicSubnet02Block: Specify a CIDR block for public subnet 2. The default value provides enough IP addresses for most implementations, but if it doesn't, then I can change it.&lt;/li&gt;
&lt;li&gt;PrivateSubnet01Block: Specify a CIDR block for private subnet 1. The default value provides enough IP addresses for most implementations, but if it doesn't, then I can change it.&lt;/li&gt;
&lt;li&gt;PrivateSubnet02Block: Specify a CIDR block for private subnet 2. The default value provides enough IP addresses for most implementations, but if it doesn't, then I can change it.&lt;/li&gt;
&lt;li&gt;(Optional) On the Options page, tag your stack resources. Choose Next.&lt;/li&gt;
&lt;li&gt;On the Review page, choose Create.&lt;/li&gt;
&lt;li&gt;When my stack is created, select it in the console and choose Outputs.&lt;/li&gt;
&lt;li&gt;Record the Security Groups value for the security group that was created. When I add nodes to my cluster, I must specify the ID of the security group. The security group is applied to the elastic network interfaces that are created by Amazon EKS in my subnets that allows the control plane to communicate with my nodes. These network interfaces have Amazon EKS in their description.&lt;/li&gt;
&lt;li&gt;Record the VpcId for the VPC that was created. I need this when I launch my node group template.&lt;/li&gt;
&lt;li&gt;Record the SubnetIds for the subnets that were created and whether I created them as public or private subnets. When I add nodes to my cluster, I must specify the IDs of the subnets that I want to launch the nodes into.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3.0 Terraform&lt;/strong&gt;&lt;br&gt;
The purpose of the Terraform section is to create all of the AWS cloud services I'll need from an environment/infrastructure perspective to run the ruralx application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create S3 Bucket To Store TFSTATE Files&lt;/strong&gt;&lt;br&gt;
Here, I will create an S3 bucket that will be used to store Terraform state files.&lt;br&gt;
I created main.tf file inside a directory, write these code;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
  bucket = "terraform-state-rurlax"
  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Terraform &lt;code&gt;main.tf&lt;/code&gt; will do these:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the S3 bucket in the us-east-1 region&lt;/li&gt;
&lt;li&gt;Ensure that version enabling is set to &lt;code&gt;True&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Utilize AES256 encryption&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Create the bucket by running the following:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;/code&gt; - To initialize the working directory and pull down the provider&lt;br&gt;
&lt;code&gt;terraform plan&lt;/code&gt; - To go through a "check" and confirm the configurations are valid&lt;br&gt;
&lt;code&gt;terraform apply&lt;/code&gt; - To create the resource&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create an Elastic Container Registry&lt;/strong&gt;&lt;br&gt;
The idea is to create a repository to store the Docker image that I created for the ruralx app.&lt;br&gt;
Then, I add to the &lt;code&gt;main.tf&lt;/code&gt; this;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    bucket = "terraform-state-ruralx"
    key    = "ecr-terraform.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_ecr_repository" "ruralx-ecr-repo" {
  name                 = var.ruralx-ecr
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, create &lt;code&gt;variables.tf&lt;/code&gt; file inside the directory, basically to store the env of the repo. I then write this code;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable ruralx-ecr {
  type        = string
  default     = "ruralx"
  description = "ECR repo to store a Docker image"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, that the Terraform &lt;code&gt;main.tf&lt;/code&gt; will do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a Terraform backend to store the &lt;code&gt;.tfstate&lt;/code&gt; in an S3 bucket.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;aws_ecr_repository&lt;/code&gt; Terraform resource to create a new respository.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Create the bucket by running the following:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;/code&gt; - To initialize the working directory and pull down the provider&lt;br&gt;
&lt;code&gt;terraform plan&lt;/code&gt; - To go through a "check" and confirm the configurations are valid&lt;br&gt;
&lt;code&gt;terraform apply&lt;/code&gt; - To create the resource&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create An EKS Cluster and IAM Role/Policy&lt;/strong&gt;&lt;br&gt;
I am going to create EKS cluster here, writing the following code;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    bucket = "terraform-state-ruralx"
    key    = "ecr-terraform.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "terraform_state" {
  bucket = "terraform-state-ruralx"
  versioning {
    enabled = true
  }

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

resource "aws_ecr_repository" "ruralx-africa-ecr-repo" {
  name                 = var.ruralx-africa-ecr
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}

terraform {
  backend "s3" {
    bucket = "terraform-state-ruralx"
    key    = "eks-terraform-workernodes.tfstate"
    region = "us-east-1"
  }
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}


# IAM Role for EKS to have access to the appropriate resources
resource "aws_iam_role" "eks-iam-role" {
  name = "ruralx-eks-iam-role"

  path = "/"

  assume_role_policy = &amp;lt;&amp;lt;EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

}

## Attach the IAM policy to the IAM role
resource "aws_iam_role_policy_attachment" "AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.eks-iam-role.name
}
resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly-EKS" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.eks-iam-role.name
}

## Create the EKS cluster
resource "aws_eks_cluster" "ruralx-eks" {
  name = "ruralx-cluster"
  role_arn = aws_iam_role.eks-iam-role.arn

  vpc_config {
    subnet_ids = [var.subnet_id_1, var.subnet_id_2]
  }

  depends_on = [
    aws_iam_role.eks-iam-role,
  ]
}

## Worker Nodes
resource "aws_iam_role" "workernodes" {
  name = "eks-node-group-example"

  assume_role_policy = jsonencode({
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
    Version = "2012-10-17"
  })
}

resource "aws_iam_role_policy_attachment" "AmazonEKSWorkerNodePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
  role       = aws_iam_role.workernodes.name
}

resource "aws_iam_role_policy_attachment" "AmazonEKS_CNI_Policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
  role       = aws_iam_role.workernodes.name
}

resource "aws_iam_role_policy_attachment" "EC2InstanceProfileForImageBuilderECRContainerBuilds" {
  policy_arn = "arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilderECRContainerBuilds"
  role       = aws_iam_role.workernodes.name
}

resource "aws_iam_role_policy_attachment" "AmazonEC2ContainerRegistryReadOnly" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.workernodes.name
}

resource "aws_eks_node_group" "worker-node-group" {
  cluster_name    = aws_eks_cluster.ruralx-eks.name
  node_group_name = "ruralx-workernodes"
  node_role_arn   = aws_iam_role.workernodes.arn
  subnet_ids      = [var.subnet_id_1, var.subnet_id_2]
  instance_types = ["t3.xlarge"]

  scaling_config {
    desired_size = 1
    max_size     = 1
    min_size     = 1
  }

  depends_on = [
    aws_iam_role_policy_attachment.AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.AmazonEKS_CNI_Policy,
    #aws_iam_role_policy_attachment.AmazonEC2ContainerRegistryReadOnly,
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "subnet_id_1" {
  type = string
  default = "subnet-05f2a43d392934382"
}

variable "subnet_id_2" {
  type = string
  default = "subnet-0086dd63b54f54812"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the EKS Cluster by running the following:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;terraform plan&lt;/code&gt; - To go through a "check" and confirm the configurations are valid&lt;br&gt;
&lt;code&gt;terraform apply&lt;/code&gt; - To create the resource&lt;/p&gt;

&lt;p&gt;If you want to get more familiar with terraform, you can start here &lt;a href="https://www.youtube.com/watch?v=SLB_c_ayRMo&amp;amp;t=4404s" rel="noopener noreferrer"&gt;Click this link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.0 Docker&lt;/strong&gt;&lt;br&gt;
Here, we plan for the application requirements, code, build, and unit test the application.&lt;br&gt;
I will assume all these phases been taken care of as DevOps team not solely responsible for these, but rather work with larger team of both development and operation of an organization. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create The Docker Image for the ruralx app&lt;/strong&gt;&lt;br&gt;
The purpose of this is to create a Docker image from the app's source code that the organization have, containerize it, and store the container inside a container repository. Here, I'll use AWS ECR repo container.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside the app source code's root directory, create &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3hp415gd1xwrxmlkbef.PNG" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Open the Dockerfile, then define the instruction, this depend on base image and others, you can consider this as an;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# syntax=docker/dockerfile:1
FROM node:10.16.1-alpine
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;To create the Docker image, you'll run the following command: &lt;code&gt;docker build -t ruralx:latest .&lt;/code&gt;
The -t is for the tag (the name) of the Docker image and the . is telling the Docker CLI that the Dockerfile is in the current directory.&lt;/li&gt;
&lt;li&gt;After the Docker image is created, run the following command to confirm the Docker image is on your machine; &lt;code&gt;docker image ls&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Run The Docker Image Locally&lt;/strong&gt;&lt;br&gt;
Now that the Docker image is created, you can run the container locally just to confirm it'll work and not crash.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To run the Docker container, run the following command: &lt;code&gt;docker run -tid ruralx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To confirm the Docker container is running, run the following command: &lt;code&gt;docker container ls&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Log Into AWS ECR Repository&lt;/strong&gt;&lt;br&gt;
The idea is to push image To ECR&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Log in to ECR with AWS CLI&lt;br&gt;
&lt;code&gt;aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/ruralx&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag The Docker image&lt;br&gt;
Tag the Docker image &lt;code&gt;docker tag ruralx 1XX9-6XXX-6XX7.dkr.ecr.us-east-1.amazonaws.com&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push The Docker Image To ECR&lt;br&gt;
Push the Docker image to ECR &lt;code&gt;docker push 1XX9-6XXX-6XX7.dkr.ecr.us-east-1.amazonaws.com/ruralx&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to Docker documentation, &lt;a href="https://www.youtube.com/watch?v=bhBSlnQcq2k&amp;amp;t=9615s" rel="noopener noreferrer"&gt;Click here&lt;/a&gt; for another useful resource from Nelson(YouTube channel; Amigoscode)&lt;/p&gt;

&lt;p&gt;To learn more, catch me up on the second part!&lt;br&gt;
Read the &amp;gt;&amp;gt;&amp;gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading! Happy Cloud Computing!&lt;/p&gt;

&lt;p&gt;I will love to connect with you on &lt;a href="https://www.linkedin.com/in/deoluoyinlola/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>aws</category>
    </item>
    <item>
      <title>How I build Full-Stack Reactjs App using AWS Amplify, GraphQL API</title>
      <dc:creator>Adeolu Oyinlola</dc:creator>
      <pubDate>Tue, 10 May 2022 12:34:54 +0000</pubDate>
      <link>https://dev.to/deoluoyinlola/how-i-build-full-stack-reactjs-app-using-aws-amplify-graphql-api-2ac7</link>
      <guid>https://dev.to/deoluoyinlola/how-i-build-full-stack-reactjs-app-using-aws-amplify-graphql-api-2ac7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Learning Objective&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This tutorial will walk you through the step-by-step instructions to build your first React application.&lt;/li&gt;
&lt;li&gt;Hosting: Build and host a React application on the AWS.&lt;/li&gt;
&lt;li&gt;Database and Storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
To effectively follow along, you will need the following set up;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React basis&lt;/li&gt;
&lt;li&gt;AWS account&lt;/li&gt;
&lt;li&gt;Github account&lt;/li&gt;
&lt;li&gt;Text-editor, preferably VS Code&lt;/li&gt;
&lt;li&gt;Install Nodejs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Tutorial Structure&lt;/strong&gt;&lt;br&gt;
For easy understanding, I will break this tutorial into four sequential order as follow;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Develop React App&lt;/strong&gt;&lt;br&gt;
Here, we will create a React application and deploy it to the cloud using AWS Amplify’s web hosting service.&lt;br&gt;
A new React application and push it to a GitHub repository. Then, we will connect the repository to AWS Amplify web hosting and deploy it to a globally available content delivery network (CDN). Next, we’ll demonstrate continuous deployment capabilities by making changes to the React application and push a new version to the master branch which will automatically kick off a new deployment.&lt;br&gt;
AWS Amplify provides a Git-based CI/CD workflow for building, deploying, and hosting single page web applications or static sites with serverless backends.&lt;br&gt;
Let's get to work;&lt;br&gt;
1.1) Create a React application&lt;br&gt;
The easiest way to create a React application is by using the command create-react-app. From the Terminal&lt;br&gt;
&lt;code&gt;npx create-react-app awsapp&lt;br&gt;
cd awsapp&lt;br&gt;
npm start&lt;/code&gt;&lt;br&gt;
Perhaps, you encountered any issue regarding global installation, first run this command before continue with the above;&lt;br&gt;
&lt;code&gt;npm uninstall -g create-react-app&lt;br&gt;
npx clear-npx-cache&lt;br&gt;
npx create-react-app my-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;1.2) Initialize a GitHub repository&lt;br&gt;
Create a new GitHub repo for your app&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzcbnmgg5nf5a7eezjsf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzcbnmgg5nf5a7eezjsf.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Initialize git and push the app to the new GitHub repo using the following commands accordingly in your command line interface:&lt;br&gt;
&lt;code&gt;git init&lt;br&gt;
git remote add origin git@github.com:username/reponame.git&lt;br&gt;
git add .&lt;br&gt;
git commit -m “initial commit”&lt;br&gt;
git push origin master&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;1.3) Now, move into AWS Management Console &lt;a href="https://console.aws.amazon.com/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;br&gt;
Then type "Amplify" in the search bar and select AWS Amplify to open the service console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ete0p741w6il0ymak49.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ete0p741w6il0ymak49.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1.4) From the AWS Amplify service console, select "Get Started" under Deploy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, select GitHub as the repository service and select Continue.&lt;/li&gt;
&lt;li&gt;Follow with authenticate with GitHub and return to the Amplify console. &lt;/li&gt;
&lt;li&gt;Choose the repository and master branch you created earlier, then select Next.&lt;/li&gt;
&lt;li&gt;Accept the default build settings and select Next.&lt;/li&gt;
&lt;li&gt;Review the final details and select Save and Deploy.
AWS Amplify will now build your source code and deploy your app at https://...amplifyapp.com.&lt;/li&gt;
&lt;li&gt;Once the build completes, select the thumbnail to see your web app up and running live. &lt;/li&gt;
&lt;li&gt;Once the build completes, select the thumbnail to see your web app up and running live.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1.5) Let's make some changes to the code.&lt;br&gt;
In this step, you will make some changes to the code using your text editor and push the changes to the master branch of your app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edit src/App.js with the code below and save.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;header className="App-header"&amp;gt;
        &amp;lt;img src={logo} className="App-logo" alt="logo" /&amp;gt;
        &amp;lt;h1&amp;gt;Hello from V2&amp;lt;/h1&amp;gt;
      &amp;lt;/header&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then run these command to push to Github;
&lt;code&gt;git add .
git commit -m “changes for v2”
git push origin master&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have successfully deployed a React application in the AWS Cloud by integrating with GitHub and using AWS Amplify. With AWS Amplify, you can continuously deploy your application in the cloud and host it on a globally-available CDN.&lt;/p&gt;

&lt;p&gt;Next, we will create a local version of the app to continue development and add new features.&lt;/p&gt;

&lt;p&gt;1.6) Amplify CLI&lt;br&gt;
The Amplify Command Line Interface (CLI) is a unified toolchain to create AWS cloud services for your app, following a simple guided workflow. Let’s go ahead and install the Amplify CLI using the Command Prompt (Windows) or the Terminal (macOS). NOTE: this command can be run in any directory in your Command Prompt/Terminal as the “-g” indicates the binary will be installed globally on your system.&lt;br&gt;
&lt;code&gt;npm install -g @aws-amplify/cli&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure Amplify CLI
Amazon Identity and Access Management enables you to manage users and user permissions in AWS. The CLI uses IAM to create and manage services programmatically on your behalf via the CLI.
&lt;code&gt;amplify configure&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Let's now initialize the Amplify app
By deploy a back end and initialize the backend environment locally.
In the Amplify console, click on Backend environments and click on click on Get started. Wait for the back end to be deployed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Backend environment tab, click on Open admin UI&lt;/p&gt;

&lt;p&gt;Go back to the Amplify Console Backend environments tab and open the Local setup instructions. Copy the command to your clipboard and open the terminal on your computer.&lt;/p&gt;

&lt;p&gt;For the remaining and full documentation &lt;a href="https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/" rel="noopener noreferrer"&gt;check&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pls, dont forget to destroy all resources used;&lt;br&gt;
&lt;code&gt;amplify delete&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Connect with on &lt;a href="https://www.linkedin.com/in/deoluoyinlola/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>aws</category>
      <category>graphql</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to dockerize Reactjs app</title>
      <dc:creator>Adeolu Oyinlola</dc:creator>
      <pubDate>Tue, 26 Apr 2022 14:58:10 +0000</pubDate>
      <link>https://dev.to/deoluoyinlola/how-to-dockerize-reactjs-app-10p1</link>
      <guid>https://dev.to/deoluoyinlola/how-to-dockerize-reactjs-app-10p1</guid>
      <description>&lt;p&gt;In this post, sequel to the first part of this series, we are going to dockerize Reactjs application.&lt;br&gt;
First, let's have a quick overview of this post;&lt;br&gt;
1.) What and Why Docker?&lt;br&gt;
2.) What are the Requirements?&lt;br&gt;
3.) What are the steps and processes involved?&lt;br&gt;
While the end goal is to dockerize our app and push that image to Amazon ECR and run that app on Amazon ECS. Deployment and DevOps on AWS ECS will be well explained in the third part.&lt;/p&gt;
&lt;h2&gt;
  
  
  1.) What and Why Docker?
&lt;/h2&gt;

&lt;p&gt;Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. Think of it as best alternative to virtual machine.&lt;/p&gt;

&lt;p&gt;Why docker?&lt;br&gt;
There are many reasons to use docker but I will just mention few; a.) Modern applications come with loads of dependencies, and having to install everything on every environment you want to run it on, or worse yet, run it on a shared environment with other apps perhaps requiring other versions of the same libraries, is complicated. With your app residing on a docker image all you do is pull the image and run it, docker handles the rest. b.) Docker reduces the need for more infrastructure resources for development and the container created for individual processes can be shared with other apps with instances of these containerized apps using less memory compared to virtual machines – it makes the development and deployment process more cost-effective.&lt;/p&gt;
&lt;h2&gt;
  
  
  2.) What are the Requirements;
&lt;/h2&gt;

&lt;p&gt;a.) Existing code/app that you would like to containerize.&lt;br&gt;
If you are starting from scratch;&lt;br&gt;
Check &lt;em&gt;SETTING UP CLIENT SIDE&lt;/em&gt; of my previous post &lt;a href="https://dev.to/deoluoyinlola/how-to-develop-mern-stack-app-4mke"&gt;Here&lt;/a&gt; or download this repo from my github&lt;a href="https://github.com/deoluoyinlola/dockerize-and-deploy-react-app-on-aws" rel="noopener noreferrer"&gt;Here&lt;/a&gt; &lt;br&gt;
b.) Code editor, preferably VS Code&lt;br&gt;
c.) Docker Desktop Install&lt;br&gt;
&lt;code&gt;$ sudo apt-get update&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ sudo apt-get install docker-ce docker-ce-cli containerd.io&lt;/code&gt;&lt;br&gt;
or follow the official documentation&lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;br&gt;
d.) Docker file (to build the Docker image)&lt;/p&gt;
&lt;h2&gt;
  
  
  3.) What are the steps and processes involved?
&lt;/h2&gt;

&lt;p&gt;After we get all the requirements ready, we can now further to Dockerize React App and later to AWS ECS for Production, where we need to follow the steps below:&lt;br&gt;
1.) Firstly, set up the reactjs source code.&lt;br&gt;
Then, we need to Dockerize the React app.&lt;br&gt;
2.) Create a Dockerfile and docker-compose.yml file in the root of the app.&lt;br&gt;
3.) Populate the Dockerfile and docker-compose.yml with with set of instruction and argument.&lt;br&gt;
4.) Run build command.&lt;br&gt;
5.) Push the docker image to a repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1.) set up the reactjs source code.&lt;/strong&gt;&lt;br&gt;
Using exiting source code or &lt;code&gt;npx create-react-app my-app&lt;/code&gt;&lt;br&gt;
Run &lt;code&gt;npm start&lt;/code&gt; command to run dev the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.2.) Dockerize React app.&lt;/strong&gt;&lt;br&gt;
I assume by now, you already have react app and docker installed on your local machine.&lt;br&gt;
Now let's create a &lt;code&gt;Dockerfile&lt;/code&gt; and &lt;code&gt;docker-compose.yml&lt;/code&gt; in the root of the app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnvz91fq234y5hlglwmq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnvz91fq234y5hlglwmq.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
In this file structure, the three files to focus on are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;docker-compose.yml&lt;/li&gt;
&lt;li&gt;.dockerignore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3.3.) Populate the Dockerfile and docker-compose.yml&lt;/strong&gt;&lt;br&gt;
Actually we are doing following with our dockerfile:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloading a base image from dockerhub&lt;/li&gt;
&lt;li&gt;Defining a working directory for our container&lt;/li&gt;
&lt;li&gt;Copying package.json file and place it in container working dir&lt;/li&gt;
&lt;li&gt;Installing our npm dependencies&lt;/li&gt;
&lt;li&gt;Copying rest of the project files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dockerfile content;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# get the base node image
FROM node:alpine as builder

# set the working dir for container
WORKDIR /app

# copy the json file first
COPY ./package.json /app

# install npm dependencies
RUN npm install

# copy other project files
COPY . .

# build the folder
CMD [ "npm", "start" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we have a dockerfile with all instructions that we need in order to create our docker image. Let's now define and create our container using docker-compose.yml file.&lt;/p&gt;

&lt;p&gt;docker-compose.yml content;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'
services:          
    app:
        build: .     
        container_name: frontend
        ports:
            - "3000:3000"
        image: app:react
        volumes: 
            - .:/app
            - /app/node_modules
        command: npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;.dockerignore content;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
npm-debug.log

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.4.) Run build command.&lt;/strong&gt;&lt;br&gt;
Now let's run it locally to see if it works.&lt;br&gt;
First we build our docker image.&lt;br&gt;
&lt;code&gt;docker build --tag react .&lt;/code&gt;&lt;br&gt;
Then we run it&lt;br&gt;
&lt;code&gt;docker run -p 3000:3000 -d react&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detached mode, shown by the option -d, means that a Docker container runs in the background. It does not receive input or display output.
Now your React app should be available again at [&lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;]
Now, in order to check our production environment locally let's run following command:
&lt;code&gt;docker-compose up&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are finally done with dockerizing your application and also succeeded in moving to a microservices architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.5.) Push the docker image to a repository.&lt;/strong&gt;&lt;br&gt;
Next, we push the docker image to a repository. Let's use a dockerhub public repository through the command line or using Docker Desktop. Create a username and repo name in all the files.&lt;br&gt;
Now we can push it to our dockerhub public repository.&lt;br&gt;
&lt;code&gt;docker push &amp;lt;your username&amp;gt;/&amp;lt;reponame&amp;gt; --all-tags&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now the image is pushed to dockerhub public repository and accessible to everyone. We are going to be pulling it on our ec2 instance next.&lt;br&gt;
We have come to the end of &lt;strong&gt;How to dockerize Reactjs app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next; Catch up with me on How to implement DevOps Approach practically with a webapp project from &lt;a href="https://dev.to/deoluoyinlola"&gt;my next post&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;Connect with me: &lt;a href="https://www.linkedin.com/in/deoluoyinlola/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>aws</category>
      <category>react</category>
      <category>containerize</category>
    </item>
    <item>
      <title>How to develop MERN stack app</title>
      <dc:creator>Adeolu Oyinlola</dc:creator>
      <pubDate>Wed, 20 Apr 2022 18:14:53 +0000</pubDate>
      <link>https://dev.to/deoluoyinlola/how-to-develop-mern-stack-app-4mke</link>
      <guid>https://dev.to/deoluoyinlola/how-to-develop-mern-stack-app-4mke</guid>
      <description>&lt;p&gt;Hello guys,&lt;br&gt;
The question I intend to answer with this tutorial is; how do I develop a MERN Stack app? So, by the end of this tutorial you will be able to develop MERN app in CRUD(create, Read, Update and Delete) form.&lt;/p&gt;

&lt;p&gt;I will assume you have some basic understanding of MERN stack as one of the most relevant app development stack in the world which is growing fast every day, use by many developers around the globe with a huge community support.&lt;br&gt;
Simply put, a MERN stack is a combination of four technologies: Mongo DB, Express JS, React JS, and Node JS. More importantly, MERN Stack is combination of open source database and Javascript library &amp;amp; runtime environment. Each letter of this acronym means;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mongo DB: A document-based open-source database, that provides scalability and flexibility.&lt;/li&gt;
&lt;li&gt;Express JS: A structured base designed to develop web applications and APIs.&lt;/li&gt;
&lt;li&gt;React JS: A Javascript Front-end library for building user interfaces. Maintained by Facebook.&lt;/li&gt;
&lt;li&gt;Node JS: A javascript runtime environment built on Chrome’s V8 JS engine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatively, you might come across another acronym very similar to MERN, called MEAN, there is, it’s almost the same, but the difference is that we use Angular instead of React.&lt;/p&gt;

&lt;p&gt;Note that this tutorial is the first part of MERN stack beginner’s series(part 2 - How to Dockerize MERN stack app in AWS EC2 &amp;amp; part 3 - How to Deploy MERN stack app on AWS ECS, it is advised to follow this sequentially. Also, find the links to the remaining part at the end this tutorial). So, I’m going to teach you how to develop a simple MERN stack Application.&lt;/p&gt;

&lt;p&gt;I believe you will agree with me that, the best way to learn anything is by doing it. So, I will guide you into developing this simple app using MERN stack, here we’re going to create a book rating web app called &lt;strong&gt;bukrate&lt;/strong&gt; in CRUD (Create, Read, Update and Delete) form. For proper understanding, I will break this tutorial into four sections; Requirements, Setting up server side, Setting up client side and Integrating server &amp;amp; client side&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REQUIREMENTS;&lt;/strong&gt;&lt;br&gt;
Basic requirement includes;&lt;br&gt;
a)basic javascript, HTML, CSS&lt;br&gt;
b)code editor; preferably VS Code&lt;br&gt;
c)setup development environment on your laptop/desktop&lt;br&gt;
d)install browser, preferably google chrome&lt;br&gt;
e)install nodejs&lt;br&gt;
f)setup MongoDB Atlas&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.0 SETTING UP SERVER SIDE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this section, we’re going to create the server of our application, where we’re going to create a RESTful API following the steps below.&lt;br&gt;
Firstly, we create an empty directory that will be the root of our system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ mkdir bukrate-app
$ cd bukrate-app

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above directory represent folder for our project - bukrate app. Inside this bukrate-app, let’s now create another empty folder called server that will be our backend folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ mkdir server
$ cd server

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow by creating our package.json inside this server folder.&lt;br&gt;
&lt;em&gt;So, what’s a package.json and how can we create one?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;package.json&lt;/em&gt; file is the heart of Node. js system. It is the manifest file of any Node. js project and contains the metadata of the project which is required before publishing to NPM, and also defines functional attributes of a project that npm uses to install dependencies, run scripts, and identify the entry point to our package.&lt;/p&gt;

&lt;p&gt;To create a package.json you need a Package Manager, preferably choose NPM (Node Package Manager) which we will be using in this tutorial. Feel free to use what you prefer say alternatively YARN&lt;/p&gt;

&lt;p&gt;Now we can create our file using NPM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
$ npm init -y

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While creating this file, you’ll be asked questions related to your project. If you’d like to keep the default provided by NPM, you can just type enter until the end.&lt;br&gt;
After that, you can find the file in the server folder. Then we'll able to install our dependencies. Check out the list and uses of our dependencies;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Express: It’s the server framework (The E in MERN).&lt;/li&gt;
&lt;li&gt;Body Parser: Responsible to get the body off of network requests.&lt;/li&gt;
&lt;li&gt;Nodemon: Restart the server when it sees changes (for a better dev experience).&lt;/li&gt;
&lt;li&gt;Cors: Package for providing a Connect/Express middleware that can be used to enable CORS with various options.&lt;/li&gt;
&lt;li&gt;Mongoose: It’s an elegant MongoDB object modeling for node.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, install all the dependencies by running this command;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install express body-parser cors mongoose nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immediately, after successfully create these dependencies, you will found additional two new folder node_modules and package-lock.json. With these two files, your project can be interpreted.&lt;/p&gt;

&lt;p&gt;From here on, we can now create NodeJS file(at the root of server folder) called index.js which contain all the logic for our API/server as follow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const mongoose = require('mongoose')
const app = express()
const apiPort = 3000

app.use(bodyParser.urlencoded({ extended: true }))
app.use(cors())
app.use(bodyParser.json())

app.get('/', (req, res) =&amp;gt; {
    res.send('Hello World!')
})

app.listen(apiPort, () =&amp;gt; console.log(`Server running on port ${apiPort}`))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3o0a56r3er4zq1m65hpp.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3o0a56r3er4zq1m65hpp.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
To start the application you just need to run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the message “Server running on port 3000” it means that everything you’ve done until now it’s correct.&lt;br&gt;
Then open a browser and type localhost:3000, you’ll see the message “Hello World”.&lt;/p&gt;

&lt;p&gt;The good news is, you’re able to see your server running. Next is to set up database for our application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.1 Setup Cloud MongoDB&lt;/strong&gt;&lt;br&gt;
We need to either install MongoDB on the computer locally or use the cloud database. For this project we use the cloud - Atlas;&lt;br&gt;
This is simple, you can just follow the step provided by MongoDB documentation here. &lt;a href="https://www.mongodb.com/docs/launch-manage/" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt; &lt;br&gt;
In an attempt not to make this tutorial unnecessarily long, I will not spend much time on setting up the database, but will try to highlight each step, also this tutorial can be of great help &lt;a href="https://www.youtube.com/watch?v=bxsemcrY4gQ&amp;amp;t=4s" rel="noopener noreferrer"&gt;Link&lt;/a&gt;;&lt;br&gt;
a)sign up &lt;a href="https://cloud.mongodb.com/" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;br&gt;
b)choose Atlas&lt;br&gt;
c)build cluster&lt;br&gt;
d)named the cluster if choose to&lt;br&gt;
e)build database; - by clicking on the collection. - Add My Own Data. - Add Database and Collection name &lt;br&gt;
f)Setup Database Access; - to add user&lt;br&gt;
g)connect to the app database; - connect to your application, - add method.&lt;br&gt;
With this, we’ve just created our database with these steps.&lt;/p&gt;

&lt;p&gt;Now, let's return back to our javascript code, we need to create a connection from our server using the Mongoose library.&lt;/p&gt;

&lt;p&gt;Now, let's update the main Nodejs file server/index.js we have something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const mongoose = require('mongoose')
const app = express()

//connect to mongodb
const dbURI = 'mongodb+srv://&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@bukrate-app.lfqmj.mongodb.net/bukrate?retryWrites=true&amp;amp;w=majority';

mongoose.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() =&amp;gt; app.listen(PORT, () =&amp;gt; console.log(`Server Running on Port: http://localhost:${PORT}`)))
  .catch((error) =&amp;gt; console.log(`${error} did not connect`));

const apiPort = 3000

app.use(bodyParser.urlencoded({ extended: true }))
app.use(cors())
app.use(bodyParser.json())

app.get('/', (req, res) =&amp;gt; {
    res.send('Hello World!')
})

app.listen(apiPort, () =&amp;gt; console.log(`Server running on port ${apiPort}`))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should notice I have added like five line after the comment &lt;em&gt;//connect to mongodb&lt;/em&gt;&lt;br&gt;
Because of this update, let's restart the application to see the effect, then you need to close and open a new one. This is where nodemon will start its working, it’s going to restart the server whenever it sees changes in any file of our project. So, let’s do this by running the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nodemon index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje1zek1lqf6sepou395o.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje1zek1lqf6sepou395o.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.1.1. Creating Book’s Schema&lt;/strong&gt;&lt;br&gt;
We need to create an entity called book that should be composed of the name of a book. For this, we just need to know the name of the book and the author of the book, and to add an important information, the rating.&lt;/p&gt;

&lt;p&gt;Let’s go ahead and create a folder called models and add a file called rate.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir models
$ cd models
$ touch rate.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose')
const Schema = mongoose.Schema

const rateSchema = new Schema(
    {
        name: { type: String, required: true },
        author: { type: String, required: true },
        rating: { type: Number, required: true },
    },
    { timestamps: true },
)

const Rate = mongoose.model('Rate', rateSchema);
module.exports = Rate;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1.2. Getting and Saving Data&lt;/strong&gt;&lt;br&gt;
Here, we’ll create all the CRUD operations and create our REST endpoints. Let’s create two more folders inside the server: routes and controllers. In the route folder, let’s create the file rate-router.js and in the controller folder, rate-ctrl.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir routes controllers
$ touch routes/rate-router.js
$ touch controllers/rate-ctrl.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Rate = require('../models/rate')

createRate = (req, res) =&amp;gt; {
    const body = req.body

    if (!body) {
        return res.status(400).json({
            success: false,
            error: 'You must provide a rate',
        })
    }

    const rate = new Rate(body)

    if (!rate) {
        return res.status(400).json({ success: false, error: err })
    }

    rate
        .save()
        .then(() =&amp;gt; {
            return res.status(201).json({
                success: true,
                id: rate._id,
                message: 'rate created!',
            })
        })
        .catch(error =&amp;gt; {
            return res.status(400).json({
                error,
                message: 'Rate not created!',
            })
        })
}

updateRate = async (req, res) =&amp;gt; {
    const body = req.body

    if (!body) {
        return res.status(400).json({
            success: false,
            error: 'You must provide a body to update',
        })
    }

    Rate.findOne({ _id: req.params.id }, (err, rate) =&amp;gt; {
        if (err) {
            return res.status(404).json({
                err,
                message: 'Rate not found!',
            })
        }
        rate.name = body.name
        rate.author = body.time
        rate.rating = body.rating
        rate
            .save()
            .then(() =&amp;gt; {
                return res.status(200).json({
                    success: true,
                    id: rate._id,
                    message: 'Rate updated!',
                })
            })
            .catch(error =&amp;gt; {
                return res.status(404).json({
                    error,
                    message: 'Rate not updated!',
                })
            })
    })
}

deleteRate = async (req, res) =&amp;gt; {
    await Rate.findOneAndDelete({ _id: req.params.id }, (err, rate) =&amp;gt; {
        if (err) {
            return res.status(400).json({ success: false, error: err })
        }

        if (!rate) {
            return res
                .status(404)
                .json({ success: false, error: `Rate not found` })
        }

        return res.status(200).json({ success: true, data: rate })
    }).catch(err =&amp;gt; console.log(err))
}

getRateById = async (req, res) =&amp;gt; {
    await Rate.findOne({ _id: req.params.id }, (err, rate) =&amp;gt; {
        if (err) {
            return res.status(400).json({ success: false, error: err })
        }

        if (!rate) {
            return res
                .status(404)
                .json({ success: false, error: `Rate not found` })
        }
        return res.status(200).json({ success: true, data: rate })
    }).catch(err =&amp;gt; console.log(err))
}

getRates = async (req, res) =&amp;gt; {
    await Rate.find({}, (err, rates) =&amp;gt; {
        if (err) {
            return res.status(400).json({ success: false, error: err })
        }
        if (!rates.length) {
            return res
                .status(404)
                .json({ success: false, error: `Rate not found` })
        }
        return res.status(200).json({ success: true, data: rates })
    }).catch(err =&amp;gt; console.log(err))
}

module.exports = {
    createRate,
    updateRate,
    deleteRate,
    getRates,
    getRateById,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')

const RateCtrl = require('../controllers/rate-ctrl')

const router = express.Router()

router.post('/rate', RateCtrl.createRate)
router.put('/rate/:id', RateCtrl.updateRate)
router.delete('/rate/:id', RateCtrl.deleteRate)
router.get('/rate/:id', RateCtrl.getRateById)
router.get('/rates', RateCtrl.getRates)

module.exports = router
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, let’s add the router in our server/index.js file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const mongoose = require('mongoose')
const Rate = require('./models/rate')
const app = express()

//connect to mongodb
const dbURI = 'mongodb+srv://&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@bukrate-app.lfqmj.mongodb.net/bukrate?retryWrites=true&amp;amp;w=majority';

mongoose.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() =&amp;gt; app.listen(PORT, () =&amp;gt; console.log(`Server Running on Port: http://localhost:${PORT}`)))
  .catch((error) =&amp;gt; console.log(`${error} did not connect`));


const rateRouter = require('./routes/rate-router')
const apiPort = 3000

app.use(bodyParser.urlencoded({ extended: true }))
app.use(cors())
app.use(bodyParser.json())

app.get('/', (req, res) =&amp;gt; {
    res.send('Hello World!')
})

app.use('/api', rateRouter)

app.listen(apiPort, () =&amp;gt; console.log(`Server running on port ${apiPort}`))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1.2.1 Protecting Your Database&lt;/strong&gt;&lt;br&gt;
Up till here, there shouldn't be any issue with our application. But if you want to test the application you can use either Postman or Robo 3T. These tools help us in verify our application workings (You can find how to from the documentation on their websites or other resources on google). &lt;br&gt;
Remember how you have to input your database access's username and password during the MongoDB setup. So, imagine you have a course to share your source code to the public, say on GitHub, you need to protect access to your database.&lt;br&gt;
Firstly, we need another dependencies to run;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create .env file server/.env&lt;/p&gt;

&lt;p&gt;Inside index.js, add and update with another variables;&lt;br&gt;
&lt;code&gt;const dotenv = require('dotenv')&lt;/code&gt;&lt;br&gt;
Also cut the MongoDB link from line 12 and replace with &lt;br&gt;
&lt;code&gt;process.env.MONGO_URL&lt;/code&gt;&lt;br&gt;
Then inside .env file;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MONGO_URL = mongodb+srv://&amp;lt;username&amp;gt;:&amp;lt;password&amp;gt;@bukrate-app.lfqmj.mongodb.net/bukrate?retryWrites=true&amp;amp;w=majority
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulation! We’ve just finished the server side. With all these knowledge you’re now in position to create other entities, try to create a user entity, maybe an employee or a table price, use your imagination is your limitation.&lt;/p&gt;

&lt;p&gt;Let’s go straight up to setting up client side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.0 SETTING UP CLIENT SIDE&lt;/strong&gt;&lt;br&gt;
This is where we’re going to create all the user-interface parts, where the user will interact with our application.&lt;br&gt;
Firstly, we’re going to the root of our project and create the client-side. For this, we need to understand about NPX.&lt;br&gt;
NPX is a tool that its goal is to help round out the experience of using packages from the NPM registry. As NPM makes it super easy to install and manage dependencies hosted on the registry, NPX makes it easy to use CLI tools and other executables hosted on the registry.&lt;br&gt;
Let’s create our directory. So, the server-side will be for the Backend and we have the client-side for the Frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npx create-react-app client 
$ cd client
$ npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application should opened this screen if you get it right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwh33yck3xlt5ydqx4id.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwh33yck3xlt5ydqx4id.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
You will remember that the default port is 3000, but we’ve already set this port to our Backend. Then, let’s changes it to 7000. Meanwhile, you choose whatever number.&lt;br&gt;
To change the port we need to change it on client/package.json. Include PORT= in the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
},
  "scripts": {
    "start": "set PORT=7000 &amp;amp;&amp;amp; react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will discover that React creates some default files. Let’s remove some of the unnecessaries files for us;&lt;br&gt;
&lt;code&gt;$ rm App.css index.css App.test.js serviceWorker.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To view the complete app, we need to set up our project by  installing some other dependencies like we do in the server side. These are what we need; Axios, Bootstrap, Styled-Components, and React Table.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;axios: It’s a promise-based the asynchronous code. It’s the most popular promise based HTTP.&lt;/li&gt;
&lt;li&gt;bootstrap: It’s is an open-source toolkit and the most popular front-end component library where allows you for developing with HTML, CSS, and JS.&lt;/li&gt;
&lt;li&gt;styled-components: It allows you to write actual CSS code to style your components.&lt;/li&gt;
&lt;li&gt;react-table: It’s a lightweight, fast, and extendable data grid built for React.&lt;/li&gt;
&lt;li&gt;react-router-dom: DOM bindings for React Routers.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install styled-components react-table react-router-dom axios bootstrap --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the src directory, we should create the new directories that will be the structure of our project. Create an index.js file inside each directory, except the app folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd src
$ mkdir api app components pages style
$ touch api/index.js components/index.js pages/index.js style/index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move the App.js file to the app directory, but renaming to index.js.&lt;/p&gt;

&lt;p&gt;Now is time for us to start the coding,&lt;br&gt;
First of all, update our file client/src/index.js for the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'

ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('root'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, we’ll develop the header of the application. And create the other components of our project. Create the new files NavBar.jsx, Logo.jsx, and Links.jsx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ touch components/NavBar.jsx components/Logo.jsx components/Links.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hey! &lt;em&gt;What is JSX extension?&lt;/em&gt;&lt;br&gt;
Simple, JSX is a notation that Reacts chose to identify a JavaScript’s eXtension. It’s recommended to use it with React to describe what the UI should look like.&lt;/p&gt;

&lt;p&gt;Now, let’s create our files.&lt;br&gt;
For the Links;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components'

const Collapse = styled.div.attrs({
    className: 'collpase navbar-collapse',
})``

const List = styled.div.attrs({
    className: 'navbar-nav mr-auto',
})``

const Item = styled.div.attrs({
    className: 'collpase navbar-collapse',
})``

class Links extends Component {
    render() {
        return (
            &amp;lt;React.Fragment&amp;gt;
                &amp;lt;Link to="/" className="navbar-brand"&amp;gt;
                    MERN Application
                &amp;lt;/Link&amp;gt;
                &amp;lt;Collapse&amp;gt;
                    &amp;lt;List&amp;gt;
                        &amp;lt;Item&amp;gt;
                            &amp;lt;Link to="/rates/list" className="nav-link"&amp;gt;
                                List Book Rates
                            &amp;lt;/Link&amp;gt;
                        &amp;lt;/Item&amp;gt;
                        &amp;lt;Item&amp;gt;
                            &amp;lt;Link to="/rates/create" className="nav-link"&amp;gt;
                                Create Book Rate
                            &amp;lt;/Link&amp;gt;
                        &amp;lt;/Item&amp;gt;
                    &amp;lt;/List&amp;gt;
                &amp;lt;/Collapse&amp;gt;
            &amp;lt;/React.Fragment&amp;gt;
        )
    }
}

export default Links
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the Logo;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'
import styled from 'styled-components'

import logo from '../logo.svg'

const Wrapper = styled.a.attrs({
    className: 'navbar-brand',
})``

class Logo extends Component {
    render() {
        return (
            &amp;lt;Wrapper href="https://deoluoyinlola.netlify.app"&amp;gt;
                &amp;lt;img src={logo} width="50" height="50" alt="deoluoyinlola.netlify.app" /&amp;gt;
            &amp;lt;/Wrapper&amp;gt;
        )
    }
}

export default Logo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the NavBar;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'
import styled from 'styled-components'

import Logo from './Logo'
import Links from './Links'

const Container = styled.div.attrs({
    className: 'container',
})``

const Nav = styled.nav.attrs({
    className: 'navbar navbar-expand-lg navbar-dark bg-dark',
})`
    margin-bottom: 20 px;
`

class NavBar extends Component {
    render() {
        return (
            &amp;lt;Container&amp;gt;
                &amp;lt;Nav&amp;gt;
                    &amp;lt;Logo /&amp;gt;
                    &amp;lt;Links /&amp;gt;
                &amp;lt;/Nav&amp;gt;
            &amp;lt;/Container&amp;gt;
        )
    }
}

export default NavBar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The components/index.js file will help to export our components, it will allow us to import them in other files using the notation; &lt;em&gt;import { blabla } from './components'&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Links from './Links'
import Logo from './Logo'
import NavBar from './NavBar'

export { Links, Logo, NavBar }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, let's update app/index.js. Then, we able to see the development of the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import { BrowserRouter as Router } from 'react-router-dom'

import { NavBar } from '../components'

import 'bootstrap/dist/css/bootstrap.min.css'

function App() {
    return (
        &amp;lt;Router&amp;gt;
            &amp;lt;NavBar /&amp;gt;
        &amp;lt;/Router&amp;gt;
    )
}

export default App
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxijn9xcv2xjdfgt4ki4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxijn9xcv2xjdfgt4ki4.PNG" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;3.0 INTEGRATING SERVER AND CLIENT SIDE&lt;/strong&gt;&lt;br&gt;
Now let's learn how to integrate the server with our client.&lt;br&gt;
First of all, let’s update the file api/index.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from 'axios'

const api = axios.create({
    baseURL: 'http://localhost:3000/api',
})

export const insertRate = payload =&amp;gt; api.post(`/rate`, payload)
export const getAllRates = () =&amp;gt; api.get(`/rates`)
export const updateRateById = (id, payload) =&amp;gt; api.put(`/rate/${id}`, payload)
export const deleteRateById = id =&amp;gt; api.delete(`/rate/${id}`)
export const getRateById = id =&amp;gt; api.get(`/rate/${id}`)

const apis = {
    insertRate,
    getAllRates,
    updateRateById,
    deleteRateById,
    getRateById,
}

export default apis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amazing! Now we can develop our routes. For this, we’ll need to update the file app/index.js adding the routes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'

import { NavBar } from '../components'
import { RatesList, RatesInsert, RatesUpdate } from '../pages'

import 'bootstrap/dist/css/bootstrap.min.css'

function App() {
    return (
        &amp;lt;Router&amp;gt;
            &amp;lt;NavBar /&amp;gt;
            &amp;lt;Switch&amp;gt;
                &amp;lt;Route path="/rates/list" exact component={RatesList} /&amp;gt;
                &amp;lt;Route path="/rates/create" exact component={RatesInsert} /&amp;gt;
                &amp;lt;Route
                    path="/rates/update/:id"
                    exact
                    component={RatesUpdate}
                /&amp;gt;
            &amp;lt;/Switch&amp;gt;
        &amp;lt;/Router&amp;gt;
    )
}

export default App
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On pages folder, let’s create the files that will do the role of each application’s page: RatesList.jsx, RatesInsert.jsx and RatesUpdate.jsx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd pages
$ touch RatesList.jsx RatesInsert.jsx RatesUpdate.jsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now, let’s create simples files where you can see the page’s transition when you click in each link of the NavBar.&lt;/p&gt;

&lt;p&gt;For RateList;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'

class RatesList extends Component {
    render() {
        return (
            &amp;lt;div&amp;gt;
                &amp;lt;p&amp;gt;In this page you'll see the list of rates&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
        )
    }
}

export default RatesList
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For RateInsert;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'

class RatesInsert extends Component {
    render() {
        return (
            &amp;lt;div&amp;gt;
                &amp;lt;p&amp;gt;In this page you'll see the form to add a book&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
        )
    }
}

export default RatesInsert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For RateUpdate;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'

class RatesUpdate extends Component {
    render() {
        return (
            &amp;lt;div&amp;gt;
                &amp;lt;p&amp;gt;In this page you'll see the form to update the books&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
        )
    }
}

export default RatesUpdate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For index.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import RatesList from './RatesList'
import RatesInsert from './RatesInsert'
import RatesUpdate from './RatesUpdate'

export { RatesList, RatesInsert, RatesUpdate }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, let’s edit our file to get the ratings from the database: RatesList.jsx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'
import ReactTable from 'react-table'
import api from '../api'

import styled from 'styled-components'

import 'react-table/react-table.css'

const Wrapper = styled.div`
    padding: 0 40px 40px 40px;
`

class RatesList extends Component {
    constructor(props) {
        super(props)
        this.state = {
            rates: [],
            columns: [],
            isLoading: false,
        }
    }

    componentDidMount = async () =&amp;gt; {
        this.setState({ isLoading: true })

        await api.getAllRates().then(rates =&amp;gt; {
            this.setState({
                rates: rates.data.data,
                isLoading: false,
            })
        })
    }

    render() {
        const { rates, isLoading } = this.state
        console.log('TCL: RatesList -&amp;gt; render -&amp;gt; rates', rates)

        const columns = [
            {
                Header: 'ID',
                accessor: '_id',
                filterable: true,
            },
            {
                Header: 'Name',
                accessor: 'name',
                filterable: true,
            },
            {
                Header: 'Author',
                accessor: 'author',
                filterable: true,
            },
            {
                Header: 'Rating',
                accessor: 'rating',
                filterable: true,
            },
            {
                Header: 'Time',
                accessor: 'time',
                Cell: props =&amp;gt; &amp;lt;span&amp;gt;{props.value.join(' / ')}&amp;lt;/span&amp;gt;,
            },
        ]

        let showTable = true
        if (!rates.length) {
            showTable = false
        }

        return (
            &amp;lt;Wrapper&amp;gt;
                {showTable &amp;amp;&amp;amp; (
                    &amp;lt;ReactTable
                        data={rates}
                        columns={columns}
                        loading={isLoading}
                        defaultPageSize={10}
                        showPageSizeOptions={true}
                        minRows={0}
                    /&amp;gt;
                )}
            &amp;lt;/Wrapper&amp;gt;
        )
    }
}

export default RatesList

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome, in this list let’s include two more things, these things will be buttons. One button to delete another button to update.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'
import ReactTable from "react-table-6"
import api from '../api'

import styled from 'styled-components'

import "react-table-6/react-table.css" 

const Wrapper = styled.div`
    padding: 0 40px 40px 40px;
`

const Update = styled.div`
    color: #ef9b0f;
    cursor: pointer;
`

const Delete = styled.div`
    color: #ff0000;
    cursor: pointer;
`

class UpdateRate extends Component {
    updateUser = event =&amp;gt; {
        event.preventDefault()

        window.location.href = `/rates/update/${this.props.id}`
    }

    render() {
        return &amp;lt;Update onClick={this.updateUser}&amp;gt;Update&amp;lt;/Update&amp;gt;
    }
}

class DeleteRate extends Component {
    deleteUser = event =&amp;gt; {
        event.preventDefault()

        if (
            window.confirm(
                `Do you want to delete the movie ${this.props.id} permanently?`,
            )
        ) {
            api.deleteRateById(this.props.id)
            window.location.reload()
        }
    }

    render() {
        return &amp;lt;Delete onClick={this.deleteUser}&amp;gt;Delete&amp;lt;/Delete&amp;gt;
    }
}

class RatesList extends Component {
    constructor(props) {
        super(props)
        this.state = {
            rates: [],
            columns: [],
            isLoading: false,
        }
    }

    componentDidMount = async () =&amp;gt; {
        this.setState({ isLoading: true })

        await api.getAllRates().then(rates =&amp;gt; {
            this.setState({
                rates: rates.data.data,
                isLoading: false,
            })
        })
    }

    render() {
        const { rates, isLoading } = this.state
        console.log('TCL: RatesList -&amp;gt; render -&amp;gt; rates', rates)

        const columns = [
            {
                Header: 'ID',
                accessor: '_id',
                filterable: true,
            },
            {
                Header: 'Name',
                accessor: 'name',
                filterable: true,
            },
            {
                Header: 'Author',
                accessor: 'author',
                filterable: true,
            },
            {
                Header: 'Rating',
                accessor: 'rating',
                filterable: true,
            },
            {
                Header: 'Time',
                accessor: 'time',
                Cell: props =&amp;gt; &amp;lt;span&amp;gt;{props.value.join(' / ')}&amp;lt;/span&amp;gt;,
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        &amp;lt;span&amp;gt;
                            &amp;lt;DeleteRate id={props.original._id} /&amp;gt;
                        &amp;lt;/span&amp;gt;
                    )
                },
            },
            {
                Header: '',
                accessor: '',
                Cell: function(props) {
                    return (
                        &amp;lt;span&amp;gt;
                            &amp;lt;UpdateRate id={props.original._id} /&amp;gt;
                        &amp;lt;/span&amp;gt;
                    )
                },
            },
        ]

        let showTable = true
        if (!rates.length) {
            showTable = false
        }

        return (
            &amp;lt;Wrapper&amp;gt;
                {showTable &amp;amp;&amp;amp; (
                    &amp;lt;ReactTable
                        data={rates}
                        columns={columns}
                        loading={isLoading}
                        defaultPageSize={10}
                        showPageSizeOptions={true}
                        minRows={0}
                    /&amp;gt;
                )}
            &amp;lt;/Wrapper&amp;gt;
        )
    }
}

export default RatesList
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, now we’re able to delete a book rate, but we still not able to update it, because we haven’t finished the component yet.&lt;br&gt;
Before, to develop the update page, let’s create the insertion page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Component } from 'react'
import api from '../api'

import styled from 'styled-components'

const Title = styled.h1.attrs({
    className: 'h1',
})``

const Wrapper = styled.div.attrs({
    className: 'form-group',
})`
    margin: 0 30px;
`

const Label = styled.label`
    margin: 5px;
`

const InputText = styled.input.attrs({
    className: 'form-control',
})`
    margin: 5px;
`

const Button = styled.button.attrs({
    className: `btn btn-primary`,
})`
    margin: 15px 15px 15px 5px;
`

const CancelButton = styled.a.attrs({
    className: `btn btn-danger`,
})`
    margin: 15px 15px 15px 5px;
`

class RatesInsert extends Component {
    constructor(props) {
        super(props)

        this.state = {
            name: '',
            author: '',
            rating: '',
            time: '',
        }
    }

    handleChangeInputName = async event =&amp;gt; {
        const name = event.target.value
        this.setState({ name })
    }
    handleChangeInputAuthor = async event =&amp;gt; {
        const author = event.target.value
        this.setState({ author })
    }

    handleChangeInputRating = async event =&amp;gt; {
        const rating = event.target.validity.valid
            ? event.target.value
            : this.state.rating

        this.setState({ rating })
    }

    handleChangeInputTime = async event =&amp;gt; {
        const time = event.target.value
        this.setState({ time })
    }

    handleIncludeRate = async () =&amp;gt; {
        const { name, rating, time } = this.state
        const arrayTime = time.split('/')
        const payload = { name, rating, time: arrayTime }

        await api.insertRate(payload).then(res =&amp;gt; {
            window.alert(`Book inserted successfully`)
            this.setState({
                name: '',
                author: '',
                rating: '',
                time: '',
            })
        })
    }

    render() {
        const { name, author, rating, time } = this.state
        return (
            &amp;lt;Wrapper&amp;gt;
                &amp;lt;Title&amp;gt;Create Book&amp;lt;/Title&amp;gt;

                &amp;lt;Label&amp;gt;Name: &amp;lt;/Label&amp;gt;
                &amp;lt;InputText
                    type="text"
                    value={name}
                    onChange={this.handleChangeInputName}
                /&amp;gt;

                &amp;lt;Label&amp;gt;Author: &amp;lt;/Label&amp;gt;
                &amp;lt;InputText
                    type="text"
                    value={author}
                    onChange={this.handleChangeInputAuthor}
                /&amp;gt;

                &amp;lt;Label&amp;gt;Rating: &amp;lt;/Label&amp;gt;
                &amp;lt;InputText
                    type="number"
                    step="0.1"
                    lang="en-US"
                    min="0"
                    max="10"
                    pattern="[0-9]+([,\.][0-9]+)?"
                    value={rating}
                    onChange={this.handleChangeInputRating}
                /&amp;gt;

                &amp;lt;Label&amp;gt;Time: &amp;lt;/Label&amp;gt;
                &amp;lt;InputText
                    type="text"
                    value={time}
                    onChange={this.handleChangeInputTime}
                /&amp;gt;

                &amp;lt;Button onClick={this.handleIncludeMovie}&amp;gt;Add Book&amp;lt;/Button&amp;gt;
                &amp;lt;CancelButton href={'/rates/list'}&amp;gt;Cancel&amp;lt;/CancelButton&amp;gt;
            &amp;lt;/Wrapper&amp;gt;
        )
    }
}

export default RatesInsert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, let’s create the update file.&lt;/p&gt;

&lt;p&gt;Friend, we have come to the end of this tutorial. In this article, you have seen the structure to build a MERN application using diverse libraries provided by an amazing community around the world.&lt;br&gt;
In this article, my intuit was to keep things simple for your understanding. This is a project that you can do many enhancements.&lt;br&gt;
Maybe you can try, for instance, create a better structure to include the year of the book or you can improve the code to put the update and insertion book in the same file, what about to create a new entity called the customer and create the same RESTful operation for it? You can add a lot of new features to this. If you prefer, tell me in the comments.&lt;/p&gt;

&lt;p&gt;You can find the complete github repo &lt;a href="https://github.com/deoluoyinlola/docker-compose-mern-app" rel="noopener noreferrer"&gt;Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, is advised to follow up this tutorial up with the next part - How Dockerize MERN App on AWS EC2, Link here&lt;br&gt;
I hope that I have contributed to your knowledge. Feel free to tell me what I should improve on to write better articles.&lt;/p&gt;

&lt;p&gt;I love to see you in the next part.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
