<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Dev Containers on Bhavya Tiwary</title>
    <link>https://bhavyatiwary.com/tags/dev-containers/</link>
    <description>Recent content in Dev Containers on Bhavya Tiwary</description>
    <image>
      <title>Bhavya Tiwary</title>
      <url>https://bhavyatiwary.com/og.png</url>
      <link>https://bhavyatiwary.com/og.png</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Fri, 07 Nov 2025 23:53:04 +0530</lastBuildDate>
    <atom:link href="https://bhavyatiwary.com/tags/dev-containers/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How to setup a Dev Container on VS Code?</title>
      <link>https://bhavyatiwary.com/posts/dev_container/</link>
      <pubDate>Fri, 07 Nov 2025 23:53:04 +0530</pubDate>
      <guid>https://bhavyatiwary.com/posts/dev_container/</guid>
      <description>A beginner&amp;#39;s guide to setting up a Dev Container in VS Code on Windows with WSL 2, so each project gets its own isolated toolchain.</description>
      <content:encoded><![CDATA[<p>This is a beginner guide to set up a dev container. A development container (or dev container for short) basically is an isolated environment with it&rsquo;s own set of tool that you can use for development. It is especially helpful for languages like Python where they have complex environment management setups (thanks but no thanks pip, anaconda, venv!) or if you do too many projects and don&rsquo;t want to setup all the components from scratch every time.
As I am using Windows currently and it&rsquo;s easier to use a linux container, this guide will be for dev container on VS Code using WSL.</p>
<h2 id="prerequisites-before-we-can-start-setting-up">Prerequisites before we can start setting up</h2>
<h4 id="setting-up-wsl-windows-1011">Setting up WSL (Windows 10/11)</h4>
<p>Windows Subsystem for Linux(WSL) is a component of Microsoft Windows that allows the use of a Linux environment from within Windows without using a VM or dual booting. There are 2 versions- WSL 1 and 2. Both are very different from each other. You can check out their Wikipedia for more details. In this setup, I&rsquo;m using WSL 2 which is a default in the recent versions of Windows (post 2019). WSL 2 uses a Linux kernel– a managed virtual machine via Hyper-V that implements the full Linux kernel. As a result, WSL 2 is compatible with more Linux binaries.</p>
<ul>
<li>
<p>Open a new PowerShell terminal as an admin and run the below command.</p>
<p>wsl &ndash;install<br>
For a specific default distro:
wsl &ndash;install &ndash;d &lt; name&gt;</p>
</li>
</ul>
<p>This will enable WSL2 and install the default distro- Ubuntu which works well for this tutorial but you may go with other distros as well.
If you&rsquo;re facing issues, you can checkout this <a href="https://learn.microsoft.com/en-us/windows/wsl/troubleshooting">link</a>. You may have to enable certain settings.</p>
<ul>
<li>Set up the username and password for the distro. PS- Don&rsquo;t use the default credentials like admin/admin as it&rsquo;s widely available in user manuals/guides and people are aware of it thus making it more vulnerable.</li>
</ul>
<h3 id="install-vs-code-and-docker-desktop">Install VS Code and Docker Desktop</h3>
<p>It&rsquo;s very simple. Just download from the official sources and run the GUI installer.
VSCode is the IDE we&rsquo;re using and Docker Desktop basically is an app that allows users to create, run, update and use docker containers. It let&rsquo;s us interact with the image repos, local images, volumes etc.
For Docker Desktop, remember to check the option to start docker at startup, unless you want to explicitly start the docker service every time manually.</p>
<p>Also, for simplicity sake, we will be using <a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a>. In the future, you may want to install Docker directly on your linux distro if the need arises.</p>
<h3 id="enable-plugins-on-vs-code">Enable plugins on VS Code</h3>
<p>On VS Code enable the plugins:</p>
<ul>
<li>Remote Development- WSL
This plugin lets us use VS Code to build Linux applications that run on the Windows Subsystem for Linux (WSL)</li>
<li>Remote Development- Dev Containers
The extension lets us use a Docker container as a full-featured development environment.</li>
<li>Docker
The Docker Extension Pack makes it easy to build, manage, and deploy containerized applications from Visual Studio Code.</li>
</ul>


<style type="text/css">
    .box-shortcode {
      padding: 1.6em;
      padding-top: 1.4em;
      line-height: 1.4em;
      margin-top: 1em;
      margin-bottom: 2em;
      border-radius: 4px;
      color: #444;
      background: #f3ebe850;
    }

    .box-title {
      margin: -18px -18px 12px;
      padding: 4px 18px;
      border-radius: 4px 4px 0 0;
      font-weight: 700;
      color: var(--content);
      background: #6ab0de;
    }
    .box-shortcode.warning .box-title {
      background: #ff6b6b;
      color: var(--content);
    }
    .box-shortcode.warning {
      background: #ff6b6b4f;
      color: var(--content);
    }
    .box-shortcode.info .box-title {
      background: #0089e488;
      color: var(--content);
    }
    .box-shortcode.info {
      background: #0089e41c;
      box-shadow: 3px 3px 5px #0089e410;
      color: var(--content);
    }
    .box-shortcode.important .box-title {
      background: #f7ec2c;
    }
    .box-shortcode.important {
      background: #f7ec2c7d;
    }
    .box-shortcode.tip .box-title {
      background: #a3ffa34d;
    }
    .box-shortcode.tip {
      background: #a3ffa34d;
      box-shadow: 3px 3px 5px #0089e410;
    }
    .icon-box {
      display: inline-flex;
      align-self: center;
      margin-right: 8px;
    }
    .icon-box img,
    .icon-box svg {
      height: 1em;
      width: 1em;
      fill: currentColor;
    }
    .icon-box img,
    .icon-box.baseline svg {
      top: 0.125em;
      position: relative;
    }
    .box-shortcode p {
      margin-bottom: 0.6em;
    }
    .box-shortcode p:first-of-type {
      display: inline;
    }
    .box-shortcode p:nth-of-type(2) {
      margin-top: 0.6em;
    }
    .box-shortcode p:last-child {
      margin-bottom: 0;
    }
  </style>

  
  <svg width="0" height="0" display="none" xmlns="http://www.w3.org/2000/svg">
    <symbol id="tip-box" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">
      <path
        d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"/>
    </symbol>
    <symbol id="important-box" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">
      <path
        d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>
    </symbol>
    <symbol id="warning-box" viewBox="0 0 576 512" preserveAspectRatio="xMidYMid meet">
      <path
        d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/>
    </symbol>
    <symbol id="info-box" viewBox="0 0 512 512" preserveAspectRatio="xMidYMid meet">
      <path
        d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"/>
    </symbol>
  </svg><div class="box box-shortcode info" >
    <span class="icon-box baseline">
      <svg><use href="#info-box"></use></svg>
    </span>
    <p>Always enable plugins from trusted and verified sources as some plugins may have backdoors, cryptojacking malwares etc that will compromise your whole system. In this case, all the three plugins are published by Microsoft so will have the blue tick.</p>
  </div>

<p><img loading="lazy" src="extensions.png" alt="Extensions"  />
</p>
<h2 id="configuring-and-setting-up-the-container">Configuring and setting up the container</h2>
<p>Now that we&rsquo;re done with the prerequsites open a new WSL window by clicking the blue button at the bottom left side corner and choose the first option- New WSL Window.
PS- I have already set up the connection hence it shows as Connect to WSL but if it&rsquo;s the first time you&rsquo;re setting it up it should show as New WSL Window
<img loading="lazy" src="connect.png" alt="The red row points to the button which when clicked shows the options for remote features."  />
</p>
<p>From here onwards we&rsquo;ll be working on Linux.
We want to create a folder to store our project in the WSL Filesystem. In this case, I have created it in the home directory. Run this in your terminal to create the a new directory (mkdir name) and open the directory (cd name) in the terminal.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir dev-container-test <span class="o">&amp;&amp;</span> <span class="nb">cd</span> dev-container-test
</span></span></code></pre></div><p>I&rsquo;m manually creating the necessary files to configure the container but you can also use templates by going to the Command Palette and  selecting the “Add Dev Container Configuration Files” option.</p>
<p>Create a new directory with the name <strong>.devcontainer</strong> with the <strong>.</strong>  and under this directory create <strong>devcontainer.json</strong> ,  <strong>Dockerfile</strong> and <strong>requirements.txt</strong> files.
<img loading="lazy" src="folderstruct.png" alt="This is the how the folder should look like."  />
</p>
<p>Now let&rsquo;s update the files we just created!</p>
<h3 id="devcontainerjson">devcontainer.json</h3>
<p>This file tells VSCode how to build our ebvironment.
Open devcontainer.json and paste this code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// This gives the dev container a name and let&#39;s the machine know to
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// build the container following the Dockerfile instructions.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;dev-container-test&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;build&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;dockerfile&#34;</span><span class="p">:</span> <span class="s2">&#34;Dockerfile&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;customizations&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Configure properties specific to VS Code.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nt">&#34;vscode&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Add extensions you want installed when the container is created.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="nt">&#34;extensions&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;ms-python.python&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;ms-python.vscode-pylance&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// All ports listed here will also be available outside your development
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// container i.e. in your machine’s localhost. By default, Docker
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// encapsulates your application in a box with no contact to the outside
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="c1">// world.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nt">&#34;forwardPorts&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mi">5000</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h3 id="dockerfile">Dockerfile:</h3>
<p>I’m going to use the container as a virtual development environment. So I want to write a <strong>Dockerfile</strong> to build a container image, beginning with the version of Python that I want, and then add all of my dependencies into it.
Open Docker file and paste the below code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-dockerfile" data-lang="dockerfile"><span class="line"><span class="cl">    <span class="c1">#The base image for the container that I have taken from DockerHub (it is hardened and secure to some extent already) </span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    FROM python:3.11-slim<span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="c1"># Disable buffering for Python&#39;s standard output (stdout) and standard error (stderr) streams so that output from Python app, such as Django logs, is sent directly to the container&#39;s logs in real time.      </span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    ENV <span class="nv">PYTHONUNBUFFERED</span><span class="o">=</span><span class="m">1</span>  <span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>     <span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="c1"># Copy python requirements to the docker container and install. Here we&#39;re going to install all our libraries and depndencies. </span><span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    COPY requirements.txt .<span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    <span class="err">
</span></span></span><span class="line"><span class="cl"><span class="err"></span>    RUN python -m pip install -r requirements.txt<span class="err">
</span></span></span></code></pre></div><h3 id="requirements">Requirements</h3>
<p>In this file we&rsquo;ll mention all the dependencies that needs to be downloaded and their versions (optional).  Keeping this very simple with only Pylint which checks for programming errors, style issues, and potential bugs</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">pylint
</span></span></code></pre></div><p>Now we should be good to build and run the docker container. Open the command palette and choose <strong>“Dev Containers: Reopen in Container”</strong>. (If you have already built a container, choose <strong>“Rebuilt and Reopen in Container</strong>” instead.)</p>
<p>Once the container build is over it will open a new workspace where you can start your development. At any point, you can update your config and rebuild the container.<br>
Happy Coding!</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
