<?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: Dhananjay Patel</title>
    <description>The latest articles on DEV Community by Dhananjay Patel (@thenanjay).</description>
    <link>https://dev.to/thenanjay</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%2F950539%2Feb38656e-7017-403a-a556-9ca86de3fae9.jpeg</url>
      <title>DEV Community: Dhananjay Patel</title>
      <link>https://dev.to/thenanjay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thenanjay"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Thu, 20 Aug 2026 18:40:36 +0000</pubDate>
      <link>https://dev.to/thenanjay/-4lio</link>
      <guid>https://dev.to/thenanjay/-4lio</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13" class="crayons-story__hidden-navigation-link"&gt;Understanding the Linux Filesystem Hierarchy&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/thenanjay" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F950539%2Feb38656e-7017-403a-a556-9ca86de3fae9.jpeg" alt="thenanjay profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/thenanjay" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Dhananjay Patel
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Dhananjay Patel
                
                
              
              &lt;div id="story-author-preview-content-4447225" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/thenanjay" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F950539%2Feb38656e-7017-403a-a556-9ca86de3fae9.jpeg" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Dhananjay Patel&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13" id="article-link-4447225"&gt;
          Understanding the Linux Filesystem Hierarchy
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/linux"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;linux&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Understanding the Linux Filesystem Hierarchy</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Thu, 20 Aug 2026 18:36:06 +0000</pubDate>
      <link>https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13</link>
      <guid>https://dev.to/thenanjay/understanding-the-linux-filesystem-hierarchy-3c13</guid>
      <description>&lt;p&gt;If you have just installed Linux, booted up your machine, opened the terminal, and typed &lt;code&gt;ls /&lt;/code&gt;, you were probably met with a wall of cryptic two- and three-letter folder names: &lt;code&gt;bin&lt;/code&gt;, &lt;code&gt;etc&lt;/code&gt;, &lt;code&gt;usr&lt;/code&gt;, &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;opt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are coming from Windows, your first question is likely: &lt;strong&gt;"Where is my C: drive? And what are all these strange folders?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't worry—you are not alone. Many computer science students and engineers navigate Linux for years without truly understanding why these directories are named this way or how they work under the hood.&lt;/p&gt;

&lt;p&gt;In this blog, we will break down the &lt;strong&gt;Linux Filesystem Hierarchy Standard (FHS)&lt;/strong&gt;, clear up common myths, learn how to navigate the directory tree, and understand the design ideas behind it. The FHS is a convention, not a rigid law: distributions can add directories, merge old paths, or package applications in different ways. The examples below describe a typical modern Linux installation.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Forest of Slashes: Windows vs. Linux
&lt;/h2&gt;

&lt;p&gt;One of the biggest differences between Windows and Linux is how they organize the filesystem namespace.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows uses a drive-based system.&lt;/strong&gt; Your operating system lives on &lt;code&gt;C:&lt;/code&gt;. If you plug in a USB drive, it gets assigned a new letter like &lt;code&gt;D:&lt;/code&gt; or &lt;code&gt;E:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux uses a single unified tree structure.&lt;/strong&gt; There are no drive letters. Instead, everything starts from a single point called the &lt;strong&gt;root directory&lt;/strong&gt;, represented by a single forward slash (&lt;code&gt;/&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi16rt4l6yjzqsqigp0gc.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi16rt4l6yjzqsqigp0gc.png" alt="root-path-/" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Linux filesystem is one unified directory tree rooted at &lt;code&gt;/&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Think of the root &lt;code&gt;/&lt;/code&gt; as the &lt;strong&gt;trunk of a massive tree&lt;/strong&gt;. Every accessible file is reached somewhere below it. Separate filesystems—such as another disk, a USB drive, or a network share—can be attached at directories in that tree using &lt;strong&gt;mounts&lt;/strong&gt;. After mounting, the contents of that filesystem appear at the chosen directory (the &lt;em&gt;mount point&lt;/em&gt;), so the application does not need a separate drive letter. If the mount point already contained files, they are temporarily hidden until the filesystem is unmounted.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4drihpwusu11i8xkcd2u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4drihpwusu11i8xkcd2u.png" alt="windows-vs-linux" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Windows exposes separate drive letters; Linux attaches filesystems into one namespace through mount points.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Golden Rule: "Everything Is a File"
&lt;/h2&gt;

&lt;p&gt;If you remember only one thing from this blog, make it this design principle: &lt;strong&gt;In Linux, almost everything is exposed through file-like interfaces&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Rather than giving every part of the system a completely different interface, Linux lets programs use familiar paths and operations for many tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regular files:&lt;/strong&gt; Your code, PDFs, images, and text documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Directories:&lt;/strong&gt; Special filesystem objects that map names to other filesystem objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Devices:&lt;/strong&gt; Many hardware and pseudo-devices are exposed through device files, such as storage devices under &lt;code&gt;/dev&lt;/code&gt; and input devices like &lt;code&gt;/dev/input/event0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processes:&lt;/strong&gt; Information about running programs is exposed through virtual files under &lt;code&gt;/proc&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a powerful convention, not a literal rule: sockets, pipes, and system calls are also important interfaces, and not every resource behaves like an ordinary file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is this useful?
&lt;/h3&gt;

&lt;p&gt;It often lets you use familiar command-line tools such as &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, and &lt;code&gt;echo&lt;/code&gt; to inspect or interact with system interfaces as well as ordinary files. The operations supported by a particular interface still matter—writing to a device or kernel interface is not the same as editing a text file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Want to see your computer's CPU specifications? Just read a virtual file: &lt;code&gt;cat /proc/cpuinfo&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Want to see your available RAM? Just check: &lt;code&gt;cat /proc/meminfo&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;code&gt;/proc&lt;/code&gt; and &lt;code&gt;/sys&lt;/code&gt; are interfaces, not ordinary folders full of permanent files. Some entries are generated when you read them, and many are only meaningful on a running Linux kernel.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Grouping Directories by Purpose
&lt;/h2&gt;

&lt;p&gt;Rather than memorizing folders alphabetically, it is much easier to group them by what they do:&lt;/p&gt;

&lt;h3&gt;
  
  
  📂 User Workspaces
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/home&lt;/code&gt; (The Workspace):&lt;/strong&gt; This is where regular users store their personal files, projects, and downloads. If your username is Alice, your personal folder is &lt;code&gt;/home/alice&lt;/code&gt;. Think of it as your desktop and documents folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/root&lt;/code&gt; (The Administrator's Home):&lt;/strong&gt; This is the private home directory of the system administrator (the &lt;code&gt;root&lt;/code&gt; user). &lt;strong&gt;Crucial distinction:&lt;/strong&gt; &lt;code&gt;/&lt;/code&gt; is the starting point of the entire filesystem, while &lt;code&gt;/root&lt;/code&gt; is just one specific folder inside it. A regular user may have administrative power through &lt;code&gt;sudo&lt;/code&gt; without using &lt;code&gt;/root&lt;/code&gt; as their home directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📂 The Toolbox &amp;amp; Applications
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/bin&lt;/code&gt; &amp;amp; &lt;code&gt;/sbin&lt;/code&gt; (Essential Tools):&lt;/strong&gt; Traditionally, &lt;code&gt;/bin&lt;/code&gt; held essential commands usable by ordinary users (&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;), while &lt;code&gt;/sbin&lt;/code&gt; held essential system-administration commands (&lt;code&gt;ip&lt;/code&gt;, &lt;code&gt;mount&lt;/code&gt;, &lt;code&gt;fsck&lt;/code&gt;, and sometimes &lt;code&gt;shutdown&lt;/code&gt;). The &lt;code&gt;s&lt;/code&gt; means &lt;em&gt;system&lt;/em&gt; or &lt;em&gt;superuser&lt;/em&gt;, but it does &lt;strong&gt;not&lt;/strong&gt; mean that every system-related program must be in &lt;code&gt;/sbin&lt;/code&gt;, nor that only root can execute its files. On many modern distributions both are compatibility links into &lt;code&gt;/usr/bin&lt;/code&gt; and &lt;code&gt;/usr/sbin&lt;/code&gt; as part of a merged-&lt;code&gt;/usr&lt;/code&gt; layout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/usr&lt;/code&gt; (Most installed software):&lt;/strong&gt; Despite its historical name, &lt;code&gt;/usr&lt;/code&gt; is not the same as a user's home directory. It commonly holds the bulk of installed programs, shared libraries, documentation, and shared data—for example, under &lt;code&gt;/usr/bin&lt;/code&gt;, &lt;code&gt;/usr/lib&lt;/code&gt;, and &lt;code&gt;/usr/share&lt;/code&gt;. A package-installed application such as Firefox may place its executable in &lt;code&gt;/usr/bin&lt;/code&gt;, libraries in &lt;code&gt;/usr/lib&lt;/code&gt;, and desktop metadata in &lt;code&gt;/usr/share/applications&lt;/code&gt;. Google Chrome's &lt;code&gt;.deb&lt;/code&gt; package commonly keeps the application files under &lt;code&gt;/opt/google/chrome&lt;/code&gt; while placing a launcher or symlink in &lt;code&gt;/usr/bin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/lib&lt;/code&gt; &amp;amp; &lt;code&gt;/lib64&lt;/code&gt; (Shared Libraries):&lt;/strong&gt; These hold libraries needed by essential programs and, on some systems, the dynamic loader. As with &lt;code&gt;/bin&lt;/code&gt;, they may be compatibility links to locations under &lt;code&gt;/usr&lt;/code&gt; on a merged-&lt;code&gt;/usr&lt;/code&gt; system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/usr/local&lt;/code&gt; (Administrator-installed local software):&lt;/strong&gt; Software installed manually by the system administrator traditionally goes here, such as &lt;code&gt;/usr/local/bin&lt;/code&gt; and &lt;code&gt;/usr/local/lib&lt;/code&gt;. It is intended to remain separate from files managed by the distribution's package manager.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/opt&lt;/code&gt; (Self-contained optional applications):&lt;/strong&gt; Large or third-party applications that keep their files together may be installed under &lt;code&gt;/opt&lt;/code&gt;, for example &lt;code&gt;/opt/vendor-app&lt;/code&gt;. There is no universal “X folder” for applications: the location depends on the packaging method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-user applications:&lt;/strong&gt; A user can install programs without affecting the whole system, commonly under &lt;code&gt;~/.local/bin&lt;/code&gt; and &lt;code&gt;~/.local/share&lt;/code&gt;. Snap and Flatpak applications use their own layouts (often &lt;code&gt;/snap&lt;/code&gt; and &lt;code&gt;/var/lib/flatpak&lt;/code&gt;). These are conventions, not replacements for learning &lt;code&gt;/usr&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful rule of thumb is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Installation style&lt;/th&gt;
&lt;th&gt;Common locations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Distribution package (&lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt;, &lt;code&gt;pacman&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/usr/bin&lt;/code&gt;, &lt;code&gt;/usr/lib&lt;/code&gt;, &lt;code&gt;/usr/share&lt;/code&gt;, with configuration in &lt;code&gt;/etc&lt;/code&gt; and changing data in &lt;code&gt;/var&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manually installed administrator software&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/usr/local/bin&lt;/code&gt;, &lt;code&gt;/usr/local/lib&lt;/code&gt;, or &lt;code&gt;/opt/&amp;lt;application&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-user software&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.local/bin&lt;/code&gt;, &lt;code&gt;~/.local/lib&lt;/code&gt;, and &lt;code&gt;~/.local/share&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snap or Flatpak&lt;/td&gt;
&lt;td&gt;Their package-specific locations and runtime namespaces&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The exact layout can vary. To find the files owned by a package, use the package manager rather than guessing—for example, &lt;code&gt;dpkg -L firefox&lt;/code&gt; on Debian/Ubuntu or &lt;code&gt;rpm -ql firefox&lt;/code&gt; on Fedora-based systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  📂 The Settings &amp;amp; Variable Data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/etc&lt;/code&gt; (System Configuration):&lt;/strong&gt; Historically, the name came from &lt;em&gt;"et cetera,"&lt;/em&gt; . Today, &lt;code&gt;/etc&lt;/code&gt; conventionally contains host-specific, system-wide configuration, such as service, network, and account-related settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/var&lt;/code&gt; (Variable Data):&lt;/strong&gt; Short for &lt;strong&gt;variable&lt;/strong&gt;. Unlike mostly static program files, &lt;code&gt;/var&lt;/code&gt; holds data that changes during normal operation—often logs (&lt;code&gt;/var/log&lt;/code&gt;), caches, mail queues, spool files, and application state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📂 Runtime, Temporary, and Kernel Interfaces
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/run&lt;/code&gt; (Runtime State):&lt;/strong&gt; This holds volatile state created since boot, such as PID files, sockets, and runtime service data. It is typically mounted as &lt;code&gt;tmpfs&lt;/code&gt;, so its contents normally disappear when the system shuts down or reboots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/tmp&lt;/code&gt; (Temporary Scratchpad):&lt;/strong&gt; Applications use this for temporary workspace files. It may be disk-backed or mounted as &lt;code&gt;tmpfs&lt;/code&gt;; cleanup timing and whether contents survive a reboot depend on the distribution and system configuration. Do not use it for data you need to keep.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/dev&lt;/code&gt; (Device Interfaces):&lt;/strong&gt; This is where device files and pseudo-devices are exposed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/proc&lt;/code&gt; &amp;amp; &lt;code&gt;/sys&lt;/code&gt; (Kernel Interfaces):&lt;/strong&gt; These are virtual filesystems provided by the kernel rather than ordinary files stored on disk. &lt;code&gt;/proc&lt;/code&gt; exposes process and kernel information; &lt;code&gt;/sys&lt;/code&gt; exposes devices, drivers, and other kernel objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/boot&lt;/code&gt; (Boot files):&lt;/strong&gt; Contains files needed to boot Linux, such as the kernel and initramfs. Some systems use a separate filesystem mounted here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/mnt&lt;/code&gt; and &lt;code&gt;/media&lt;/code&gt; (Mount points):&lt;/strong&gt; &lt;code&gt;/mnt&lt;/code&gt; is a conventional temporary mount point for an administrator; &lt;code&gt;/media&lt;/code&gt; is commonly used for removable media mounted for a desktop user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/srv&lt;/code&gt; (Service data):&lt;/strong&gt; A conventional location for data served by services, such as a website or file server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/lost+found&lt;/code&gt; (Filesystem recovery):&lt;/strong&gt; On many &lt;code&gt;ext&lt;/code&gt; filesystems, this directory holds recovered fragments after filesystem repair. It may not exist on other filesystem types.&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkb22tp005i0dk3yu8fft.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkb22tp005i0dk3yu8fft.png" alt="linux-directory-map" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The major Linux directories grouped by purpose.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Crucial Navigational Shortcuts
&lt;/h2&gt;

&lt;p&gt;To explore this tree yourself in the terminal, you only need a few simple commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pwd&lt;/code&gt; (Print Working Directory): Tells you exactly where you are in the tree.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; (Change Directory): Moves you to another folder.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cd ~&lt;/code&gt; takes you straight back to your safe and cozy home directory.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd ..&lt;/code&gt; moves you up one level (closer to the &lt;code&gt;/&lt;/code&gt; root).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls&lt;/code&gt;: Lists the contents of the directory you are in.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls -la&lt;/code&gt;: Includes hidden entries (names beginning with &lt;code&gt;.&lt;/code&gt;), permissions, owners, sizes, and timestamps.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;man &amp;lt;command&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;command&amp;gt; --help&lt;/code&gt;: Reads local documentation and usage options.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;which &amp;lt;command&amp;gt;&lt;/code&gt; or &lt;code&gt;command -v &amp;lt;command&amp;gt;&lt;/code&gt;: Shows which executable the shell would run. Use &lt;code&gt;type -a &amp;lt;command&amp;gt;&lt;/code&gt; to also see aliases and all matching entries in &lt;code&gt;PATH&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Paths, &lt;code&gt;PATH&lt;/code&gt;, and permissions
&lt;/h3&gt;

&lt;p&gt;A path beginning with &lt;code&gt;/&lt;/code&gt; is &lt;strong&gt;absolute&lt;/strong&gt;: &lt;code&gt;/etc/hosts&lt;/code&gt; means the same thing no matter where you are. A path without that slash is &lt;strong&gt;relative&lt;/strong&gt; to the current directory: &lt;code&gt;notes/today.md&lt;/code&gt;. &lt;code&gt;.&lt;/code&gt; means the current directory and &lt;code&gt;..&lt;/code&gt; means its parent; &lt;code&gt;~&lt;/code&gt; is expanded by the shell to the current user's home directory.&lt;/p&gt;

&lt;p&gt;When you type &lt;code&gt;chrome&lt;/code&gt;, the shell searches the directories in the &lt;code&gt;PATH&lt;/code&gt; environment variable, usually including &lt;code&gt;/usr/local/bin&lt;/code&gt;, &lt;code&gt;/usr/bin&lt;/code&gt;, and possibly &lt;code&gt;~/.local/bin&lt;/code&gt;. The directory where a program is stored and the permissions needed to run it are separate concerns. A binary in &lt;code&gt;/usr/bin&lt;/code&gt; is not automatically “for root,” and a binary in &lt;code&gt;/usr/sbin&lt;/code&gt; is not automatically inaccessible to regular users.&lt;/p&gt;

&lt;p&gt;Linux also uses ownership and permission bits on filesystem objects. Inspect them with &lt;code&gt;ls -l&lt;/code&gt;; use &lt;code&gt;sudo&lt;/code&gt; only when an operation genuinely requires elevated privileges, and take extra care with commands that modify &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/usr&lt;/code&gt;, or &lt;code&gt;/var&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pro-Tip: Visualizing the Tree
&lt;/h3&gt;

&lt;p&gt;You can install a tool called &lt;code&gt;tree&lt;/code&gt; using your package manager (like &lt;code&gt;sudo apt install tree&lt;/code&gt; on Ubuntu). Running the following command will print a level-1 overview of the directories visible below &lt;code&gt;/&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;tree &lt;span class="nt"&gt;-L&lt;/span&gt; 1 /
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tree&lt;/code&gt; may not be installed, and some directories will produce permission warnings. A portable alternative is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;findmnt                 &lt;span class="c"&gt;# show mounted filesystems and mount points&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-ld&lt;/span&gt; / /home /usr /var &lt;span class="c"&gt;# inspect selected directories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. A Few Advanced Checks
&lt;/h2&gt;

&lt;p&gt;The visible directory tree is a namespace assembled from multiple filesystems. These commands help connect paths to storage and programs:&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;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; /home              &lt;span class="c"&gt;# filesystem containing /home and its free space&lt;/span&gt;
&lt;span class="nb"&gt;du&lt;/span&gt; &lt;span class="nt"&gt;-sh&lt;/span&gt; ~/Downloads       &lt;span class="c"&gt;# space used by one directory&lt;/span&gt;
findmnt /                &lt;span class="c"&gt;# filesystem mounted at the root&lt;/span&gt;
&lt;span class="nb"&gt;readlink&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# resolve a symlink to its target&lt;/span&gt;
file /usr/bin/ls         &lt;span class="c"&gt;# identify a file's type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not assume that every directory consumes space on the root disk: &lt;code&gt;/home&lt;/code&gt;, &lt;code&gt;/boot&lt;/code&gt;, &lt;code&gt;/var&lt;/code&gt;, or even &lt;code&gt;/tmp&lt;/code&gt; may be separate mounts. Likewise, &lt;code&gt;/proc&lt;/code&gt;, &lt;code&gt;/sys&lt;/code&gt;, and often &lt;code&gt;/run&lt;/code&gt; are virtual or memory-backed filesystems rather than permanent disk storage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary Cheat Sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directory&lt;/th&gt;
&lt;th&gt;What Lives Here?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The root start of the filesystem tree.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/home&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Personal folders for regular users.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/etc&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;System configurations and settings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/bin&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traditionally, essential commands such as &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;cat&lt;/code&gt;; often a link into &lt;code&gt;/usr/bin&lt;/code&gt; today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/sbin&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traditionally, essential system-administration commands; often a link into &lt;code&gt;/usr/sbin&lt;/code&gt; today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/usr&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Distribution-managed programs, libraries, and shared data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/usr/local&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Locally installed administrator-managed software.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/opt&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optional or third-party self-contained applications.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/var&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Variable files that change, such as logs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/run&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Volatile runtime state, typically stored in &lt;code&gt;tmpfs&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;/tmp&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Temporary application files; cleanup behavior is system-dependent.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Big Picture: A Deep Dive into Linux Architecture</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Thu, 18 Dec 2025 15:20:37 +0000</pubDate>
      <link>https://dev.to/thenanjay/the-big-picture-a-deep-dive-into-linux-architecture-2if</link>
      <guid>https://dev.to/thenanjay/the-big-picture-a-deep-dive-into-linux-architecture-2if</guid>
      <description>&lt;p&gt;As DevOps engineers, we often get caught up in the high-level tools—Kubernetes, Docker, Jenkins. We treat the server as a black box that just "runs things." But to truly master the cloud, you have to understand the engine that powers it all: &lt;strong&gt;The Linux Operating System.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've been revisiting the fundamentals of Linux architecture, specifically looking at how the pieces fit together from the hardware up. Here is "The Big Picture" of what actually happens inside your server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Layers of Reality
&lt;/h2&gt;

&lt;p&gt;At its core, a Linux system is an abstraction machine. It takes complex, messy hardware and turns it into clean, usable software interfaces. It does this through three distinct layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Hardware (The Foundation)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Kernel (The Manager)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Space (The Interface)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Hardware: The Raw Power
&lt;/h3&gt;

&lt;p&gt;This is the physical reality—the CPU, the RAM (Main Memory), the hard disks, and the network cards.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Constraint:&lt;/strong&gt; Hardware is dumb. A CPU only knows how to execute simple instructions. A disk only knows how to store bits. Without management, two programs would fight over the same piece of memory, crashing the system instantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The Kernel: The Boss
&lt;/h3&gt;

&lt;p&gt;This is the heart of Linux. The Kernel is the &lt;em&gt;only&lt;/em&gt; program that speaks directly to the hardware. It acts as the strict manager of the system's resources. Its primary jobs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Process Management:&lt;/strong&gt; It decides which program gets to use the CPU and for how long (Time Slicing). It creates the illusion that your browser and your terminal are running at the same time, when in reality, they are rapidly switching turns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device Drivers:&lt;/strong&gt; It translates generic commands ("Write file") into specific electrical signals for your specific SSD or Hard Drive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Management:&lt;/strong&gt; It splits the RAM into private chunks. This leads us to the most important concept in OS architecture: &lt;strong&gt;The Split.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Great Divide: Kernel Space vs. User Space
&lt;/h3&gt;

&lt;p&gt;To prevent chaos, Linux divides the system memory into two distinct zones. This isn't just a software rule; it is enforced by the hardware (CPU) itself using &lt;strong&gt;Protection Rings&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kernel Space (Ring 0)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The VIP Zone:&lt;/strong&gt; This is the reserved memory where the Kernel executes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privilege:&lt;/strong&gt; In Kernel Space, code has &lt;strong&gt;unrestricted access&lt;/strong&gt; to the hardware. It can write to any address in RAM, stop the CPU, or wipe the disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Risk:&lt;/strong&gt; If code crashes here, the entire system halts (Kernel Panic). This is why you cannot just run any random script in Kernel Space.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  User Space (Ring 3)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Sandbox:&lt;/strong&gt; This is where your applications live (Nginx, Python, Chrome, Bash).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restricted Memory:&lt;/strong&gt; Programs here cannot see physical RAM directly. The Kernel gives them a "Virtual Memory" address.

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Illusion:&lt;/em&gt; Program A thinks it has address &lt;code&gt;0x100&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Reality:&lt;/em&gt; The Kernel maps that &lt;code&gt;0x100&lt;/code&gt; to a safe physical spot in RAM.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protection:&lt;/strong&gt; If Program A tries to read Program B's memory, the CPU detects a violation and the Kernel steps in to kill Program A (Segmentation Fault). This ensures one bad app cannot crash the whole server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. User Space: Where We Live
&lt;/h3&gt;

&lt;p&gt;This is where everything else happens. Your shell (Bash/Zsh), your web server (Nginx), your text editor (Vim), and even your graphical desktop—they all run in &lt;strong&gt;User Space&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Critical Distinction:&lt;/strong&gt; Programs in User Space &lt;em&gt;cannot&lt;/em&gt; access hardware directly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;ls&lt;/code&gt; wants to read a directory, it cannot touch the disk.&lt;/li&gt;
&lt;li&gt;It must ask the Kernel to do it.&lt;/li&gt;
&lt;li&gt;This request is called a &lt;strong&gt;System Call (syscall)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters for DevOps
&lt;/h2&gt;

&lt;p&gt;Understanding this separation explains why "sudo" exists.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Space&lt;/strong&gt; is restricted to protect the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Kernel&lt;/strong&gt; has "Rootly powers" to touch hardware and memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run a Docker container, you aren't creating a new machine; you are creating a new isolated area in &lt;strong&gt;User Space&lt;/strong&gt;, sharing the same &lt;strong&gt;Kernel&lt;/strong&gt;. This efficiency is why containers took over the world.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Linux isn't just a collection of commands. It's a carefully orchestrated dance between processes demanding resources and a Kernel managing them. As I dig deeper into the system internals, the "magic" of commands like &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, and &lt;code&gt;ps&lt;/code&gt; starts to look a lot more like logic.&lt;/p&gt;

&lt;p&gt;Next up: Diving into the directory hierarchy and the secrets of the shell.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am documenting my journey of mastering DevOps by going deep into the internals that power the Cloud. Follow along as I break down the systems we build upon every day.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>cloud</category>
      <category>kernal</category>
      <category>devops</category>
    </item>
    <item>
      <title>Understanding DNS: From Root Servers to resolv.conf</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Sun, 07 Sep 2025 18:12:16 +0000</pubDate>
      <link>https://dev.to/thenanjay/understanding-dns-from-root-servers-to-resolvconf-4e6a</link>
      <guid>https://dev.to/thenanjay/understanding-dns-from-root-servers-to-resolvconf-4e6a</guid>
      <description>&lt;p&gt;When you type &lt;code&gt;google.com&lt;/code&gt; in your browser, it feels instant. But behind the scenes, there’s a powerful system mapping human-readable domains to machine-friendly IPs: &lt;strong&gt;DNS (Domain Name System)&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;For DevOps engineers, DNS is more than just theory—it’s at the heart of &lt;strong&gt;application availability, cluster networking, and troubleshooting&lt;/strong&gt;. Let’s break down how DNS works and why it matters in real-world DevOps.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 1. Root Servers – The Internet’s Directory
&lt;/h2&gt;

&lt;p&gt;Every DNS query starts with the &lt;strong&gt;root servers&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
There are &lt;strong&gt;13 named root server clusters (A–M)&lt;/strong&gt;, but thanks to &lt;strong&gt;anycast&lt;/strong&gt;, they exist as &lt;strong&gt;hundreds of distributed servers&lt;/strong&gt; worldwide.  &lt;/p&gt;

&lt;p&gt;Here’s the &lt;strong&gt;step-by-step flow&lt;/strong&gt; when you query &lt;code&gt;google.com&lt;/code&gt;:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Browser/OS Check:&lt;/strong&gt; Browser checks cache, OS cache, and &lt;code&gt;/etc/hosts&lt;/code&gt;. If no record, it queries the configured resolver (e.g., 8.8.8.8).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursive Resolver → Root Server:&lt;/strong&gt; Resolver doesn’t know &lt;code&gt;google.com&lt;/code&gt;, so it asks a &lt;strong&gt;root server&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root Server Response:&lt;/strong&gt; Root server says, “I don’t know google.com, but I know who manages &lt;code&gt;.com&lt;/code&gt;. Go ask the &lt;code&gt;.com&lt;/code&gt; TLD server.”
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLD Server:&lt;/strong&gt; &lt;code&gt;.com&lt;/code&gt; server responds, “I don’t know the IP, but here’s the authoritative server for google.com.”
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authoritative Server:&lt;/strong&gt; Google’s DNS replies: “&lt;code&gt;google.com&lt;/code&gt; = 142.250.72.14.”
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Final Step:&lt;/strong&gt; Resolver caches it, and your browser connects directly to that IP.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;📌 &lt;strong&gt;DevOps Use Case:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you deploy &lt;code&gt;myapp.dev&lt;/code&gt; on AWS and configure it in Route53, DNS propagation follows this chain. A single misstep (e.g., wrong nameserver delegation) = app unreachable. Tools like &lt;code&gt;dig&lt;/code&gt; or &lt;code&gt;nslookup&lt;/code&gt; help trace where it fails.  &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%2F3b5lxx0knbiqdxgw3pqn.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%2F3b5lxx0knbiqdxgw3pqn.png" alt="dns-flow" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🔑 2. Anycasting of Root Servers – Why DNS is Fast &amp;amp; Resilient
&lt;/h2&gt;

&lt;p&gt;Root servers aren’t single machines. They use &lt;strong&gt;anycast routing&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple servers worldwide share the &lt;strong&gt;same IP address&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;When you query, BGP routing ensures you hit the &lt;strong&gt;closest available root server&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;This reduces latency and increases fault tolerance.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 &lt;strong&gt;DevOps Use Case:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For global apps (deployed in Mumbai + Virginia), anycasting ensures &lt;strong&gt;users always hit the nearest DNS server&lt;/strong&gt;, speeding up requests. Without it, DNS would be a massive bottleneck.  &lt;/p&gt;


&lt;h2&gt;
  
  
  🔑 3. Port 53 – The Gateway for DNS
&lt;/h2&gt;

&lt;p&gt;DNS typically uses &lt;strong&gt;port 53&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UDP/53&lt;/strong&gt; → Default for queries (fast, lightweight).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TCP/53&lt;/strong&gt; → Used if the response is too large (e.g., DNSSEC, zone transfers).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 &lt;strong&gt;DevOps Use Case:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If your &lt;strong&gt;firewall or Kubernetes NetworkPolicy blocks port 53&lt;/strong&gt;, pods can’t resolve domains (&lt;code&gt;curl google.com&lt;/code&gt; fails inside containers). Always check port 53 when debugging DNS issues in clusters.  &lt;/p&gt;


&lt;h2&gt;
  
  
  🔑 4. resolv.conf – The Resolver Configuration
&lt;/h2&gt;

&lt;p&gt;On Linux/macOS, &lt;code&gt;/etc/resolv.conf&lt;/code&gt; tells your system &lt;strong&gt;which DNS servers to use&lt;/strong&gt;.  &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;nameserver&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;.&lt;span class="m"&gt;8&lt;/span&gt;.&lt;span class="m"&gt;8&lt;/span&gt;.&lt;span class="m"&gt;8&lt;/span&gt;      &lt;span class="c"&gt;# Google DNS
&lt;/span&gt;&lt;span class="n"&gt;nameserver&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;      &lt;span class="c"&gt;# Cloudflare DNS
&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;.&lt;span class="n"&gt;svc&lt;/span&gt;.&lt;span class="n"&gt;cluster&lt;/span&gt;.&lt;span class="n"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;nameserver&lt;/code&gt; lines specify where queries go first.
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;search&lt;/code&gt; directive is critical in Kubernetes:

&lt;ul&gt;
&lt;li&gt;You can just run &lt;code&gt;ping myservice&lt;/code&gt; in a pod.
&lt;/li&gt;
&lt;li&gt;Behind the scenes, it expands to &lt;code&gt;myservice.default.svc.cluster.local&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 &lt;strong&gt;DevOps Use Case:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If services in Kubernetes aren’t resolving, check &lt;code&gt;/etc/resolv.conf&lt;/code&gt; inside pods. Misconfigured &lt;code&gt;search&lt;/code&gt; domains break &lt;strong&gt;service discovery&lt;/strong&gt;.  &lt;/p&gt;


&lt;h2&gt;
  
  
  🔑 5. hosts File – Manual Overrides
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/etc/hosts&lt;/code&gt; file maps hostnames to IP addresses before DNS is queried.  &lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="m"&gt;127&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;    &lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;span class="m"&gt;192&lt;/span&gt;.&lt;span class="m"&gt;168&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="n"&gt;staging&lt;/span&gt;.&lt;span class="n"&gt;myapp&lt;/span&gt;.&lt;span class="n"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Checked &lt;strong&gt;before DNS lookup&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Useful for &lt;strong&gt;local testing and overrides&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 &lt;strong&gt;DevOps Use Case:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Point &lt;code&gt;staging.myapp.dev&lt;/code&gt; to a local IP for testing before DNS propagation.
&lt;/li&gt;
&lt;li&gt;Override domains during CI/CD pipeline testing.
&lt;/li&gt;
&lt;li&gt;Debug DNS by bypassing external resolvers.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔑 6. Bonus: Other Important DNS Concepts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recursive Resolvers&lt;/strong&gt; → Google DNS (8.8.8.8), Cloudflare DNS (1.1.1.1), or your ISP.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authoritative Servers&lt;/strong&gt; → Store the final answer for a domain (managed via Route53, Cloudflare, GoDaddy, etc.).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS Caching&lt;/strong&gt; → Reduces latency, but wrong TTL = stale records.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS Propagation&lt;/strong&gt; → Global delay when records change (can take minutes to hours).
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Real-World Scenarios Where DNS Breaks DevOps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pods can’t resolve services&lt;/strong&gt; → CoreDNS misconfigured in Kubernetes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App deployed but unreachable&lt;/strong&gt; → DNS record missing or not propagated.  👉 Coming up next in my Advanced DevOps series: “Kubernetes Networking Demystified: From Pod-to-Pod Communication to Ingress”. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL cert failure&lt;/strong&gt; → Domain points to wrong IP.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-region latency&lt;/strong&gt; → Not using latency-based DNS routing (Route53, Cloudflare).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD tests failing&lt;/strong&gt; → Use &lt;code&gt;/etc/hosts&lt;/code&gt; override to simulate new environments.
&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;DNS is the hidden backbone of the internet. For DevOps engineers, understanding &lt;strong&gt;root servers, anycast, port 53, resolv.conf, and hosts&lt;/strong&gt; is more than academic—it’s practical.  &lt;/p&gt;

&lt;p&gt;The next time a pod can’t reach a service or your new domain fails to resolve, you’ll know exactly where to look in the chain.  &lt;/p&gt;




</description>
      <category>devops</category>
      <category>networking</category>
      <category>cloud</category>
      <category>devopscommunity</category>
    </item>
    <item>
      <title>Dockerfile Anti-Patterns: What Not to Do</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Tue, 26 Nov 2024 09:29:16 +0000</pubDate>
      <link>https://dev.to/thenanjay/dockerfile-anti-patterns-what-not-to-do-188a</link>
      <guid>https://dev.to/thenanjay/dockerfile-anti-patterns-what-not-to-do-188a</guid>
      <description>&lt;p&gt;Docker is an essential tool for modern software development, offering efficiency and scalability in building, shipping, and running applications. However, writing an efficient and maintainable Dockerfile is not always straightforward. Many developers, especially beginners, unknowingly introduce anti-patterns that can lead to bloated images, slow builds, or even security vulnerabilities.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll explore some common Dockerfile anti-patterns, their consequences, and best practices to avoid them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Using Large Base Images&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Choosing a heavy, general-purpose base image, such as &lt;code&gt;ubuntu:latest&lt;/code&gt; or &lt;code&gt;debian:latest&lt;/code&gt;, for simple applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Large base images increase the size of your Docker image unnecessarily, leading to longer build and deployment times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use minimal base images, such as alpine, whenever possible. For example, instead of:&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; ubuntu:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use:&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; alpine:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This drastically reduces the size of the image, often by hundreds of megabytes.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. Failing to Leverage Multi-Stage Builds&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Including build tools, dependencies, and artifacts in the final image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This makes the image unnecessarily large and exposes tools and files that aren’t required in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use multi-stage builds to separate build-time dependencies from the final runtime image. For example:&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="c"&gt;# Stage 1: Build&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&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; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; myapp

&lt;span class="c"&gt;# Stage 2: Runtime&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:latest&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; --from=builder /app/myapp .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./myapp"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that only the necessary runtime files are included in the final image.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. Using latest Tag for Base Images&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pulling a base image with the latest tag.&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:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The latest tag can lead to inconsistent builds if the image updates. This unpredictability can cause issues in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Specify a fixed version tag for consistency and reproducibility. For example:&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:18&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures your build uses the same version every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Excessive Layering&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Splitting every command into a separate layer.&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;RUN &lt;/span&gt;apt-get update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each RUN instruction creates a new layer, increasing the image size and making it harder to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Combine related commands into a single RUN instruction.&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;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    curl &lt;span class="se"&gt;\
&lt;/span&gt;    vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;5. Ignoring .dockerignore&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Failing to exclude unnecessary files from the build context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your build context contains unnecessary files, such as .git directories or large media files, the build process slows down significantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.dockerignore&lt;/code&gt; file to exclude unnecessary files and directories. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.git
node_modules
*.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces the build context size, speeding up builds.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Hardcoding Secrets in Dockerfile&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Embedding sensitive information, such as API keys or database credentials, in your Dockerfile.&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;ENV&lt;/span&gt;&lt;span class="s"&gt; API_KEY=supersecretkey&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Secrets embedded in images can be extracted, posing a significant security risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use environment variables or secret management tools to handle sensitive data securely. For example, use Docker’s secrets management in swarm or Kubernetes secrets.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;7. Not Cleaning Up After Installation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Leaving behind unnecessary files after package installation.&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;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    curl &lt;span class="se"&gt;\
&lt;/span&gt;    vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Temporary files from installations increase the size of your image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clean up temporary files after installation.&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;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    curl &lt;span class="se"&gt;\
&lt;/span&gt;    vim &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;8. Missing a Specific CMD or ENTRYPOINT&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Anti-Pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Relying on the default shell behavior instead of defining a specific &lt;code&gt;CMD&lt;/code&gt; or &lt;code&gt;ENTRYPOINT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It’s a Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It leads to ambiguity and makes the container harder to use and debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Specify the intended command or entry point for your application.&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;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, if you need a more robust setup:&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;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["python"]&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Writing an efficient Dockerfile is both an art and a science. Avoiding these anti-patterns will result in smaller, faster, and more secure Docker images that are easier to maintain and deploy.&lt;/p&gt;

&lt;p&gt;Take the time to review your Dockerfiles and incorporate these best practices into your workflow. With consistent improvements, you’ll ensure your Dockerized applications run smoothly and efficiently.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>container</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Docker Layer Caching Explained: Tips to Improve Build Times</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Tue, 19 Nov 2024 10:59:30 +0000</pubDate>
      <link>https://dev.to/thenanjay/docker-layer-caching-explained-tips-to-improve-build-times-6kc</link>
      <guid>https://dev.to/thenanjay/docker-layer-caching-explained-tips-to-improve-build-times-6kc</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In our previous discussion on Docker image optimization, we focused on reducing image size to achieve faster deployments and lower storage costs. Now, let’s address another vital aspect of Docker workflows: build speed.&lt;/p&gt;

&lt;p&gt;The time it takes to build a Docker image can significantly impact your development and deployment cycles. Fortunately, Docker offers a powerful feature called layer caching that can drastically reduce build times by reusing unchanged layers from previous builds.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll dive into how Docker layer caching works, practical tips to use it effectively, and common pitfalls to avoid.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What Is Docker Layer Caching?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Docker images are constructed layer by layer, with each instruction in the Dockerfile creating a new layer. &lt;/p&gt;

&lt;p&gt;For example:&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:16  &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="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .  &lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this Dockerfile, each instruction (FROM, WORKDIR, COPY, etc.) generates a new layer in the image. Docker saves these layers in the cache. If a subsequent build encounters an instruction that hasn’t changed, Docker reuses the cached layer instead of recreating it, speeding up the build process.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why Is Layer Caching Important?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster Builds&lt;/strong&gt;: Reusing cached layers reduces the time spent on unchanged instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Development Workflow&lt;/strong&gt;: Iterative changes become quicker to test and deploy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Efficiency&lt;/strong&gt;: Shorter build times reduce compute resource usage in CI/CD pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How Docker Layer Caching Works&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Docker processes the Dockerfile sequentially:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It examines the first instruction.&lt;/li&gt;
&lt;li&gt;If the instruction hasn’t changed since the last build, Docker uses the cached layer.&lt;/li&gt;
&lt;li&gt;Once a layer’s cache is invalidated, all subsequent layers are rebuilt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If COPY package.json changes, the cache for the RUN npm install step will also be invalidated. (same example as above)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instructions after the invalidated layer will not benefit from caching.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices for Leveraging Docker Layer Caching&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Organize Your Instructions Thoughtfully&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To maximize caching, place instructions that rarely change at the top of your Dockerfile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&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="c"&gt;# Better&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.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="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;In this example, updates to your application code (copied in the last step) won’t invalidate the cached npm install layer.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Leverage Multi-Stage Builds&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Multi-stage builds allow you to separate the build and runtime environments, reducing unnecessary layers in the final image.&lt;/p&gt;

&lt;p&gt;Example for Node.js App:&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="c"&gt;# Build Stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder  &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 package-lock.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="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .  &lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build  

&lt;span class="c"&gt;# Runtime Stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine  &lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/build /usr/share/nginx/html  &lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that only the production-ready artifacts are included in the final image, significantly reducing size and build time.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Use .dockerignore to Avoid Irrelevant Files&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Include a .dockerignore file to exclude unnecessary files like .git directories, logs, or node_modules that could invalidate caching.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;node_modules  
*.log  
.git 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Avoid Frequent Changes to Dependency Files&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Modifications to files like package.json or requirements.txt can invalidate cache for subsequent layers. If possible, group and minimize such changes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Combine Commands to Reduce Layers&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each instruction creates a new layer. Combining commands into a single RUN statement minimizes layer count and keeps images compact.&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;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl vim &lt;span class="se"&gt;\ &lt;/span&gt; 
    &amp;amp;&amp;amp; apt-get clean &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or there is one more option, Rather than endless &amp;amp;&amp;amp; \ statements this would be more readable, especially for more complex runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN &amp;lt;&amp;lt;EOF
apt-get update
apt-get install -y curl vim 
apt-get clean
rm -rf /var/lib/apt/lists/*  
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Bump Cache for Layer-Sensitive Changes&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When changes in dependencies (e.g., bumping package.json version) invalidate a cache, consider temporary techniques like pre-defining dependency versions to isolate changes.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Common Pitfalls to Avoid&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Changing Order of Instructions&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rearranging Dockerfile instructions can invalidate the cache for no reason. Be consistent in the order.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Neglecting Cleanup&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Temporary files in one layer persist unless explicitly removed in the same instruction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&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;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl &lt;span class="se"&gt;\ &lt;/span&gt; 
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;
apt-get update
apt-get install -y curl vim 
apt-get clean
rm -rf /var/lib/apt/lists/*  
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Forgetting the Build Context&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Large files in the build context can slow down COPY or ADD instructions and invalidate the cache.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Tools to Enhance Build Speed&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;BuildKit&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Docker BuildKit offers advanced caching mechanisms and parallelism for faster builds.&lt;/p&gt;

&lt;p&gt;In the another blog I will deep dive into Buildkit. &lt;/p&gt;

&lt;p&gt;as of now just Enable BuildKit:&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="nv"&gt;DOCKER_BUILDKIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 docker build &lt;span class="nb"&gt;.&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Layer Caching in CI/CD&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many CI/CD platforms, like GitHub Actions and GitLab CI, support Docker layer caching to avoid rebuilding unchanged layers in every pipeline run.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Docker layer caching is a game-changer for accelerating builds and optimizing your workflows. By structuring your Dockerfile smartly, leveraging tools like BuildKit, and avoiding common pitfalls, you can drastically reduce build times and improve developer productivity.&lt;/p&gt;

&lt;p&gt;Start experimenting with these techniques, and let me know how much faster your builds become! 🚀&lt;/p&gt;

</description>
      <category>docker</category>
      <category>container</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Docker Image Optimization: Reducing Size for Faster Deployments</title>
      <dc:creator>Dhananjay Patel</dc:creator>
      <pubDate>Sat, 16 Nov 2024 14:07:39 +0000</pubDate>
      <link>https://dev.to/thenanjay/docker-image-optimization-reducing-size-for-faster-deployments-489g</link>
      <guid>https://dev.to/thenanjay/docker-image-optimization-reducing-size-for-faster-deployments-489g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A few months ago, while working on a critical deployment for a client, we faced an unexpected issue: the deployment took forever to complete. The culprit? Bloated Docker images. The process was not only frustrating but also led to downtime we couldn’t afford.  &lt;/p&gt;

&lt;p&gt;This experience taught me an important lesson: small changes can make a big impact. By optimizing Docker images, we managed to cut deployment times in half, save storage costs, and improve our CI/CD pipeline's overall efficiency. Today, I’ll share the strategies we used to achieve this transformation.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Why Optimize Docker Images?
&lt;/h2&gt;

&lt;p&gt;If you've ever experienced sluggish builds, long deployment times, or a cluttered registry filled with oversized images, you’re not alone. Here’s why reducing image sizes is crucial:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Faster Builds:&lt;/strong&gt; Your development cycles become quicker, letting you focus on what matters.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Storage:&lt;/strong&gt; Smaller images save disk space in your Docker registries and on your machines.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quicker Deployments:&lt;/strong&gt; Deploying a smaller image over a network is much faster.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security:&lt;/strong&gt; Fewer components mean fewer vulnerabilities.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Day We Shrunk Our Docker Images
&lt;/h2&gt;

&lt;p&gt;I remember the first time I ran &lt;code&gt;docker images&lt;/code&gt; after our optimization efforts. Seeing the "before" and "after" sizes felt like stepping on the weighing scale after weeks of gym sessions—you notice the difference, and it feels rewarding.  &lt;/p&gt;

&lt;p&gt;Here are the exact steps we followed to make that transformation happen:  &lt;/p&gt;




&lt;h2&gt;
  
  
  7 Effective Ways to Optimize Docker Images
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Choose a Minimal Base Image
&lt;/h3&gt;

&lt;p&gt;Instead of starting with &lt;code&gt;ubuntu:latest&lt;/code&gt; or other large images, we switched to &lt;code&gt;alpine&lt;/code&gt;. This one change reduced the image size from 800MB to less than 30MB.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&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; alpine:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Use Multi-Stage Builds
&lt;/h3&gt;

&lt;p&gt;In many projects, such as a React application, we might have build dependencies (like Node.js and npm) that are only required during the build process but not needed in the production image. By using multi-stage builds, we can separate the build environment from the runtime environment, resulting in a much smaller image.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
In this example, we’ll use a multi-stage build for a React app:&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="c"&gt;# Build Stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&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 package-lock.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="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="c"&gt;# Runtime Stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/build /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above Dockerfile&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The first stage uses the official node:16 image to install dependencies, build the React app, and generate static files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second stage uses the smaller nginx:alpine image to serve the built React app.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This multi-stage approach ensures that only the necessary build artifacts (the build directory) are included in the final image, keeping the image size minimal and optimized for production.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Remove Unnecessary Files
&lt;/h3&gt;

&lt;p&gt;While debugging, we often included temporary files in our builds. By adding a &lt;code&gt;.dockerignore&lt;/code&gt; file, we ensured these files never made it into the image.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
*.log
.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Combine and Minimize Layers
&lt;/h3&gt;

&lt;p&gt;Each instruction in a &lt;code&gt;Dockerfile&lt;/code&gt; (e.g., &lt;code&gt;RUN&lt;/code&gt;, &lt;code&gt;COPY&lt;/code&gt;, &lt;code&gt;ADD&lt;/code&gt;) creates a new layer in the Docker image. Too many layers can bloat your image size. By combining multiple instructions into a single &lt;code&gt;RUN&lt;/code&gt; statement, you can reduce the number of layers and optimize the image.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Instead of writing:&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;RUN &lt;/span&gt;apt-get update  
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl vim  
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get clean  
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combine them into one:&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;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl vim &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach minimizes the number of layers and ensures temporary files (e.g., cache) are removed within the same layer, keeping the image smaller and cleaner.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Avoid Installing Unnecessary Dependencies
&lt;/h3&gt;

&lt;p&gt;Initially, our Docker images had extra libraries "just in case." Over time, we realized that this led to bloated images and unnecessary security risks. By specifying only the dependencies that are actually needed for runtime, we kept the image smaller and more secure.  &lt;/p&gt;

&lt;p&gt;For example, instead of installing a large number of libraries for every project, we focused on minimal dependencies and avoided unnecessary packages.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Use &lt;code&gt;docker-slim&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A game-changer for our process was &lt;code&gt;docker-slim&lt;/code&gt;. This tool automatically analyzes your images and reduces their size by removing unnecessary parts, such as unused files, binaries, and libraries, without affecting functionality.  &lt;/p&gt;

&lt;p&gt;We saw an image size reduction of up to 80% using &lt;code&gt;docker-slim&lt;/code&gt;, making it an invaluable tool in our optimization strategy.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command to slim down an image:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  7. Regularly Audit and Prune Images
&lt;/h3&gt;

&lt;p&gt;Docker images accumulate over time, and unused images or layers can take up valuable space. Regularly auditing and pruning unused images helps maintain a clean environment.&lt;/p&gt;

&lt;p&gt;You can remove unused images and layers by running these commands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command to prune unused images:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system prune &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Command to remove all unused images:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image prune &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By incorporating regular pruning into your workflow, you ensure that your Docker environment stays lean and efficient.&lt;/p&gt;




&lt;h2&gt;
  
  
  Measuring Success
&lt;/h2&gt;

&lt;p&gt;After implementing these optimizations, we used &lt;code&gt;docker images&lt;/code&gt; to compare sizes. The results were stunning:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before Optimization:&lt;/strong&gt; 1.2GB
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After Optimization:&lt;/strong&gt; 250MB
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not only did our deployments become faster, but our cloud storage costs also went down significantly.  &lt;/p&gt;




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

&lt;p&gt;Optimizing Docker images might seem like a minor task, but the benefits it brings to your workflows are immense. Whether you’re a solo developer or part of a large team, these strategies can make a real difference.  &lt;/p&gt;

&lt;p&gt;So, what are you waiting for? Dive into your &lt;code&gt;Dockerfile&lt;/code&gt;, start optimizing, and enjoy the perks of leaner, faster deployments.  &lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com" rel="noopener noreferrer"&gt;Docker Official Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/" rel="noopener noreferrer"&gt;Best Practices for Writing Dockerfiles&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;📖 &lt;strong&gt;Love this blog?&lt;/strong&gt; You can also read my articles on &lt;strong&gt;&lt;a href="https://blog.thenanjay.com/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt;&lt;/strong&gt; and follow me there for more tech insights! 🚀  &lt;/p&gt;




</description>
      <category>docker</category>
      <category>container</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
