{"id":56088,"date":"2025-03-25T10:05:00","date_gmt":"2025-03-25T17:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=56088"},"modified":"2025-03-25T10:05:00","modified_gmt":"2025-03-25T17:05:00","slug":"dotnet-in-dev-container","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/dotnet-in-dev-container\/","title":{"rendered":"Exploring new .NET releases with Dev Containers"},"content":{"rendered":"<p>The .NET team has just released preview2 of .NET 10, and it&#8217;s got a <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/dotnet-10-preview-2\/\">bundle of new features and improvements<\/a>.\nYou might want to give these a try but don&#8217;t want to mess with your local development environment.\nA great way to try out a .NET preview is by using dev containers.\nIn this blog post, we&#8217;ll walk you through the steps to set up and use dev containers for experimenting with a new .NET release.<\/p>\n<h2>What are Dev Containers?<\/h2>\n<p><a href=\"https:\/\/containers.dev\/\">Dev containers<\/a> are pre-configured, isolated environments that allow developers to work on projects without worrying about dependencies and configurations. They are particularly useful for trying out new technologies, as they provide a consistent and reproducible setup.<\/p>\n<p>Many development environments, including Visual Studio Code, support dev containers. This allows you to easily create and manage these environments.<\/p>\n<p>You can also use dev containers in GitHub Codespaces, which provide a cloud-based development environment.<\/p>\n<h3>Types of .NET Container Images<\/h3>\n<p>There are many types of <a href=\"https:\/\/learn.microsoft.com\/dotnet\/core\/docker\/container-images\">.NET container images<\/a> available, each designed for different scenarios.\n.NET container images are published to the <a href=\"https:\/\/mcr.microsoft.com\/\">Microsoft Artifact Registry<\/a>. These images are regularly updated\nto include the latest patches and features, ensuring that you have access to the most secure and up-to-date versions.<\/p>\n<p>If you want to get more information about a specific .NET container image, such as mcr.microsoft.com\/dotnet\/nightly\/sdk:9.0, you can use one of the following methods:<\/p>\n<ul>\n<li>\n<p>From the Microsoft Artifact Registry: The Microsoft Artifact Registry documentation provides comprehensive information about the .NET container images, including how they are tagged and updated.<\/p>\n<\/li>\n<li>\n<p>Use the docker inspect Command: If you have already pulled the image, you can use the docker inspect command to get detailed information about the image. For example:<\/p>\n<pre><code class=\"language-sh\">docker inspect mcr.microsoft.com\/dotnet\/nightly\/sdk:9.0<\/code><\/pre>\n<\/li>\n<\/ul>\n<p>Some of these images are designed specifically for running .NET applications in production.\nFor exploring a new .NET release, you&#8217;ll want to use a dev container image that includes the .NET SDK and runtime.\nFor exploring a preview release, you&#8217;ll probably want a dev container for a current GA release augmented with the\npreview version of .NET 10 you want to try out.<\/p>\n<table>\n<thead>\n<tr>\n<th>Container Type<\/th>\n<th>Best For<\/th>\n<th>Example Tag<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>SDK<\/td>\n<td>Development<\/td>\n<td><code>mcr.microsoft.com\/dotnet\/sdk:9.0<\/code><\/td>\n<td>Includes full SDK, runtime, and development tools<\/td>\n<\/tr>\n<tr>\n<td>Runtime<\/td>\n<td>Production<\/td>\n<td><code>mcr.microsoft.com\/dotnet\/runtime:9.0<\/code><\/td>\n<td>Smaller image with just the runtime<\/td>\n<\/tr>\n<tr>\n<td>ASP.NET<\/td>\n<td>Web apps<\/td>\n<td><code>mcr.microsoft.com\/dotnet\/aspnet:9.0<\/code><\/td>\n<td>Includes ASP.NET Core runtime<\/td>\n<\/tr>\n<tr>\n<td>Nightly<\/td>\n<td>Testing previews<\/td>\n<td><code>mcr.microsoft.com\/dotnet\/nightly\/sdk:10.0<\/code><\/td>\n<td>Latest preview builds<\/td>\n<\/tr>\n<tr>\n<td>Dev Container<\/td>\n<td>Local development<\/td>\n<td><code>mcr.microsoft.com\/devcontainers\/dotnet:1-8.0<\/code><\/td>\n<td>Pre-configured development environment with additional tools<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Setting Up Your Dev Container<\/h2>\n<p>To get started with dev containers, you&#8217;ll need Docker and Visual Studio Code with the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=ms-vscode-remote.remote-containers\">Dev Containers extension<\/a> installed. Follow these steps to set up your dev container for exploring a new .NET release.<\/p>\n<h3>Create a Dev Container Configuration<\/h3>\n<p>In your project directory, create a .devcontainer folder and add a devcontainer.json file.\nThe easiest way to do this is with the Dev Container extension in Visual Studio Code. Open the Command Palette (Ctrl+Shift+P) and select &#8220;Dev Containers: Add Development Container Configuration Files&#8230;&#8221;. You can store the configuration files in the workspace or in the user data folder, outside the workspace &#8212; I generally choose the workspace option.\nChoose the &#8220;C#(.NET)&#8221; template, and it will create a .devcontainer folder with a devcontainer.json file that you can then customize as needed.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2025\/03\/AddConfigFiles.png\" alt=\"Add Dev Container Configuration\" \/><\/p>\n<p>For GA versions of .NET, there are prebuilt dev containers available. For preview versions, you can create a custom dev container configuration.<\/p>\n<h3>Add a Dockerfile<\/h3>\n<p>In my devcontainer configuration, I use a Dockerfile to pull in all the versions of .NET I need.\nI typically want the most recent LTS version and the most recent STS version as a base image &#8212;\ncurrently that means .NET 8 and .NET 9.\nThese are useful for running dotnet based tools that depend on one of these GA versions.\nOn top of this I install the preview version of .NET 10 I want.<\/p>\n<p>The Dockerfile lives in the same directory as the devcontainer.json file.\nYou point to from the devcontainer.json file using the &#8220;dockerFile&#8221; property of the &#8220;build&#8221; property, as follows:<\/p>\n<pre><code class=\"language-json\">    \"build\": {\n        \"dockerfile\": \".\/Dockerfile\",\n        \"context\": \".\"\n    },<\/code><\/pre>\n<p>This replaces the &#8220;image&#8221; property in the stock devcontainer.json file.<\/p>\n<p>I use the devcontainer of the most recent .NET LTS as the base image for my dev container.<\/p>\n<pre><code class=\"language-text\">FROM mcr.microsoft.com\/devcontainers\/dotnet:1-8.0<\/code><\/pre>\n<p>Then I &#8220;install&#8221; the most recent STS version of .NET, which is currently .NET 9, and the preview version of .NET 10 I want to try out.\nTo install these SDK versions, I copy the SDK from the corresponding SDK image, using the Docker COPY command, as follows:<\/p>\n<pre><code class=\"language-text\"># Install the current .NET STS release on top of that\nCOPY --from=mcr.microsoft.com\/dotnet\/sdk:9.0 \/usr\/share\/dotnet \/usr\/share\/dotnet\n\n# Finally install the most recent .NET 10.0 preview using the dotnet-install script\nCOPY --from=mcr.microsoft.com\/dotnet\/nightly\/sdk:10.0.100-preview.2 \/usr\/share\/dotnet \/usr\/share\/dotnet<\/code><\/pre>\n<p>You can see my complete devcontainer.json and Dockerfile for .NET 10 preview2 in my <a href=\"https:\/\/github.com\/mikekistler\/aspnet-whats-new\/tree\/dotnet-10-preview2\/.devcontainer\">aspnet-whats-new repo<\/a>.<\/p>\n<h3>Other dev container configuration options<\/h3>\n<p>You can customize your dev container further by adding additional configuration options in the devcontainer.json file.\nWhat&#8217;s really great about dev containers is that you can tailor them to your specific needs,\nmeaning that you only install the specific tools and dependencies you need for your project.<\/p>\n<p>Here are a few common options you might want to consider:<\/p>\n<ul>\n<li>\n<p><strong>Extensions<\/strong>: You can specify any Visual Studio Code extensions you want to install in your dev container.\nFor example, to install the C# DevKit extension, add the following line to your devcontainer.json file:<\/p>\n<pre><code class=\"language-json\">\"extensions\": [\n\"ms-dotnettools.csdevkit\",\n]<\/code><\/pre>\n<\/li>\n<li>\n<p><strong>Features<\/strong>: You can specify additional features to include in your dev container. For example, to include the Azure CLI, add the following line to your devcontainer.json file:<\/p>\n<pre><code class=\"language-json\">\"features\": {\n  \"azure-cli\": \"latest\"\n}<\/code><\/pre>\n<p>You can see the full list of available features in the <a href=\"https:\/\/containers.dev\/features\">dev container features documentation<\/a>.<\/p>\n<\/li>\n<li>\n<p><strong>Post-Create Command<\/strong>: You can specify a command to run after the dev container is created. This is useful for installing additional dependencies or running setup scripts. For example, to install the latest version of the .NET CLI, add the following line to your devcontainer.json file:<\/p>\n<pre><code class=\"language-json\">\"postCreateCommand\": \"dotnet tool install -g dotnet-ef\"<\/code><\/pre>\n<p>Be aware that the postCreateCommand runs every time you start the dev container, in contrast to commands in the Dockerfile, which are only run when the dev container is built.<\/p>\n<\/li>\n<\/ul>\n<h2>Build and Start Your Dev Container<\/h2>\n<p>Once you have your dev container configuration set up, you can build and start your dev container. The easiest way to do this is with the &#8220;Dev Containers: Open Folder in Container&#8221; command. This will build and start your dev container based on the configuration files you created. You can check that the .NET versions are installed correctly with the dotnet &#8211;list-sdks command:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2025\/03\/DevContainerInVSCode.png\" alt=\".NET Preview 2 in dev container\" \/><\/p>\n<p>Note that once the container image is built, it is cached locally, so that you don&#8217;t have to rebuild it every time you start the dev container. However, this means that if there are new service releases of .NET 8 or .NET 9, you will need to rebuild the dev container to pick up those changes. You can do this with the &#8220;Dev Containers: Rebuild Container Without Cache&#8221; command. This will force a rebuild of the dev container image, and it will pull the latest version of the base images.<\/p>\n<h2>Conclusion<\/h2>\n<p>Using dev containers is a fantastic way to try out new .NET releases without affecting your local development environment.\nWith a consistent and isolated setup, you can explore new features and enhancements with ease.<\/p>\n<p>Give it a try and let us know what you think!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to set up and use dev containers for experimenting with new .NET releases.<\/p>\n","protected":false},"author":68772,"featured_media":56089,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,197,7509,7252,7689,7593],"tags":[4,32,7693,57,7753],"class_list":["post-56088","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-aspnet","category-aspnetcore","category-cloud","category-cloud-native","category-visual-studio-code","tag-net","tag-asp-net-core","tag-cloud-native","tag-containers","tag-vscode"],"acf":[],"blog_post_summary":"<p>Learn how to set up and use dev containers for experimenting with new .NET releases.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56088","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/68772"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=56088"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56088\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/56089"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=56088"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=56088"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=56088"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}