<?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>Forem: Rodrigo Faria</title>
    <description>The latest articles on Forem by Rodrigo Faria (@rodrigofaria).</description>
    <link>https://forem.com/rodrigofaria</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%2F1030462%2F66ac4d59-86d8-47a8-a267-d5423819b469.jpeg</url>
      <title>Forem: Rodrigo Faria</title>
      <link>https://forem.com/rodrigofaria</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rodrigofaria"/>
    <language>en</language>
    <item>
      <title>Running a Node.JS API on Kubernetes local with K3D</title>
      <dc:creator>Rodrigo Faria</dc:creator>
      <pubDate>Sun, 26 Feb 2023 12:49:51 +0000</pubDate>
      <link>https://forem.com/rodrigofaria/running-a-nodejs-api-on-kubernetes-local-with-k3d-3e87</link>
      <guid>https://forem.com/rodrigofaria/running-a-nodejs-api-on-kubernetes-local-with-k3d-3e87</guid>
      <description>&lt;p&gt;How to "play" with &lt;a href="https://kubernetes.io" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; on your own machine? One way to achieve this could be &lt;a href="https://k3d.io/v5.4.7" rel="noopener noreferrer"&gt;K3D&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;This tutorial will show how to run an application on a local Kubernetes inside a Ubuntu machine running on &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/install" rel="noopener noreferrer"&gt;WSL2&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;First, we need to install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://k3d.io/v5.4.7" rel="noopener noreferrer"&gt;K3D&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/tools/#kubectl" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; (or another code editor)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, you need to have an account in &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Node.js API
&lt;/h2&gt;

&lt;p&gt;The first step is to create our API. Let's create a folder and initialize a Node.js project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgy0x1fhrrmn469zz1osn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgy0x1fhrrmn469zz1osn.png" alt="Node initialization" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to install &lt;a href="https://www.npmjs.com/package/express" rel="noopener noreferrer"&gt;express&lt;/a&gt; with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now open the Visual Studio Code, or another code editor, and create a folder called &lt;code&gt;src&lt;/code&gt; and inside a file called &lt;code&gt;index.js&lt;/code&gt; as in the picture below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fe2cf8azcf681353dkxm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fe2cf8azcf681353dkxm2.png" alt="Application structure" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's write some code to create an API that responds with &lt;code&gt;Hello World&lt;/code&gt; in the path &lt;code&gt;http://localhost:8087/api/v1/test&lt;/code&gt;:&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 app = express()

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

app.listen(8087, () =&amp;gt; console.log('Server started on port 8087'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's change the &lt;code&gt;package.json&lt;/code&gt; file to remove the &lt;code&gt;test&lt;/code&gt; instruction created by default and add our instruction to execute the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F19h3jamisgis0td6so96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F19h3jamisgis0td6so96.png" alt="package.json file" width="715" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the command line just type &lt;code&gt;npm start&lt;/code&gt; and you can open your browser and access the application with the URL &lt;code&gt;http://localhost:8087/api/v1/test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1gz4jrji0x0sq7z1oiqr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1gz4jrji0x0sq7z1oiqr.png" alt="Application running" width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker image
&lt;/h2&gt;

&lt;p&gt;In order to execute our application in Kubernetes, we should create an image of our application. In this tutorial, we will create a Docker image.&lt;/p&gt;

&lt;p&gt;The first step is to create in the root of the project a file called &lt;code&gt;Dockerfile&lt;/code&gt; and add this content below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:18-alpine

WORKDIR /app

COPY package*json ./

RUN npm i

COPY ./src ./src

CMD ["npm", "start"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we should use the &lt;code&gt;build&lt;/code&gt; command to generate the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t rodrigoluisfaria/new-api:1.0.0 .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the command above you should replace &lt;code&gt;rodrigoluisfaria&lt;/code&gt; with your username in Docker Hub.&lt;/p&gt;

&lt;p&gt;If the command executes successfully, you can check the image generated using the command &lt;code&gt;docker images&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fd43jz0cdvzilodm5gbjp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fd43jz0cdvzilodm5gbjp.png" alt="docker images command" width="800" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to test the image generated, we can run the command below to execute the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -it --rm -p 8087:8087 rodrigoluisfaria/new-api:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the container start, you can open the browser and test if you can access the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F37h67o0dl2ufqqgeoj4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F37h67o0dl2ufqqgeoj4x.png" alt="running application on Docker" width="800" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step is to put this image in our Docker Hub repository.&lt;br&gt;
For this you need to log in to the docker hub using 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;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the page Docker Hub create a new repository called &lt;code&gt;new-api&lt;/code&gt; and execute the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push rodrigoluisfaria/new-api:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to replace &lt;code&gt;rodrigoluisfaria&lt;/code&gt; with your username in Docker Hub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cluster Kubernetes - K3D
&lt;/h2&gt;

&lt;p&gt;Now let's create our cluster using K3D!&lt;br&gt;
For this you just need to execute 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;k3d cluster create -p "8087:80@loadbalancer" my-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this command, you start a cluster and expose port &lt;code&gt;8087&lt;/code&gt; of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxb2kf7wvs30h5d907txa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxb2kf7wvs30h5d907txa.png" alt="Creating cluster Kubernetes" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to test your cluster you could run some commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl cluster-info
kubectl get nodes
kubectl get pods --all-namespaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fmms8qefu15gzefce2cdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmms8qefu15gzefce2cdk.png" alt="Cluster info" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes
&lt;/h2&gt;

&lt;p&gt;Now let's create a folder called &lt;code&gt;k8s&lt;/code&gt; and three files inside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deployment.yaml - &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;Deployment&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;service.yaml - &lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="noopener noreferrer"&gt;Service&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ingress.yaml - &lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" rel="noopener noreferrer"&gt;Ingress&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;code&gt;deployment.yaml&lt;/code&gt; file put the content:&lt;br&gt;
&lt;/p&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: my-app-deployment
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: rodrigoluisfaria/new-api:1.0.0
          ports:
            - containerPort: 8087
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;service.yaml&lt;/code&gt; file put the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
  - port: 8087
    targetPort: 8087
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;ingress.yaml&lt;/code&gt; file put the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 8087
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's run a kubectl commands to create those resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify the resources you could execute the commands below:&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 deployments
kubectl get services
kubectl get ingress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F4ubj42ligixxzdq1qv52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F4ubj42ligixxzdq1qv52.png" alt="kubectl commands" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step is to test! Open the browser and check if your application is running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsy83sbf0w8lqkee270n9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsy83sbf0w8lqkee270n9.png" alt="Application" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this tutorial was helpful, and if you have any comments or questions you could comment here or in my e-mail &lt;a href="mailto:rodrigolfsi@gmail.com"&gt;rodrigolfsi@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>product</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
