{"id":1598,"date":"2021-05-19T17:23:32","date_gmt":"2021-05-20T00:23:32","guid":{"rendered":"http:\/\/blog.nillsf.com\/?p=1598"},"modified":"2021-05-19T17:23:40","modified_gmt":"2021-05-20T00:23:40","slug":"development-containers-in-visual-studio-code-are-awesome","status":"publish","type":"post","link":"https:\/\/nillsf.com\/index.php\/2021\/05\/19\/development-containers-in-visual-studio-code-are-awesome\/","title":{"rendered":"Development containers in Visual Studio code are awesome"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">As part of my job, I work with multiple languages and multiple tools on a daily basis. Keeping environments up to date and having all the right tools installed can sometimes become a bit of a burden. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I recently started using development containers in Visual Studio Code (VS Code) to help manage this burden. Development containers in VS Code are a way to leverage containers as a remote environment with all required tools and extensions pre-installed. By using containers, you can run multiple environments on your machine without having to install the tools locally. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, I&#8217;m doing some development work right now in Azure PowerShell. I recently bought a new PC, where I have no tools pre-installed.  I&#8217;m going to use a development container where I run PowerShell and Azure PowerShell, to do some coding work for Bellhop.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s get started:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing the required tools<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In order to get devcontainers in VScode to work, you need to install a couple of things:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Docker Desktop (if on Windows, preferably with WSL 2)<\/li><li>VS Code<\/li><li>The Visual Studio Code Remote &#8211; Containers\u00a0extension <\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">To install the first two, I used chocolatey. The following two commands install chocolatey and install Docker Desktop and VS Code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https:\/\/chocolatey.org\/install.ps1'))\nchoco install vscode dockerdesktop -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now a reboot is required. After this reboot, to optimize Docker performance, installing WSL 2 is recommended. For more info on how to do this, please refer to <a href=\"https:\/\/blog.nillsf.com\/index.php\/2020\/02\/17\/setting-up-wsl2-windows-terminal-and-oh-my-zsh\/\">this post<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once WSL is setup, you also need to install the VS Code remote containers extension. To do this, open VS Code, click on the extensions icon, look for &#8220;container&#8221; and click on the install button.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"532\" src=\"\/wp-content\/uploads\/2021\/05\/image-1024x532.png\" alt=\"\" class=\"wp-image-1605\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-1024x532.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-300x156.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-768x399.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-1536x799.png 1536w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image.png 1675w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And you now have the ability to open any folder in a container. Let&#8217;s start with opening an existing repo with a .devcontainer folder:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Opening an existing repo with a devcontainer definition<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For this example, let&#8217;s use an existing git repository with a devcontainer definition. I&#8217;m using <a href=\"https:\/\/github.com\/azure\/bellhop\">Bellhop <\/a>for this example. Bellhop is an open source project I&#8217;m working on, and which I now want to work on from my new desktop. I created a branch with a .devcontainer definition. To get this locally, you can also use the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/Azure\/bellhop.git\ncd bellhop\ngit checkout devcontainers\ncode .<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">These commands will work either from within Windows or from within WSL.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The moment you open this folder in VS Code, VS Code will detect the .devcontainer folder, and will ask you reopen this folder in a container:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"680\" height=\"166\" src=\"\/wp-content\/uploads\/2021\/05\/image-1.png\" alt=\"\" class=\"wp-image-1606\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-1.png 680w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-1-300x73.png 300w\" sizes=\"auto, (max-width: 680px) 100vw, 680px\" \/><figcaption>Notification that shows VS Code detected a devcontainer definition and asks you to open the folder in a container<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If you didn&#8217;t get this notification, you can also get here by opening the command pallet in VS code (CTRL + SHIFT + P) and looking for the action &#8220;Remote-Containers: Reopen in Container&#8230;&#8221;<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"913\" height=\"473\" src=\"\/wp-content\/uploads\/2021\/05\/image-3.png\" alt=\"\" class=\"wp-image-1608\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-3.png 913w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-3-300x155.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-3-768x398.png 768w\" sizes=\"auto, (max-width: 913px) 100vw, 913px\" \/><figcaption>You can use the command palette to reopen a folder in a container.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This will cause VS Code to build the container if this is the first time you&#8217;re opening this repo in the container. If you open the repo again, it will use the same container you used previously, avoiding the time required to build the container.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And once you reopen an existing repo in the container, all tools are installed for you. In the case of the Bellhop container definition, this includes Az PowerShell and Pester, as well as the PowerShell extension for VS Code. As you can see below, this leads to intellisense being available and a Powershell terminal automatically opening as well:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"764\" src=\"\/wp-content\/uploads\/2021\/05\/image-5-1024x764.png\" alt=\"\" class=\"wp-image-1613\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-5-1024x764.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-5-300x224.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-5-768x573.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-5-1536x1146.png 1536w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-5.png 1538w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>No magic here, Az PowerShell, PowerShell extension for VSCode and Intellisense provided by the devcontainer.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The Bellhop repo contains a devcontainer definition already. But what if you don&#8217;t have one ready? I&#8217;ll cover that in the next section.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating a new devcontainer definition<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To create a new devcontainer definition you can use one of two options:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"https:\/\/code.visualstudio.com\/docs\/remote\/create-dev-container\">Write definition from scratch<\/a>.<\/li><li><a href=\"https:\/\/github.com\/microsoft\/vscode-dev-containers\/tree\/master\/containers\">Start from a template<\/a> and edit as needed<\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">I prefer option (2) as it comes with some prebuilt containers. Let&#8217;s explore it here and let&#8217;s try to make a container with Python and the ability to edit Jupyter notebooks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To start, we&#8217;ll need to open a new folder in VS Code. To open a new folder, use the File menu and click open folder and select a new folder.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"450\" height=\"389\" src=\"\/wp-content\/uploads\/2021\/05\/image-16.png\" alt=\"\" class=\"wp-image-1637\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-16.png 450w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-16-300x259.png 300w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><figcaption>Opening a new folder in VS Code<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Next, open the VS code command palette by clicking CTRL+SHIFT+P. In this palette look for the &#8220;Add Development Container Configuration Files&#8221; option.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"910\" height=\"467\" src=\"\/wp-content\/uploads\/2021\/05\/image-19.png\" alt=\"\" class=\"wp-image-1640\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-19.png 910w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-19-300x154.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-19-768x394.png 768w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><figcaption>Adding a devcontainer definition<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Next, you&#8217;ll want to scroll down and select the &#8220;Show All Definitions&#8221; option:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"917\" height=\"522\" src=\"\/wp-content\/uploads\/2021\/05\/image-20.png\" alt=\"\" class=\"wp-image-1641\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-20.png 917w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-20-300x171.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-20-768x437.png 768w\" sizes=\"auto, (max-width: 917px) 100vw, 917px\" \/><figcaption>Showing all definitions<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In that view, you&#8217;ll see a big list of predefined devcontainers. Look for the one called &#8220;Anaconda&#8221; and select that.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"920\" height=\"186\" src=\"\/wp-content\/uploads\/2021\/05\/image-21.png\" alt=\"\" class=\"wp-image-1642\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-21.png 920w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-21-300x61.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-21-768x155.png 768w\" sizes=\"auto, (max-width: 920px) 100vw, 920px\" \/><figcaption>Looking for the anaconda definition<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This will open the devcontainer.json. You don&#8217;t need to make changes to this, you can now build the container. To do this, open the command palette again (CTRL+SHIFT+P) and select the &#8220;rebuild and reopen in container&#8221; option:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"917\" height=\"121\" src=\"\/wp-content\/uploads\/2021\/05\/image-22.png\" alt=\"\" class=\"wp-image-1643\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-22.png 917w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-22-300x40.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-22-768x101.png 768w\" sizes=\"auto, (max-width: 917px) 100vw, 917px\" \/><figcaption>Building the container<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This will build the devcontainer, which will take a couple of minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once the container is built, we can try if Python and Jupyter work well. To do so, let&#8217;s create a new notebook called &#8220;test.ipynb&#8221; (make sure to match the file extension):<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"386\" height=\"181\" src=\"\/wp-content\/uploads\/2021\/05\/image-23.png\" alt=\"\" class=\"wp-image-1644\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-23.png 386w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-23-300x141.png 300w\" sizes=\"auto, (max-width: 386px) 100vw, 386px\" \/><figcaption>Creating a new Jupyter notebook<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The moment you open this file, you&#8217;ll notice that VS Code automatically launches it in a Jupyter notebook editor:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"394\" src=\"\/wp-content\/uploads\/2021\/05\/image-24-1024x394.png\" alt=\"\" class=\"wp-image-1645\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-24-1024x394.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-24-300x115.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-24-768x295.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-24.png 1079w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>When opening the notebook, VS Code automatically opens it in a notebook editor.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And you can work with this as any other notebook. Try for instance to make a small Python loop:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for i in range(10):\n  print(i)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Which you can execute by pressing CTRL+ENTER or use the play icon in the top bar. As you will see, this executes in Python flawlessly:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"\/wp-content\/uploads\/2021\/05\/image-25-1024x576.png\" alt=\"\" class=\"wp-image-1646\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-25-1024x576.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-25-300x169.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-25-768x432.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-25.png 1076w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Executing Python code in the container<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">One cool thing with devcontainers is that the files are still stored locally on your disk, not in the container. For example, for this Python development work, I created a folder in Windows, and opened that in the devcontainer. The file I created in the devcontainer is present on my local disk:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"591\" height=\"274\" src=\"\/wp-content\/uploads\/2021\/05\/image-26.png\" alt=\"\" class=\"wp-image-1647\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-26.png 591w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/image-26-300x139.png 300w\" sizes=\"auto, (max-width: 591px) 100vw, 591px\" \/><figcaption>Files are still available on the local file system<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And now that you have a working devcontainer, you can make changes to either the Dockerfile or the devcontainer.json to customize your environment. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this post I showed you how to create and use VS Code devcontainers. They are amazing! You can work with any tool, any language without having to install anything locally (OK, you need VS Code and Docker). Once you launch a container, you have all the tools, VS Code extensions, intellisense available as if it were installed on your local machine. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>As part of my job, I work with multiple languages and multiple tools on a daily basis. Keeping environments up to date and having all the right tools installed can sometimes become a bit of a burden. I recently started using development containers in Visual Studio Code (VS Code) to help manage this burden. Development [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1648,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,5,31],"tags":[128,55,183],"class_list":["post-1598","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-open-source","category-software-development","tag-containers","tag-software-development","tag-vistual-studio-code"],"jetpack_featured_media_url":"https:\/\/nillsfblog.blob.core.windows.net\/media\/2021\/05\/2021-05-19-17_10_44-Customize-core-dumps-in-Azure-Kubernetes.pptx-Microsoft-PowerPoint-Online-and-.png","_links":{"self":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/1598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/comments?post=1598"}],"version-history":[{"count":6,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/1598\/revisions"}],"predecessor-version":[{"id":1649,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/1598\/revisions\/1649"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/media\/1648"}],"wp:attachment":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/media?parent=1598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/categories?post=1598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/tags?post=1598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}