<?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: Santhosh</title>
    <description>The latest articles on DEV Community by Santhosh (@santhosh_jack).</description>
    <link>https://dev.to/santhosh_jack</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3941040%2Fc6e6e4d1-dc72-4fd7-a99e-da0d165ea513.jpeg</url>
      <title>DEV Community: Santhosh</title>
      <link>https://dev.to/santhosh_jack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/santhosh_jack"/>
    <language>en</language>
    <item>
      <title>I Built My Own Container Runtime from Scratch Using Only Linux (No Docker, No containerd, No LXC)</title>
      <dc:creator>Santhosh</dc:creator>
      <pubDate>Mon, 01 Jun 2026 07:49:28 +0000</pubDate>
      <link>https://dev.to/santhosh_jack/i-built-my-own-container-runtime-from-scratch-using-only-linux-no-docker-no-containerd-no-lxc-3l17</link>
      <guid>https://dev.to/santhosh_jack/i-built-my-own-container-runtime-from-scratch-using-only-linux-no-docker-no-containerd-no-lxc-3l17</guid>
      <description>&lt;p&gt;I’ve been using Docker for a while, but at some point I realized I didn’t actually understand what it was doing under the hood.&lt;br&gt;
How does a process suddenly get its own filesystem, its own network, its own environment?&lt;/p&gt;

&lt;p&gt;So instead of reading more blogs, I decided to build it myself.&lt;br&gt;
No Docker. No containerd. No LXC.&lt;br&gt;
Just namespaces, cgroups, networking, and filesystem isolation.&lt;/p&gt;

&lt;p&gt;That’s how I ended up building &lt;strong&gt;LXR (Linux Container Runtime)&lt;/strong&gt; written in Go, using only Linux primitives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build containers from scratch and make them usable for real development.&lt;/p&gt;

&lt;p&gt;LXR not only creates containers, but also lets you work inside them directly from the browser or terminal, while the runtime handles everything underneath.&lt;/p&gt;

&lt;p&gt;So LXR can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;pull images from Docker Hub&lt;/li&gt;
&lt;li&gt;extract rootfs&lt;/li&gt;
&lt;li&gt;create isolated containers&lt;/li&gt;
&lt;li&gt;configure networking (veth + bridge + IP allocation)&lt;/li&gt;
&lt;li&gt;provide shell access via lxr exec&lt;/li&gt;
&lt;li&gt;run code-server inside containers for browser access&lt;/li&gt;
&lt;/ol&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%2F7rfcrcx4lng07pwzxha6.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%2F7rfcrcx4lng07pwzxha6.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From the outside, it looks simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lxr create &lt;span class="nt"&gt;--name&lt;/span&gt; goCon golang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;But internally&lt;/strong&gt;, this triggers a full setup.&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%2F57w84wfg04r9m64g74rb.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%2F57w84wfg04r9m64g74rb.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F592x9wf8s9yc59vl9hbb.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%2F592x9wf8s9yc59vl9hbb.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;image layers are pulled&lt;/li&gt;
&lt;li&gt;dependencies are installed into the image rootfs&lt;/li&gt;
&lt;li&gt;root filesystem is prepared&lt;/li&gt;
&lt;li&gt;overlay filesystem is created&lt;/li&gt;
&lt;li&gt;networking is configured&lt;/li&gt;
&lt;li&gt;IP is allocated&lt;/li&gt;
&lt;li&gt;container process is started&lt;/li&gt;
&lt;li&gt;code-server is launched&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of this... just to start one container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once containers are running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lxr ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cvdbqh0iqdb6aoxms69.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%2F1cvdbqh0iqdb6aoxms69.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each container has:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;its own PID&lt;/li&gt;
&lt;li&gt;its own IP&lt;/li&gt;
&lt;li&gt;its own network namespace&lt;/li&gt;
&lt;li&gt;its own filesystem (OverlayFS)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, LXR behaves as an real container runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first issue wasn’t networking or filesystem.&lt;br&gt;
It was just starting a process.&lt;/p&gt;

&lt;p&gt;I tried running containers as a non-root user, but it didn’t work the way I expected.Processes failed to start or behaved inconsistently due to restrictions.&lt;/p&gt;

&lt;p&gt;This turned out to be related to how Linux handles namespaces and permissions.&lt;/p&gt;

&lt;p&gt;I’ll cover that part in the upcoming post.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>containers</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
