<?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: Madhav Nakra</title>
    <description>The latest articles on DEV Community by Madhav Nakra (@madhavnakra).</description>
    <link>https://dev.to/madhavnakra</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3944547%2F1dded4cf-b050-4ed7-9d21-795782aeacad.jpg</url>
      <title>DEV Community: Madhav Nakra</title>
      <link>https://dev.to/madhavnakra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/madhavnakra"/>
    <language>en</language>
    <item>
      <title>Istio and the Sidecar Pattern: What I Learned About Service Mesh Fundamentals</title>
      <dc:creator>Madhav Nakra</dc:creator>
      <pubDate>Mon, 27 Jul 2026 16:39:00 +0000</pubDate>
      <link>https://dev.to/madhavnakra/istio-and-the-sidecar-pattern-what-i-learned-about-service-mesh-fundamentals-1np6</link>
      <guid>https://dev.to/madhavnakra/istio-and-the-sidecar-pattern-what-i-learned-about-service-mesh-fundamentals-1np6</guid>
      <description>&lt;p&gt;If you work with Kubernetes long enough, you eventually hit a wall that has nothing to do with your application code. Your services are deployed, your pods are healthy, but you still have no good answer to questions like: Is traffic between these two services encrypted? What happens if one service starts failing? Can I roll out a new version to just 10% of users without touching my app code?&lt;/p&gt;

&lt;p&gt;That wall is exactly where a service mesh comes in, and it's what pushed me to spend some time this week going through &lt;a href="https://github.com/iam-veeramalla/istio-guide" rel="noopener noreferrer"&gt;istio-guide&lt;/a&gt;, a repository by Abhishek Veeramalla that walks through Istio fundamentals for DevOps engineers. Here's what I took away from it, structured the way it clicked for me rather than as a glossary.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem a service mesh is solving
&lt;/h2&gt;

&lt;p&gt;In a monolith, calling another part of your system is a function call. In microservices, it's a network call, and network calls fail, get slow, and get intercepted. Every team ends up needing the same things: retries, timeouts, load balancing, encrypted traffic between services, and some way to see what's actually happening when something breaks.&lt;/p&gt;

&lt;p&gt;You could build all of that into every service. Or you could push it into the infrastructure layer, so no application code has to change. That's the pitch of a service mesh: a dedicated layer that handles service-to-service communication, security, and observability, sitting underneath your application rather than inside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sidecars: how the mesh gets into your pods
&lt;/h2&gt;

&lt;p&gt;The mechanism that makes this possible is the sidecar pattern. A sidecar is just a second container running alongside your main application container in the same pod, sharing its network namespace. In Istio's case, that sidecar is an Envoy proxy, and every bit of traffic in and out of your application container gets routed through it first.&lt;/p&gt;

&lt;p&gt;This is the part that reframed things for me: your application never talks to the network directly anymore. It talks to a proxy that happens to live right next to it. That proxy is what enforces encryption, applies traffic rules, and reports metrics, all without your code knowing the mesh exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Admission controllers: how the sidecar actually shows up
&lt;/h2&gt;

&lt;p&gt;The natural next question is: who's adding this second container to my pod? I never wrote it into my deployment YAML.&lt;/p&gt;

&lt;p&gt;That's where admission controllers come in. In Kubernetes, an admission controller sits between the API server and etcd, intercepting requests to create or modify objects before they're persisted, and it can either reject them or mutate them on the way through. Istio ships a mutating webhook that watches for new pods and injects the Envoy sidecar container into them automatically, as long as the namespace is labeled for injection.&lt;/p&gt;

&lt;p&gt;Seeing this connection was honestly the most useful part of going through the repo. Admission controllers and sidecars are often taught as separate Kubernetes topics, but in Istio they're the same mechanism: the sidecar isn't magic, it's a mutating admission webhook doing its job at pod creation time.&lt;/p&gt;

&lt;h2&gt;
  
  
  mTLS: the payoff you get almost for free
&lt;/h2&gt;

&lt;p&gt;Once every service has a proxy sitting in front of it, mutual TLS becomes a configuration problem instead of an engineering problem. With mTLS enabled, both sides of a connection present a certificate, so a service isn't just encrypting traffic, it's proving its identity to the service it's talking to. No certificate management inside application code, no library to bolt on. It's the sidecars handling the handshake on your service's behalf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traffic management: routing without touching deployments
&lt;/h2&gt;

&lt;p&gt;This is where Istio moves from "nice security layer" to genuinely useful for day-to-day operations. Three pieces work together here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VirtualServices&lt;/strong&gt; define how requests to a service get routed, which is what makes canary releases and A/B testing possible without spinning up separate infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DestinationRules&lt;/strong&gt; define the policy for traffic once it's been routed to a specific version, things like load balancing algorithm and TLS settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit breaking&lt;/strong&gt; sets thresholds on error rate or latency, and once a service crosses them, the mesh stops sending it requests instead of letting failures cascade through the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these require changes to the services themselves. It's all configuration sitting at the mesh layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gateways and observability
&lt;/h2&gt;

&lt;p&gt;Gateways are how external traffic gets into the mesh in the first place, acting as the ingress and egress points between the outside world and everything running inside. And because every request already passes through an Envoy proxy, observability comes almost as a side effect: distributed tracing, metrics, and logging are available without instrumenting each service individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service mesh vs. Ingress: a distinction worth being precise about
&lt;/h2&gt;

&lt;p&gt;This one is easy to blur, so it's worth stating plainly. An Ingress controller manages traffic coming into the cluster from outside, things like SSL termination and HTTP routing at the edge. A service mesh operates one layer deeper, governing how services inside the cluster talk to each other. They solve different problems, and most real setups end up using both rather than treating them as alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The repo isn't just a README, it's got hands-on folders for admission controllers, install and setup, mTLS, and traffic management, so the next step for me is working through those labs directly instead of just reading. Concepts like circuit breaking and canary routing make a lot more sense once you've broken something on purpose and watched the mesh react.&lt;/p&gt;

&lt;p&gt;If you're working with Kubernetes and haven't looked into service mesh concepts yet, I'd genuinely recommend starting with this repo. It doesn't try to cover every corner of Istio, it just gets the fundamentals straight, which turned out to be exactly what I needed.&lt;/p&gt;




</description>
      <category>devops</category>
      <category>istio</category>
      <category>kubernetes</category>
      <category>sidecar</category>
    </item>
    <item>
      <title>Deploying a Dockerized Node.js Application on Kubernetes 🚀</title>
      <dc:creator>Madhav Nakra</dc:creator>
      <pubDate>Tue, 09 Jun 2026 21:08:21 +0000</pubDate>
      <link>https://dev.to/madhavnakra/deploying-a-dockerized-nodejs-application-on-kubernetes-34e4</link>
      <guid>https://dev.to/madhavnakra/deploying-a-dockerized-nodejs-application-on-kubernetes-34e4</guid>
      <description>&lt;p&gt;After containerizing an application with Docker, the next logical step is deploying it on Kubernetes.&lt;/p&gt;

&lt;p&gt;Kubernetes helps automate application deployment, scaling, networking, and management of containerized workloads. Instead of manually running containers, Kubernetes ensures your application remains available and can easily scale when needed.&lt;/p&gt;

&lt;p&gt;In this guide, we'll deploy a Docker image of a Node.js application on Kubernetes using a Deployment and a Service.&lt;/p&gt;




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

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker installed&lt;/li&gt;
&lt;li&gt;Kubernetes cluster running (Docker Desktop Kubernetes, Minikube, Kind, EKS, etc.)&lt;/li&gt;
&lt;li&gt;kubectl configured&lt;/li&gt;
&lt;li&gt;A Docker image pushed to Docker Hub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my case, the image was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;madhavnaks/node-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Running a container using Docker is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 madhavnaks/node-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, in production environments we need much more than simply running a container.&lt;/p&gt;

&lt;p&gt;Kubernetes provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High availability&lt;/li&gt;
&lt;li&gt;Self-healing containers&lt;/li&gt;
&lt;li&gt;Load balancing&lt;/li&gt;
&lt;li&gt;Service discovery&lt;/li&gt;
&lt;li&gt;Horizontal scaling&lt;/li&gt;
&lt;li&gt;Rolling updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it the industry standard for container orchestration.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding the Kubernetes Architecture for This Deployment
&lt;/h1&gt;

&lt;p&gt;For this deployment, we'll use two Kubernetes resources:&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;A Deployment is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating Pods&lt;/li&gt;
&lt;li&gt;Maintaining desired replica count&lt;/li&gt;
&lt;li&gt;Recreating failed Pods automatically&lt;/li&gt;
&lt;li&gt;Managing updates and rollbacks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Service
&lt;/h3&gt;

&lt;p&gt;A Service provides a stable network endpoint for Pods.&lt;/p&gt;

&lt;p&gt;Since Pod IPs change frequently, Services allow applications and users to communicate reliably with Pods.&lt;/p&gt;




&lt;h1&gt;
  
  
  Deployment and Service Manifest
&lt;/h1&gt;

&lt;p&gt;Create a file named:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;app.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-app&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-app&lt;/span&gt;

  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-app&lt;/span&gt;

    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-app&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;madhavnaks/node-app:latest&lt;/span&gt;

          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-app&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-app&lt;/span&gt;

  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;

  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
      &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;32000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Understanding the Deployment Configuration
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Replica Count
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kubernetes will maintain two running Pod instances of the application.&lt;/p&gt;

&lt;p&gt;If one Pod crashes, Kubernetes automatically creates another one to maintain the desired state.&lt;/p&gt;




&lt;h3&gt;
  
  
  Docker Image
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;madhavnaks/node-app:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kubernetes pulls the image directly from Docker Hub and uses it to create containers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Container Port
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This specifies the port on which the Node.js application listens inside the container.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding the Service Configuration
&lt;/h1&gt;

&lt;p&gt;The Service exposes our Pods to network traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Port
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the port exposed by the Kubernetes Service inside the cluster.&lt;/p&gt;




&lt;h3&gt;
  
  
  Target Port
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traffic arriving at the Service is forwarded to port 3000 inside the container.&lt;/p&gt;




&lt;h3&gt;
  
  
  NodePort
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;32000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exposes the application outside the cluster.&lt;/p&gt;

&lt;p&gt;Requests reaching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Node-IP&amp;gt;:32000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are forwarded to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Service Port → Target Port → Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;32000 → 123 → 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Deploying the Application
&lt;/h1&gt;

&lt;p&gt;Apply the manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; complete.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deployment.apps/node-app created
service/node-app created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Verify the Deployment
&lt;/h1&gt;

&lt;p&gt;Check Deployments:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME       READY   UP-TO-DATE   AVAILABLE
node-app   2/2     2            2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Check Pods:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME                        READY   STATUS
node-app-xxxxx              1/1     Running
node-app-yyyyy              1/1     Running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that Kubernetes created two Pods because we specified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Check Services:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME         TYPE       CLUSTER-IP      PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;
node-app     NodePort   10.x.x.x        123:32000/TCP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Accessing the Application
&lt;/h1&gt;

&lt;p&gt;To access the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:32000
&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;http://&amp;lt;Node-IP&amp;gt;:32000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;depending on your Kubernetes setup.&lt;/p&gt;

&lt;p&gt;The request flow looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
   │
   ▼
NodePort (32000)
   │
   ▼
Service Port (123)
   │
   ▼
Target Port (3000)
   │
   ▼
Node.js Container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Benefits of Using a Deployment
&lt;/h1&gt;

&lt;p&gt;Deployments provide several production-grade capabilities:&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-Healing
&lt;/h3&gt;

&lt;p&gt;If a Pod crashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl delete pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kubernetes automatically creates a replacement Pod.&lt;/p&gt;




&lt;h3&gt;
  
  
  Scaling
&lt;/h3&gt;

&lt;p&gt;Increase replicas easily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; complete.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kubernetes creates additional Pods automatically.&lt;/p&gt;




&lt;h3&gt;
  
  
  Rolling Updates
&lt;/h3&gt;

&lt;p&gt;When a new Docker image version is pushed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;madhavnaks/node-app:v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying the updated manifest performs a rolling update with minimal downtime.&lt;/p&gt;




&lt;h1&gt;
  
  
  Key Takeaways
&lt;/h1&gt;

&lt;p&gt;✅ Deployments manage Pods automatically&lt;/p&gt;

&lt;p&gt;✅ Replica count ensures high availability&lt;/p&gt;

&lt;p&gt;✅ Services provide stable networking&lt;/p&gt;

&lt;p&gt;✅ NodePort exposes applications outside the cluster&lt;/p&gt;

&lt;p&gt;✅ Kubernetes continuously maintains the desired state of the application&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Deploying a containerized application on Kubernetes is a major step toward building production-ready cloud-native applications.&lt;/p&gt;

&lt;p&gt;Using a Deployment and Service, Kubernetes can automatically manage application availability, networking, scaling, and recovery without manual intervention.&lt;/p&gt;

&lt;p&gt;Once you're comfortable with these fundamentals, the next topics to explore are ConfigMaps, Secrets, Ingress, Persistent Volumes, and Helm Charts.&lt;/p&gt;

&lt;p&gt;Happy Learning and Happy Kubernetes! 🚀&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>docker</category>
      <category>beginners</category>
    </item>
    <item>
      <title>From Dockerfile to Docker Hub: A Complete Beginner's Guide to Docker 🚀</title>
      <dc:creator>Madhav Nakra</dc:creator>
      <pubDate>Tue, 02 Jun 2026 21:06:56 +0000</pubDate>
      <link>https://dev.to/madhavnakra/from-dockerfile-to-docker-hub-a-complete-beginners-guide-to-docker-2o1b</link>
      <guid>https://dev.to/madhavnakra/from-dockerfile-to-docker-hub-a-complete-beginners-guide-to-docker-2o1b</guid>
      <description>&lt;p&gt;Containerization has become a fundamental skill for DevOps Engineers, Cloud Engineers, and Software Developers.&lt;/p&gt;

&lt;p&gt;However, many beginners learn Docker commands without understanding the complete workflow behind them.&lt;/p&gt;

&lt;p&gt;Questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What exactly is a Docker Image?&lt;/li&gt;
&lt;li&gt;How does a Dockerfile become a running Container?&lt;/li&gt;
&lt;li&gt;Why do we push images to Docker Hub?&lt;/li&gt;
&lt;li&gt;How do organizations deploy the same application everywhere?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;are common when starting out.&lt;/p&gt;

&lt;p&gt;In this blog, we'll build a simple Node.js application, containerize it using Docker, run it locally, and finally push the image to Docker Hub.&lt;/p&gt;

&lt;p&gt;By the end of this guide, you'll understand the complete Docker workflow used in real-world DevOps environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Workflow Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Application Code] --&amp;gt; B[Dockerfile]
    B --&amp;gt; C[Docker Build]
    C --&amp;gt; D[Docker Image]
    D --&amp;gt; E[Docker Run]
    E --&amp;gt; F[Docker Container]
    D --&amp;gt; G[Docker Push]
    G --&amp;gt; H[Docker Hub]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the same workflow followed by developers and DevOps teams worldwide.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Are We Building?
&lt;/h1&gt;

&lt;p&gt;We'll create a simple Node.js application that returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A welcome message&lt;/li&gt;
&lt;li&gt;Environment information&lt;/li&gt;
&lt;li&gt;Container hostname&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps us verify that our application is actually running inside a Docker container.&lt;/p&gt;




&lt;h1&gt;
  
  
  Project Structure
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── Dockerfile
├── app.js
└── package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Step 1: Create the Node.js Application
&lt;/h1&gt;

&lt;h2&gt;
  
  
  app.js
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ENV&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENV_VALUE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No env set&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HOSTNAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HOSTNAME&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;os&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from Simple App (Node)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HOSTNAME&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Node Hello listening on &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  package.json
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello-app-node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.2.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Application Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    User --&amp;gt; Browser
    Browser --&amp;gt; Container
    Container --&amp;gt; NodeJS
    NodeJS --&amp;gt; JSONResponse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever a user accesses the application, the request reaches the containerized Node.js application, which returns a JSON response.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 2: Create the Dockerfile
&lt;/h1&gt;

&lt;p&gt;A Dockerfile is simply a blueprint that tells Docker how to build an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:24-slim&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--production&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Understanding the Dockerfile
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Base Image
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:24-slim&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start with an official lightweight Node.js image from Docker Hub.&lt;/p&gt;




&lt;h3&gt;
  
  
  Working Directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates and switches to the &lt;code&gt;/app&lt;/code&gt; directory inside the container.&lt;/p&gt;




&lt;h3&gt;
  
  
  Copy Dependency Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copies package files first.&lt;/p&gt;

&lt;p&gt;This is considered a Docker best practice because Docker can cache dependency layers and speed up future builds.&lt;/p&gt;




&lt;h3&gt;
  
  
  Install Dependencies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installs only production dependencies.&lt;/p&gt;




&lt;h3&gt;
  
  
  Copy Application Source Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copies the entire project into the container.&lt;/p&gt;




&lt;h3&gt;
  
  
  Expose Application Port
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documents that the application listens on port 3000.&lt;/p&gt;




&lt;h3&gt;
  
  
  Start the Application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runs the Node.js application when the container starts.&lt;/p&gt;




&lt;h1&gt;
  
  
  What Happens During Docker Build?
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A[Dockerfile]
    --&amp;gt; B[Pull Node Base Image]
    --&amp;gt; C[Create Working Directory]
    --&amp;gt; D[Copy package.json]
    --&amp;gt; E[Install Dependencies]
    --&amp;gt; F[Copy Application Code]
    --&amp;gt; G[Create Image Layers]
    --&amp;gt; H[Docker Image Ready]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker executes each instruction sequentially and creates image layers.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 3: Build the Docker Image
&lt;/h1&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; madhavnaks/node-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Builds an image from a Dockerfile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assigns a tag to the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;madhavnaks/node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Image name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Current directory containing the Dockerfile.&lt;/p&gt;




&lt;p&gt;After a successful build you'll see output similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; naming to docker.io/madhavnaks/node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker has now created an image locally on your machine.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 4: Verify the Image
&lt;/h1&gt;

&lt;p&gt;To see locally available images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;REPOSITORY                TAG       IMAGE ID       SIZE
madhavnaks/node-app       latest    42c936686000   234MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the image exists but is not running.&lt;/p&gt;




&lt;h1&gt;
  
  
  Docker Image vs Docker Container
&lt;/h1&gt;

&lt;p&gt;Many beginners confuse these two concepts.&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Image = Blueprint&lt;/li&gt;
&lt;li&gt;Docker Container = Running Application
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Docker Image]
    --&amp;gt; B[Container 1]

    A --&amp;gt; C[Container 2]

    A --&amp;gt; D[Container 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single image can create multiple containers.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 5: Run a Container
&lt;/h1&gt;

&lt;p&gt;Now let's start our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; node-app &lt;span class="nt"&gt;-p&lt;/span&gt; 3001:3000 madhavnaks/node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Understanding the Command
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Detached Mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runs the container in the background.&lt;/p&gt;




&lt;h3&gt;
  
  
  Container Name
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--name&lt;/span&gt; node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assigns a friendly name to the container.&lt;/p&gt;




&lt;h3&gt;
  
  
  Port Mapping
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-p&lt;/span&gt; 3001:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host Port      → Container Port
3001           → 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application listens on port 3000 inside the container but is accessible on port 3001 from your machine.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 6: Verify the Container
&lt;/h1&gt;

&lt;p&gt;Check running containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;CONTAINER ID   IMAGE                 STATUS
10265698c978   madhavnaks/node-app   Up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Step 7: Access the Application
&lt;/h1&gt;

&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from Simple App (Node)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No env set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"container"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10265698c978"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the hostname.&lt;/p&gt;

&lt;p&gt;The hostname corresponds to the container ID, proving the application is running inside Docker.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 8: Login to Docker Hub
&lt;/h1&gt;

&lt;p&gt;Before pushing images, authenticate with Docker Hub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Login Succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker is now authorized to push images to your repository.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Push Images to Docker Hub?
&lt;/h1&gt;

&lt;p&gt;Docker Hub acts as a centralized registry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Developer Machine]
    --&amp;gt;|Push| B[Docker Hub]

    B --&amp;gt;|Pull| C[Server]

    B --&amp;gt;|Pull| D[Kubernetes Cluster]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once an image is pushed, it can be pulled and run from anywhere.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 9: Push the Image
&lt;/h1&gt;

&lt;p&gt;Push the image to Docker Hub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push madhavnaks/node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;latest: digest: sha256:d1081ec542f521e100bd886943c13ab7568c663b56e36200e6d846163975f979
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that the image has been successfully uploaded.&lt;/p&gt;




&lt;h1&gt;
  
  
  Step 10: Verify on Docker Hub
&lt;/h1&gt;

&lt;p&gt;Visit your Docker Hub account.&lt;/p&gt;

&lt;p&gt;You should now see:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;listed under repositories.&lt;/p&gt;

&lt;p&gt;You can even share the image with others.&lt;/p&gt;

&lt;p&gt;Anyone can now run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull madhavnaks/node-app

docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3001:3000 madhavnaks/node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without needing your source code.&lt;/p&gt;




&lt;h1&gt;
  
  
  Real-World DevOps Workflow
&lt;/h1&gt;

&lt;p&gt;In production environments, the workflow usually looks 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;flowchart LR
    A[Developer Writes Code]
    --&amp;gt; B[GitHub]

    B --&amp;gt; C[CI/CD Pipeline]

    C --&amp;gt; D[Docker Build]

    D --&amp;gt; E[Docker Hub]

    E --&amp;gt; F[Kubernetes Cluster]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly how modern DevOps teams package and deploy applications.&lt;/p&gt;




&lt;h1&gt;
  
  
  Key Takeaways
&lt;/h1&gt;

&lt;p&gt;✅ Dockerfile defines how an image should be built&lt;/p&gt;

&lt;p&gt;✅ Docker Build creates an image&lt;/p&gt;

&lt;p&gt;✅ Docker Run creates a container&lt;/p&gt;

&lt;p&gt;✅ Docker Hub stores and distributes images&lt;/p&gt;

&lt;p&gt;✅ One image can create multiple containers&lt;/p&gt;

&lt;p&gt;✅ Containerization ensures consistency across environments&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this guide, we covered the complete Docker workflow from source code to Docker Hub.&lt;/p&gt;

&lt;p&gt;We learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Dockerfile&lt;/li&gt;
&lt;li&gt;Build a Docker image&lt;/li&gt;
&lt;li&gt;Run a container&lt;/li&gt;
&lt;li&gt;Verify application execution&lt;/li&gt;
&lt;li&gt;Push images to Docker Hub&lt;/li&gt;
&lt;li&gt;Understand how images move through real-world DevOps pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mastering these Docker fundamentals is the first step toward advanced topics like Docker Compose, Kubernetes, Helm, CI/CD pipelines, and cloud-native deployments.&lt;/p&gt;

&lt;p&gt;If you're learning DevOps, try containerizing applications in different languages such as Python, Java, Go, or .NET to strengthen your understanding of Docker.&lt;/p&gt;

&lt;p&gt;Happy Containerizing! 🚀&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>containers</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Configuring AWS CLI on Ubuntu for Local Machine ☁️🐧</title>
      <dc:creator>Madhav Nakra</dc:creator>
      <pubDate>Thu, 21 May 2026 17:26:05 +0000</pubDate>
      <link>https://dev.to/madhavnakra/configuring-aws-cli-on-ubuntu-for-local-machine-5elf</link>
      <guid>https://dev.to/madhavnakra/configuring-aws-cli-on-ubuntu-for-local-machine-5elf</guid>
      <description>&lt;p&gt;When people start learning AWS, they usually focus only on installing the AWS CLI.&lt;br&gt;
But installing it is just the first step.&lt;/p&gt;

&lt;p&gt;To actually interact with AWS services from your Ubuntu machine, you also need to configure AWS credentials properly.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll go through the complete setup process for AWS CLI on Ubuntu — from installation to configuration and verification.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why AWS CLI?
&lt;/h2&gt;

&lt;p&gt;AWS CLI allows you to manage AWS services directly from your terminal.&lt;/p&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch EC2 instances&lt;/li&gt;
&lt;li&gt;Upload files to S3&lt;/li&gt;
&lt;li&gt;Configure IAM&lt;/li&gt;
&lt;li&gt;Manage EKS clusters&lt;/li&gt;
&lt;li&gt;Automate cloud operations using scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of clicking through the AWS Console every time, AWS CLI helps automate everything efficiently.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Update Packages
&lt;/h2&gt;

&lt;p&gt;First, update your system packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures your package manager has the latest repository information.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Install Required Dependencies
&lt;/h2&gt;

&lt;p&gt;Install &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;unzip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;unzip curl &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tools are required to download and extract the AWS CLI installer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Download AWS CLI v2 Installer
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"awscliv2.zip"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This downloads the latest AWS CLI v2 package for Ubuntu/Linux systems.&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%2Fbg4u0m4kan12svme29j8.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%2Fbg4u0m4kan12svme29j8.png" alt=" " width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Unzip the Installer
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;unzip awscliv2.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This extracts the installation files.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Run the Install Script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; ./aws/install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AWS CLI will now be installed on your machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Verify Installation
&lt;/h2&gt;

&lt;p&gt;Check whether AWS CLI is installed successfully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&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%2Frw2fyc22q8fq5z20yu14.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%2Frw2fyc22q8fq5z20yu14.png" alt=" " width="797" height="109"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Configure AWS CLI
&lt;/h2&gt;

&lt;p&gt;Now comes the important part — configuration.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll be asked for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;AWS Access Key ID
AWS Secret Access Key
Default region name
Default output format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;AWS Access Key ID &lt;span class="o"&gt;[&lt;/span&gt;None]: AKIAXXXXX
AWS Secret Access Key &lt;span class="o"&gt;[&lt;/span&gt;None]: &lt;span class="k"&gt;********&lt;/span&gt;
Default region name &lt;span class="o"&gt;[&lt;/span&gt;None]: ap-south-1
Default output format &lt;span class="o"&gt;[&lt;/span&gt;None]: json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can generate Access Keys from:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AWS Console → IAM → Users → Security Credentials → Create Access Key&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Verify Configured Profiles
&lt;/h2&gt;

&lt;p&gt;To check configured AWS profiles and settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps verify whether your credentials and region are configured correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9: View Stored Credentials
&lt;/h2&gt;

&lt;p&gt;AWS stores credentials locally inside the &lt;code&gt;.aws&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Check credentials file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.aws/credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.aws/config
&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%2Fr5xbt1zmtfqdzblyq7cy.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%2Fr5xbt1zmtfqdzblyq7cy.png" alt=" " width="799" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  credentials file
&lt;/h3&gt;

&lt;p&gt;Stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access Key ID&lt;/li&gt;
&lt;li&gt;Secret Access Key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[default]&lt;/span&gt;
&lt;span class="py"&gt;aws_access_key_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;XXXXX&lt;/span&gt;
&lt;span class="py"&gt;aws_secret_access_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;XXXXX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  config file
&lt;/h3&gt;

&lt;p&gt;Stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default region&lt;/li&gt;
&lt;li&gt;Output format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[default]&lt;/span&gt;
&lt;span class="py"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ap-south-1&lt;/span&gt;
&lt;span class="py"&gt;output&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Important Security Tip ⚠️
&lt;/h2&gt;

&lt;p&gt;Never share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access Key ID&lt;/li&gt;
&lt;li&gt;Secret Access Key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.aws/credentials&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, add &lt;code&gt;.aws/&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt; if you're working inside projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Installing AWS CLI is easy, but properly configuring it is what actually enables you to work with AWS services from your local Ubuntu machine.&lt;/p&gt;

&lt;p&gt;Once configured, you can automate cloud operations directly from the terminal and integrate AWS into scripts, CI/CD pipelines, and DevOps workflows.&lt;/p&gt;

&lt;p&gt;If you're starting your cloud or DevOps journey, AWS CLI is one of the most essential tools to learn 🚀&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>ubuntu</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
