<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Devops Learning]]></title><description><![CDATA[Devops Learning]]></description><link>https://devops-learning-commands.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 05 Oct 2026 18:52:50 GMT</lastBuildDate><atom:link href="https://devops-learning-commands.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[DevOps Under the Hood — Episode 3: What Actually Happens When You Run docker run?]]></title><description><![CDATA[If you have used Docker, you have probably typed this command countless times:
docker run nginx

A few seconds later, you see a running container.
It feels simple.
But Docker didn't just "start Nginx.]]></description><link>https://devops-learning-commands.hashnode.dev/devops-under-the-hood-episode-3-what-actually-happens-when-you-run-docker-run</link><guid isPermaLink="true">https://devops-learning-commands.hashnode.dev/devops-under-the-hood-episode-3-what-actually-happens-when-you-run-docker-run</guid><category><![CDATA[Devops]]></category><category><![CDATA[DevOps Journey]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Docker compose]]></category><category><![CDATA[docker run]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Sarthak-code786]]></dc:creator><pubDate>Tue, 01 Sep 2026 11:14:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c6a45f9aa3928a58bc9fb5/68aee5c1-3c88-447b-a077-e58152f4844e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have used Docker, you have probably typed this command countless times:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>A few seconds later, you see a running container.</p>
<p>It feels simple.</p>
<p>But Docker didn't just "start Nginx."</p>
<p>Between pressing <strong>Enter</strong> and seeing that container running, Docker performs a series of operations involving images, the Docker daemon, storage, networking, isolation, and processes.</p>
<p>That made me curious:</p>
<p><strong>What actually happens when we run</strong> <code>docker run</code><strong>?</strong></p>
<p>Let's go under the hood.</p>
<hr />
<h2>First, What Does <code>docker run</code> Actually Mean?</h2>
<p>When we execute:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>we are essentially asking Docker to:</p>
<blockquote>
<p>Find the <code>nginx</code> image, create a new container from it, configure the container, and start its main process.</p>
</blockquote>
<p>A useful way to visualize it is:</p>
<pre><code class="language-plaintext">docker run nginx
        |
        v
Docker CLI
        |
        v
Docker Daemon
        |
        v
Check for nginx image
        |
   +----+----+
   |         |
Exists     Doesn't exist
   |         |
   |      Pull image
   |         |
   +----+----+
        |
        v
Create container
        |
        v
Configure filesystem &amp; networking
        |
        v
Start container process
        |
        v
Nginx is running
</code></pre>
<p>Now let's break this down.</p>
<hr />
<h1>Step 1 — You Run the Command</h1>
<p>Everything starts here:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>The command is executed through the <strong>Docker CLI</strong>.</p>
<p>The CLI is the interface we use to communicate with Docker.</p>
<p>But here's something important:</p>
<p><strong>The Docker CLI doesn't do all the work itself.</strong></p>
<p>It communicates with the <strong>Docker daemon</strong>, which is responsible for actually managing containers, images, networks, and other Docker resources.</p>
<p>So conceptually:</p>
<pre><code class="language-plaintext">You
 ↓
Docker CLI
 ↓
Docker Daemon
</code></pre>
<hr />
<h1>Step 2 — Docker Checks for the Image</h1>
<p>Docker now needs to find the <code>nginx</code> image.</p>
<p>It first checks whether the image already exists locally.</p>
<p>You can see your local images with:</p>
<pre><code class="language-plaintext">docker images
</code></pre>
<p>If <code>nginx</code> is already available, Docker can use it.</p>
<p>If it isn't available locally, Docker needs to retrieve it from a container registry.</p>
<hr />
<h1>Step 3 — Docker Pulls the Image If Necessary</h1>
<p>If Docker can't find the image locally, it pulls it from a registry.</p>
<p>For example:</p>
<pre><code class="language-plaintext">docker pull nginx
</code></pre>
<p>The default registry most developers encounter is Docker Hub.</p>
<p>The image is downloaded in layers.</p>
<p>You may have seen output similar to:</p>
<pre><code class="language-plaintext">Pull complete
Pull complete
Pull complete
</code></pre>
<p>These layers are one of the reasons Docker images can be efficient.</p>
<p>Different images can share common layers instead of storing duplicate data.</p>
<hr />
<h1>Step 4 — Docker Creates the Container</h1>
<p>This is where an important distinction comes in.</p>
<p><strong>An image is not a container.</strong></p>
<p>Think about it like this:</p>
<blockquote>
<p><strong>Docker Image = Blueprint</strong><br /><strong>Container = House built from the blueprint</strong></p>
</blockquote>
<p>The image contains what is needed to create the application environment.</p>
<p>The container is the running instance created from that image.</p>
<p>So when you execute:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>Docker uses the <code>nginx</code> image to create a new container.</p>
<p>You can verify the running container with:</p>
<pre><code class="language-plaintext">docker ps
</code></pre>
<hr />
<h1>Step 5 — Docker Prepares the Container Environment</h1>
<p>Before starting the application, Docker needs to prepare the environment in which the container will run.</p>
<p>This includes things such as:</p>
<ul>
<li><p>Filesystem</p>
</li>
<li><p>Networking</p>
</li>
<li><p>Environment variables</p>
</li>
<li><p>Resource configuration</p>
</li>
<li><p>Process isolation</p>
</li>
</ul>
<p>This is one of the reasons containers are more than just "lightweight virtual machines."</p>
<p>Containers use operating-system-level isolation mechanisms to separate processes and resources.</p>
<hr />
<h1>Step 6 — The Container Gets Its Own Filesystem View</h1>
<p>The container needs a filesystem to work with.</p>
<p>Docker builds this environment from the image layers and creates a writable layer for the container.</p>
<p>This means multiple containers can be created from the same image while maintaining their own changes.</p>
<p>For example:</p>
<pre><code class="language-plaintext">                 Nginx Image
                     |
          +----------+----------+
          |                     |
          v                     v
     Container A           Container B
     Writable Layer        Writable Layer
</code></pre>
<p>Both containers can use the same underlying image while having their own container-specific writable layer.</p>
<hr />
<h1>Step 7 — Docker Sets Up Networking</h1>
<p>Docker also creates the networking environment required by the container.</p>
<p>For a basic container:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>Docker typically connects the container to its default network.</p>
<p>However, there's an important detail.</p>
<p>If you run:</p>
<pre><code class="language-plaintext">docker run -p 8080:80 nginx
</code></pre>
<p>you're explicitly mapping:</p>
<pre><code class="language-plaintext">Host Port 8080
       |
       v
Container Port 80
</code></pre>
<p>So when you visit:</p>
<pre><code class="language-plaintext">http://localhost:8080
</code></pre>
<p>the request can reach Nginx running inside the container.</p>
<p>This is one of those Docker concepts that becomes much easier once you understand what's happening underneath.</p>
<hr />
<h1>Step 8 — Docker Starts the Main Process</h1>
<p>Now comes the part that makes the container actually "run."</p>
<p>Docker starts the process defined by the image's configuration.</p>
<p>For the Nginx image, that means starting the Nginx process.</p>
<p>This leads to another important concept:</p>
<p><strong>A container is fundamentally about running a process.</strong></p>
<p>It's not just a packaged folder.</p>
<p>Docker creates an isolated environment and starts the application's process inside it.</p>
<hr />
<h1>Image vs Container</h1>
<p>This distinction is worth remembering.</p>
<table>
<thead>
<tr>
<th>Docker Image</th>
<th>Docker Container</th>
</tr>
</thead>
<tbody><tr>
<td>Read-only template</td>
<td>Running instance</td>
</tr>
<tr>
<td>Used to create containers</td>
<td>Created from an image</td>
</tr>
<tr>
<td>Can be shared</td>
<td>Has its own writable layer</td>
</tr>
<tr>
<td>Doesn't represent a running process</td>
<td>Runs application processes</td>
</tr>
</tbody></table>
<p>A simple analogy:</p>
<p><strong>Image = Recipe</strong></p>
<p><strong>Container = Meal prepared using that recipe</strong></p>
<p>You can prepare multiple meals using the same recipe.</p>
<p>Similarly, you can create multiple containers from the same image.</p>
<hr />
<h1>What If the Container Stops?</h1>
<p>Here's another interesting part.</p>
<p>If you run:</p>
<pre><code class="language-plaintext">docker ps
</code></pre>
<p>you'll only see currently running containers.</p>
<p>To see stopped containers too:</p>
<pre><code class="language-plaintext">docker ps -a
</code></pre>
<p>Why?</p>
<p>Because the container itself can still exist even after its main process has stopped.</p>
<p>You can then start it again using:</p>
<pre><code class="language-plaintext">docker start &lt;container-id&gt;
</code></pre>
<p>This helped me understand that:</p>
<p><strong>Container lifecycle and application lifecycle are closely connected.</strong></p>
<p>When the main process ends, the container generally stops.</p>
<hr />
<h1>The Complete Journey</h1>
<p>So the next time you run:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>think about everything happening underneath:</p>
<pre><code class="language-plaintext">You
 |
 | docker run nginx
 v
Docker CLI
 |
 v
Docker Daemon
 |
 v
Check local image
 |
 +---- Image exists
 |          |
 |          v
 |     Use existing image
 |
 +---- Image doesn't exist
            |
            v
        Pull image
            |
            v
      Create container
            |
            v
   Prepare filesystem
            |
            v
    Configure networking
            |
            v
     Start main process
            |
            v
       Nginx running
</code></pre>
<p>One command.</p>
<p>A surprisingly long chain of operations.</p>
<hr />
<h1>Why Understanding This Matters in DevOps</h1>
<p>When I first learned Docker, I focused on commands:</p>
<pre><code class="language-plaintext">docker build
docker run
docker ps
docker stop
docker rm
</code></pre>
<p>But knowing commands is only one part of working with Docker.</p>
<p>Understanding what happens underneath makes troubleshooting much easier.</p>
<p>For example, when a container doesn't work, I can start asking better questions:</p>
<p><strong>Is the image available?</strong></p>
<p><strong>Did the container actually start?</strong></p>
<p><strong>Is the application process running?</strong></p>
<p><strong>Is the port mapped correctly?</strong></p>
<p><strong>Is the container connected to the expected network?</strong></p>
<p><strong>What do the container logs say?</strong></p>
<p>Instead of randomly trying commands, I can start investigating the actual layer where the problem exists.</p>
<hr />
<h1>This Became Important in My CI/CD Project</h1>
<p>While building my own CI/CD pipeline, Docker wasn't just something I was learning separately.</p>
<p>It became part of the delivery process.</p>
<p>The simplified flow looked like:</p>
<pre><code class="language-plaintext">Git Push
   ↓
Jenkins
   ↓
Maven Build
   ↓
SonarQube
   ↓
Docker Build
   ↓
Docker Image
   ↓
Container
   ↓
AWS EC2
</code></pre>
<p>Understanding Docker at this level makes the pipeline easier to reason about.</p>
<p>The pipeline isn't simply "running Docker."</p>
<p>It's building an artifact, creating an environment from that artifact, and eventually running the application as a container.</p>
<hr />
<h1>What I Took Away From This</h1>
<p>Before digging into Docker internals, I thought:</p>
<pre><code class="language-plaintext">docker run nginx
</code></pre>
<p>meant:</p>
<blockquote>
<p>"Start Nginx."</p>
</blockquote>
<p>Now I think of it differently.</p>
<p>It means:</p>
<blockquote>
<p>"Take this image, create an isolated container environment from it, configure the required resources and networking, and start the application's process."</p>
</blockquote>
<p>That's a much better mental model.</p>
<p>And this is becoming a recurring theme in my DevOps journey.</p>
<p>The command is only the surface.</p>
<p><strong>The interesting part is what happens underneath.</strong></p>
]]></content:encoded></item><item><title><![CDATA[What Actually Happens After You Type git push?]]></title><description><![CDATA[If you've worked with Git for even a few days, you've probably typed this command hundreds of times.
git push

A few seconds later, your code appears on GitHub.
It feels almost magical.
But behind tha]]></description><link>https://devops-learning-commands.hashnode.dev/what-actually-happens-after-you-type-git-push</link><guid isPermaLink="true">https://devops-learning-commands.hashnode.dev/what-actually-happens-after-you-type-git-push</guid><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[linux-basics]]></category><category><![CDATA[DevOps Journey]]></category><category><![CDATA[git push]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[Sarthak-code786]]></dc:creator><pubDate>Sun, 26 Jul 2026 12:50:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c6a45f9aa3928a58bc9fb5/caff63fc-fd2f-4c69-ab1e-f0c11fcffc5a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've worked with Git for even a few days, you've probably typed this command hundreds of times.</p>
<pre><code class="language-plaintext">git push
</code></pre>
<p>A few seconds later, your code appears on GitHub.</p>
<p>It feels almost magical.</p>
<p>But behind that simple command is a surprisingly sophisticated sequence of events.</p>
<p>When I first started learning DevOps, I treated <code>git push</code> as nothing more than "upload my code."</p>
<p>Now, after building CI/CD pipelines and working with Git daily, I see it very differently.</p>
<p>Let's take a look under the hood.</p>
<hr />
<h2>Step 1 — Git Finds What Has Changed</h2>
<p>The first thing Git does isn't upload anything.</p>
<p>Instead, it compares your local branch with the remote branch.</p>
<p>It asks a simple question:</p>
<blockquote>
<p>"Which commits does the remote repository not have yet?"</p>
</blockquote>
<p>Only those missing commits will be prepared for transfer.</p>
<p>This is one reason Git remains incredibly efficient even for large repositories.</p>
<hr />
<h2>Step 2 — Git Creates a Packfile</h2>
<p>Git doesn't upload every individual file.</p>
<p>Instead, it creates what's called a <strong>packfile</strong>.</p>
<p>Inside this compressed package are:</p>
<ul>
<li><p>Commits</p>
</li>
<li><p>Trees (directory structure)</p>
</li>
<li><p>Blobs (file contents)</p>
</li>
</ul>
<p>Because of this compression, Git transfers only the required information while minimizing network traffic.</p>
<p>This is one of Git's biggest strengths.</p>
<hr />
<h2>Step 3 — Authentication</h2>
<p>Before GitHub accepts anything, it verifies your identity.</p>
<p>Depending on your configuration, this usually happens through:</p>
<ul>
<li><p>SSH Keys</p>
</li>
<li><p>Personal Access Tokens (HTTPS)</p>
</li>
</ul>
<p>If authentication fails, the push stops immediately.</p>
<p>No code is transferred.</p>
<hr />
<h2>Step 4 — Secure Communication</h2>
<p>Now the data begins travelling across the internet.</p>
<p>Most developers push using one of two protocols:</p>
<ul>
<li><p>SSH (Port 22)</p>
</li>
<li><p>HTTPS (Port 443)</p>
</li>
</ul>
<p>Both provide encrypted communication, ensuring your commits remain secure during transmission.</p>
<hr />
<h2>Step 5 — GitHub Performs Validation</h2>
<p>Receiving the data isn't enough.</p>
<p>GitHub now validates several things.</p>
<p>For example:</p>
<ul>
<li><p>Does the repository exist?</p>
</li>
<li><p>Does the branch exist?</p>
</li>
<li><p>Does the user have permission?</p>
</li>
<li><p>Are branch protection rules satisfied?</p>
</li>
</ul>
<p>If any of these checks fail, GitHub rejects the push.</p>
<hr />
<h2>Step 6 — Updating the Remote Repository</h2>
<p>Once every validation passes successfully, GitHub updates the branch reference.</p>
<p>Your commits now become part of the remote repository.</p>
<p>At this point, everyone collaborating on the project can access the latest changes.</p>
<hr />
<h2>Step 7 — The Hidden DevOps Pipeline</h2>
<p>For many organizations, this is where the interesting part begins.</p>
<p>A single <code>git push</code> can automatically trigger an entire CI/CD workflow.</p>
<p>For example:</p>
<pre><code class="language-plaintext">Developer
      │
      ▼
git push
      │
      ▼
GitHub Repository
      │
      ▼
Webhook
      │
      ▼
Jenkins Pipeline
      │
      ▼
Build
      │
      ▼
Run Tests
      │
      ▼
SonarQube Analysis
      │
      ▼
Docker Image
      │
      ▼
Deploy to AWS EC2
</code></pre>
<p>What looks like a simple Git command can actually start an automated software delivery process.</p>
<p>That realization completely changed how I viewed Git.</p>
<hr />
<h2>Why Understanding This Matters</h2>
<p>As beginners, we often focus on memorizing commands.</p>
<p>Experienced engineers ask a different question:</p>
<p><strong>"What happens after I run this command?"</strong></p>
<p>That mindset leads to a much deeper understanding of systems.</p>
<p>And in DevOps, understanding systems is often more valuable than memorizing tools.</p>
<hr />
<p>Finally</p>
<p>Today, whenever I type:</p>
<pre><code class="language-plaintext">git push
</code></pre>
<p>I no longer think:</p>
<blockquote>
<p>"I'm uploading my code."</p>
</blockquote>
<p>Instead, I think:</p>
<blockquote>
<p>"I'm triggering a chain of systems that will validate, build, test, and possibly deploy my application."</p>
</blockquote>
<p>A single command.</p>
<p>An entire ecosystem working behind the scenes.</p>
<p>And that's exactly what makes DevOps fascinating.</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[A Green Pipeline Doesn’t Always Mean Success]]></title><description><![CDATA[When I first started building CI/CD pipelines, I had a very simple definition of success:
Pipeline green = Everything is working.
If Jenkins showed a successful build, I assumed:

The application was ]]></description><link>https://devops-learning-commands.hashnode.dev/a-green-pipeline-doesn-t-always-mean-success</link><guid isPermaLink="true">https://devops-learning-commands.hashnode.dev/a-green-pipeline-doesn-t-always-mean-success</guid><category><![CDATA[Devops]]></category><category><![CDATA[Devops articles]]></category><category><![CDATA[DevOps Journey]]></category><category><![CDATA[#Devopscommunity]]></category><category><![CDATA[Jenkins]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Linux]]></category><category><![CDATA[linux for beginners]]></category><category><![CDATA[linux-commands]]></category><category><![CDATA[linux-basics]]></category><dc:creator><![CDATA[Sarthak-code786]]></dc:creator><pubDate>Sun, 24 May 2026 14:49:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c6a45f9aa3928a58bc9fb5/2ff1121a-a06a-46fc-91fe-710eb8421643.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I first started building CI/CD pipelines, I had a very simple definition of success:</p>
<p>Pipeline green = Everything is working.</p>
<p>If Jenkins showed a successful build, I assumed:</p>
<ul>
<li><p>The application was fine</p>
</li>
<li><p>Deployment worked</p>
</li>
<li><p>The system was healthy</p>
</li>
</ul>
<p>But after working on real setups, I realized something important:</p>
<p>A successful pipeline only means the steps executed successfully.</p>
<p>It does not guarantee the outcome is correct.</p>
<p>And honestly, that changed the way I think about DevOps.</p>
<hr />
<h2>The first time I realized this</h2>
<p>One of my deployments looked completely successful.</p>
<p>Build stage ✔<br />Docker stage ✔<br />Deployment stage ✔</p>
<p>Everything was green.</p>
<p>But when I opened the application—</p>
<p>nothing worked.</p>
<p>The service wasn’t accessible.</p>
<p>At first, I thought Jenkins had failed silently.</p>
<p>But after debugging further, the actual issues were:</p>
<ul>
<li><p>Security group misconfiguration</p>
</li>
<li><p>Container startup failure</p>
</li>
<li><p>Port accessibility problems</p>
</li>
</ul>
<p>The pipeline had technically succeeded.</p>
<p>The system had not.</p>
<hr />
<h2>Another Example: Maven Test Failures</h2>
<p>In another instance, the pipeline failed due to Maven tests.</p>
<p>The Jenkins setup itself was correct.</p>
<p>But the build failed due to:</p>
<pre><code class="language-plaintext">Failed to execute goal maven-surefire-plugin:test
</code></pre>
<p>That moment helped me understand something important:</p>
<p>Sometimes the pipeline is healthy.</p>
<p>The code is not.</p>
<hr />
<h2>CI/CD Pipelines Don’t Just Deploy Code</h2>
<p>Earlier, I viewed pipelines as automation tools.</p>
<p>Now I see them differently.</p>
<p>Pipelines are validation systems.</p>
<p>They verify:</p>
<ul>
<li><p>Build quality</p>
</li>
<li><p>Test execution</p>
</li>
<li><p>Deployment flow</p>
</li>
<li><p>System consistency</p>
</li>
</ul>
<p>A failed pipeline is not always “bad.”</p>
<p>Sometimes it’s the system protecting production.</p>
<hr />
<h2>What I Started Checking After Deployments</h2>
<p>Earlier, my workflow ended at:</p>
<p>✔ Jenkins build successful</p>
<p>Now I validate much more:</p>
<ul>
<li><p>Is the application actually running?</p>
</li>
<li><p>Is the service reachable?</p>
</li>
<li><p>Are ports exposed correctly?</p>
</li>
<li><p>Did the container start properly?</p>
</li>
<li><p>Is the server accessible?</p>
</li>
</ul>
<p>That small mindset shift changed how I debug systems.</p>
<hr />
<h2>Why This Matters in DevOps</h2>
<p>One thing I’m slowly learning:</p>
<p>Automation alone is not enough.</p>
<p>A pipeline can automate mistakes very efficiently if validation is missing.</p>
<p>That’s why observability, testing, logging, and verification matter so much in real systems.</p>
<hr />
<h2>What This Journey Taught Me</h2>
<h2>The deeper I go into DevOps, the more I realize:</h2>
<p>The hardest part is not running tools.</p>
<p>It’s understanding systems.</p>
<p>Because tools only execute instructions.</p>
<p>Engineers have to understand outcomes.</p>
<hr />
<h2>Final Thoughts</h2>
<p>Today, when I see a green pipeline, I no longer immediately assume success.</p>
<p>Instead, I ask:</p>
<ul>
<li><p>Did the deployment actually work?</p>
</li>
<li><p>Is the application healthy?</p>
</li>
<li><p>Can users access the system?</p>
</li>
<li><p>Did the infrastructure behave correctly?</p>
</li>
</ul>
<p>That mindset changed how I approach CI/CD completely.</p>
<p>And honestly, it made the learning journey far more interesting.</p>
<hr />
<p>LinkedIn: <a href="https://bit.ly/41vlNEW">https://bit.ly/41vlNEW</a>  </p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Linux Commands That Became Essential While Building My DevOps Projects]]></title><description><![CDATA[When I first started learning DevOps, I focused heavily on tools.
Jenkins.Docker.AWS.Terraform.
But while building real projects, I kept running into problems that none of those tools alone could solv]]></description><link>https://devops-learning-commands.hashnode.dev/linux-commands-that-became-essential-while-building-my-devops-projects</link><guid isPermaLink="true">https://devops-learning-commands.hashnode.dev/linux-commands-that-became-essential-while-building-my-devops-projects</guid><category><![CDATA[Devops]]></category><category><![CDATA[DevOps Journey]]></category><category><![CDATA[Devops articles]]></category><category><![CDATA[#Devopscommunity]]></category><category><![CDATA[Jenkins]]></category><category><![CDATA[ Jenkins, DevOps]]></category><category><![CDATA[AWS]]></category><category><![CDATA[aws lambda]]></category><category><![CDATA[Linux]]></category><category><![CDATA[linux for beginners]]></category><category><![CDATA[linux-commands]]></category><category><![CDATA[Terraform]]></category><dc:creator><![CDATA[Sarthak-code786]]></dc:creator><pubDate>Sun, 17 May 2026 13:38:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69c6a45f9aa3928a58bc9fb5/74b666e6-da7d-4e2c-8de4-b83ec39f25ae.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I first started learning DevOps, I focused heavily on tools.</p>
<p>Jenkins.<br />Docker.<br />AWS.<br />Terraform.</p>
<p>But while building real projects, I kept running into problems that none of those tools alone could solve.</p>
<p>Most of the time, the answer was somewhere inside Linux.</p>
<p>That’s when I realized:</p>
<p>DevOps tools may automate systems.<br />But Linux helps you understand them.</p>
<p>Over the past few weeks, while working on CI/CD pipelines, Docker containers, EC2 deployments, and Terraform setups, a few Linux commands became part of my daily workflow.</p>
<p>These weren’t just commands I memorized.</p>
<p>They became the commands that helped me debug, fix, and understand systems better.</p>
<hr />
<h1>1. <code>chmod</code> — Fixing SSH Key Permission Issues</h1>
<p>One of the first real problems I faced was while connecting to an AWS EC2 instance using SSH.</p>
<p>The instance was running.<br />The public IP was correct.</p>
<p>But SSH kept failing.</p>
<p>The issue turned out to be incorrect permissions on the <code>.pem</code> key file.</p>
<p>The fix:</p>
<pre><code class="language-plaintext">chmod 400 petclinic-key.pem
</code></pre>
<p>This command restricts access to the key file and allows SSH to use it securely.</p>
<p>This was one of the moments where Linux stopped feeling “optional.”</p>
<hr />
<h1>2. <code>ls</code> — Understanding Files and Permissions</h1>
<p>Simple, but essential.</p>
<p>While working with Terraform files, Docker configurations, and Jenkins setups, I constantly used:</p>
<pre><code class="language-plaintext">ls -l
</code></pre>
<p>This helped me:</p>
<ul>
<li><p>Check file permissions</p>
</li>
<li><p>Verify scripts</p>
</li>
<li><p>Confirm generated files</p>
</li>
<li><p>Understand ownership and access</p>
</li>
</ul>
<p>It became one of the fastest ways to debug environment issues.</p>
<hr />
<h1>3. <code>cd</code> and <code>pwd</code> — Navigating Projects Efficiently</h1>
<p>During CI/CD setup, multiple directories quickly become confusing.</p>
<p>Using:</p>
<pre><code class="language-plaintext">pwd
</code></pre>
<p>helped confirm the current working directory.</p>
<p>And:</p>
<pre><code class="language-plaintext">cd
</code></pre>
<p>became second nature while moving between:</p>
<ul>
<li><p>Jenkins workspace</p>
</li>
<li><p>Terraform folders</p>
</li>
<li><p>Docker project directories</p>
</li>
</ul>
<p>Basic commands, but used constantly.</p>
<hr />
<h1>4. <code>systemctl</code> — Managing Services</h1>
<p>When services failed unexpectedly, this command became extremely important.</p>
<p>Example:</p>
<pre><code class="language-plaintext">systemctl status docker
</code></pre>
<p>This helped me:</p>
<ul>
<li><p>Check if Docker is running</p>
</li>
<li><p>Verify service states</p>
</li>
<li><p>Troubleshoot startup issues</p>
</li>
</ul>
<p>Other useful variations:</p>
<pre><code class="language-plaintext">systemctl start docker
systemctl restart docker
</code></pre>
<p>Understanding services made debugging much easier.</p>
<hr />
<h1>5. <code>docker logs</code> — Understanding Container Failures</h1>
<p>Sometimes containers exited immediately without clear errors.</p>
<p>Instead of guessing, I started checking logs:</p>
<pre><code class="language-plaintext">docker logs &lt;container-id&gt;
</code></pre>
<p>This exposed:</p>
<ul>
<li><p>Application startup failures</p>
</li>
<li><p>Port conflicts</p>
</li>
<li><p>Missing configurations</p>
</li>
<li><p>Runtime exceptions</p>
</li>
</ul>
<p>This command saved hours of blind troubleshooting.</p>
<hr />
<h1>6. <code>ps</code> — Checking Running Processes</h1>
<p>When applications behaved unexpectedly, I used:</p>
<pre><code class="language-plaintext">ps -ef
</code></pre>
<p>This helped identify:</p>
<ul>
<li><p>Running processes</p>
</li>
<li><p>Stuck services</p>
</li>
<li><p>Background tasks</p>
</li>
</ul>
<p>A small command, but very useful while debugging deployments.</p>
<hr />
<h1>7. <code>top</code> — Watching System Resources</h1>
<p>While testing deployments on EC2, I became curious about resource usage.</p>
<p>Using:</p>
<pre><code class="language-plaintext">top
</code></pre>
<p>helped monitor:</p>
<ul>
<li><p>CPU usage</p>
</li>
<li><p>Memory consumption</p>
</li>
<li><p>Running processes</p>
</li>
</ul>
<p>This was one of the first steps toward understanding system performance.</p>
<hr />
<h1>8. <code>grep</code> — Searching Faster</h1>
<p>Logs can become overwhelming very quickly.</p>
<p>Using:</p>
<pre><code class="language-plaintext">grep
</code></pre>
<p>helped filter important information from large outputs.</p>
<p>Example:</p>
<pre><code class="language-plaintext">docker logs container-id | grep ERROR
</code></pre>
<p>This made debugging much faster.</p>
<hr />
<h1>9. <code>mkdir</code> and <code>rm</code> — Managing Project Structure</h1>
<p>Simple commands, but heavily used while creating environments and cleaning up setups.</p>
<p>Examples:</p>
<pre><code class="language-plaintext">mkdir terraform-ec2
rm -rf old-folder
</code></pre>
<p>These became part of daily project management.</p>
<hr />
<h1>What Linux Actually Taught Me</h1>
<p>Before these projects, Linux felt like:</p>
<p>“A set of commands to memorize.”</p>
<p>Now it feels different.</p>
<p>Linux is not just an operating system in DevOps.</p>
<p>It’s the layer where:</p>
<ul>
<li><p>Services run</p>
</li>
<li><p>Containers execute</p>
</li>
<li><p>Permissions matter</p>
</li>
<li><p>Logs exist</p>
</li>
<li><p>Systems reveal problems</p>
</li>
</ul>
<p>The more I worked on real setups, the more Linux stopped feeling theoretical.</p>
<p>It became practical.</p>
<hr />
<h1>Final Thoughts</h1>
<p>One thing I’ve learned during this journey:</p>
<p>Most DevOps debugging eventually leads back to Linux.</p>
<p>Not because the tools are bad.</p>
<p>But because Linux is where those tools operate.</p>
<p>The better I understand Linux, the easier it becomes to understand systems.</p>
<p>And honestly, that has been one of the biggest shifts in my learning journey so far.</p>
<hr />
<p>LinkedIn: <a href="https://bit.ly/41vlNEW">https://bit.ly/41vlNEW</a>  </p>
<hr />
<h3>Tags</h3>
<p>#devops #linux #AWS #docker #terraform #jenkins #cicd</p>
]]></content:encoded></item></channel></rss>