<?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[The Real Story of Containerization.]]></title><description><![CDATA[The Real Story of Containerization.]]></description><link>https://containerizationunderhood.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 01 Sep 2026 08:43:44 GMT</lastBuildDate><atom:link href="https://containerizationunderhood.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How Docker Talks to Linux: The Real Story of Containerization]]></title><description><![CDATA[What is a Linux Container?
A Linux container is a lightweight way to run applications in isolation. Think of it as a "box" where you can run a program, and that program won't interfere with other programs running on the same computer. Containers are ...]]></description><link>https://containerizationunderhood.hashnode.dev/how-docker-talks-to-linux-the-real-story-of-containerization</link><guid isPermaLink="true">https://containerizationunderhood.hashnode.dev/how-docker-talks-to-linux-the-real-story-of-containerization</guid><category><![CDATA[SRE]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Shreyas Deshmukh]]></dc:creator><pubDate>Tue, 01 Jul 2025 13:52:09 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-what-is-a-linux-container"><strong>What is a Linux Container?</strong></h1>
<p>A <strong>Linux container</strong> is a lightweight way to run applications in isolation. Think of it as a "box" where you can run a program, and that program won't interfere with other programs running on the same computer. Containers are built using special features of the Linux operating system, and two of the most important features are <strong>namespaces</strong> and <strong>cgroups</strong>.  </p>
<h1 id="heading-what-are-namespaces"><strong>What are Namespaces?</strong></h1>
<p><strong>Namespaces</strong> are like "walls" that separate different parts of the system. They create logical partitions of system resources so that processes (programs) running inside a namespace can only see and interact with their own "world." For example:</p>
<ul>
<li><p>A <strong>PID namespace</strong> isolates process IDs (the unique numbers assigned to running programs).</p>
</li>
<li><p>A <strong>network namespace</strong> isolates network interfaces (like IP addresses).</p>
</li>
<li><p>A <strong>mount namespace</strong> isolates file systems (like directories and files).</p>
</li>
</ul>
<p>In short, namespaces are what make containers feel like their own little "mini-computers" inside the larger system.</p>
<p>What are cgroups (Control Groups)?</p>
<p>While namespaces isolate processes, <strong>cgroups</strong> are used to control how much of the system's resources (like CPU, memory, or disk) a process can use. This ensures that one process doesn't hog all the resources and cause problems for other processes.</p>
<p>Example: PID Namespace</p>
<p>Let's focus on the <strong>PID namespace</strong> to understand how namespaces work.  </p>
<p><strong>Normal System View</strong>: When you run the ps axf command on a Linux system, it shows a list of all the running processes. Each process has a unique <strong>PID</strong> (Process ID). For example: PID , TTY ,STAT ,TIME COMMAND</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751375674963/9374da5f-fffd-42fc-a8e3-da6e620d0443.png" alt class="image--center mx-auto" /></p>
<p>This is the "global" view of all processes running on the system.</p>
<h2 id="heading-creating-a-new-pid-namespace">Creating a New PID Namespace</h2>
<p>Now, let's create a new PID namespace using the unshare command. This command creates a new "box" (namespace) for processes. Here's the command: sudo unshare --fork --pid --mount-proc=/proc /bin/sh</p>
<p>-<strong>fork</strong>: Starts a new process in the new namespace.</p>
<p>-<strong>pid</strong>: Creates a new PID namespace.</p>
<p><strong>-mount-proc=/proc</strong>: Mounts a new /proc directory for the namespace (this is where process information is stored).  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751375848662/f7b5b012-79a8-4a8b-8e55-0bd50651d7ab.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Notice that the shell process (/bin/sh) now has PID 1, and the ps command has PID 2.</p>
</li>
<li><p>All other processes from the "global" system have disappeared! This is because the new namespace isolates the processes inside it.</p>
<p>  <strong>Checking from Outside</strong>: If you open another terminal and run ps axf on the main system, you'll still see all the processes, including the unshare command and the shell process running in the new namespace.<br />  This shows that the processes in the new namespace are still part of the global system, but they are isolated and cannot see the global processes.  </p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751376014948/e44f3e66-0b0d-42af-9042-99816964e34a.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h2 id="heading-why-is-isolation-important"><strong>Why is Isolation Important?</strong></h2>
<ul>
<li><p>The isolation provided by namespaces is useful because it allows you to run programs in their own "box" without interfering with other programs. For example:</p>
<ul>
<li><p>You can run multiple versions of the same program without conflicts.</p>
</li>
<li><p>You can test software in a safe environment without affecting the rest of the system.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-the-problem-resource-usage"><strong>The Problem: Resource Usage</strong></h3>
<p>    Even though namespaces isolate processes, they don't limit how much of the system's resources (like memory or CPU) those processes can use. This can cause problems.</p>
<p>    Example:</p>
<ol>
<li><p>Imagine you have a child namespace with some processes running inside it.</p>
</li>
<li><p>These processes start using a lot of memory, eventually using up all the memory available on the system.</p>
</li>
<li><p>When the system runs out of memory, the Linux kernel activates the <strong>OOM killer</strong> (Out-Of-Memory killer) to free up memory by killing processes.</p>
</li>
<li><p>The OOM killer might kill processes outside the namespace (in the global system), causing problems for other programs.  </p>
<h3 id="heading-solution-cgroups"><strong>Solution: cgroups</strong></h3>
<p> To prevent this, we use <strong>cgroups</strong> to limit how much memory, CPU, or other resources a namespace can use. For example:</p>
<ul>
<li><p>You can set a memory limit for the child namespace so that it cannot use more than a certain amount of memory.</p>
</li>
<li><p>If the processes in the namespace try to use more memory than allowed, they will be stopped, and the rest of the system will remain unaffected.</p>
</li>
</ul>
</li>
</ol>
<h1 id="heading-what-are-cgroups"><strong>What are cgroups?</strong></h1>
<ul>
<li><p><strong>cgroups</strong> (control groups) are a Linux kernel feature that allows you to:</p>
<ol>
<li><p><strong>Group processes</strong> together.</p>
</li>
<li><p><strong>Control and limit</strong> how much of the system's resources (like CPU, memory, disk I/O, etc.) those processes can use.</p>
</li>
</ol>
</li>
</ul>
<p>    This is useful when you want to ensure that one process or group of processes doesn’t consume too many resources and affect the rest of the system<br />    Example: Limiting CPU Usage with cgroups</p>
<p>    Let’s go through the example step by step.</p>
<ol>
<li>Stressing the CPU</li>
</ol>
<p>    First, we run a command that uses 100% of the CPU. The command is:</p>
<p>    yes &gt; /dev/null &amp;</p>
<ul>
<li><p>The yes command generates an infinite stream of "yes" and writes it to /dev/null (a "black hole" where data is discarded).</p>
</li>
<li><p>The &amp; at the end runs the command in the background.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751376535002/72a2b82a-174e-49c1-8063-580710217cc1.png" alt class="image--center mx-auto" /></p>
<p>  Now, if you monitor the system using the top command, you’ll see that the yes process is consuming 100% of the CPU:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751376502742/594975a9-3da2-4d41-89a2-8ba1855e71fe.png" alt class="image--center mx-auto" /></p>
<p>  <strong>Creating a cgroup for CPU</strong></p>
<p>  To limit the CPU usage of the yes process, we use <strong>cgroups</strong>. cgroups are organized as directories under /sys/fs/cgroup/, and each directory represents a resource type (e.g., CPU, memory, etc.).  </p>
<p>  <strong>List available cgroups</strong>: ls /sys/fs/cgroup</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751376691919/910753f4-0528-4305-bf93-852c608da137.png" alt class="image--center mx-auto" /></p>
<p>  The cpu directory is where we control CPU usage.<br />  <strong>Create a new cgroup</strong>: We create a new directory under /sys/fs/cgroup/cpu/ to represent our cgroup. Let’s call it box: <code>mkdir /sys/fs/cgroup/box</code></p>
<p>  <strong>Set CPU limit (50%)</strong></p>
</li>
<li><p><code>cpu.max = &lt;quota&gt; &lt;period&gt;</code><br />  Example: 50% of one core = 50ms per 100ms.</p>
<p>  <strong>echo "50000 100000" | sudo tee /sys/fs/cgroup/box/cpu.max</strong></p>
<ul>
<li><p><code>50000</code> → quota: microseconds of CPU time</p>
</li>
<li><p><code>100000</code> → period: how often the quota resets</p>
</li>
</ul>
</li>
</ul>
<p>        <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751377550558/a98d78fa-b789-4265-bf62-5c1bb2df3eaa.png" alt class="image--center mx-auto" /></p>
<p>        <strong>Assign the process to your cgroup</strong></p>
<h4 id="heading-echo-sudo-tee-sysfscgroupboxcgroupprocs"><code>echo &lt;PID&gt; | sudo tee /sys/fs/cgroup/box/cgroup.procs</code></h4>
<p>        <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751377515926/855a89a2-25ca-450d-96cc-008e7fc3c0ab.png" alt class="image--center mx-auto" /></p>
<p>        <strong>Check the CPU usage again</strong>: Run top again to monitor the system:</p>
<p>        <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751377462996/061a74e4-f65c-40e7-ad54-cc9cf5da7170.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-does-this-work"><strong>How Does This Work?</strong></h2>
<ul>
<li><p>The cpu.cfs_quota_us file sets the maximum amount of CPU time a process in the cgroup can use in a given period.</p>
</li>
<li><p>The default period is 100,000 µs (0.1 seconds), which is controlled by the cpu.cfs_period_us file.</p>
</li>
<li><p>By setting the quota to 50000, we are allowing the process to use 50% of the CPU time in each 0.1-second period.</p>
</li>
</ul>
<h2 id="heading-why-is-this-useful"><strong>Why is This Useful?</strong></h2>
<p>This example shows how <strong>cgroups</strong> can be used to control resource usage. By limiting the CPU usage of the yes process, we ensure that it doesn’t consume all the CPU and leave other processes without enough resources.</p>
<h1 id="heading-containers-and-isolation"><strong>Containers and Isolation</strong></h1>
<p>By combining <strong>namespaces</strong> (for isolation) and <strong>cgroups</strong> (for resource control), we can create fully isolated environments for applications. These environments, called <strong>containers</strong>, allow us to:</p>
<ol>
<li><p>Run applications in isolation (using namespaces).</p>
</li>
<li><p>Control how much CPU, memory, and other resources they can use (using cgroups).</p>
</li>
</ol>
<p>This is the foundation of modern container technologies like <strong>Docker</strong> and <strong>Kubernetes</strong>.</p>
]]></content:encoded></item></channel></rss>