devblogs.microsoft.com Open in urlscan Pro
2600:1400:d:581::2f1e  Public Scan

URL: https://devblogs.microsoft.com/dotnet/announcing-builtin-container-support-for-the-dotnet-sdk/?ocid=AID3031635&utm_issue=Septem...
Submission: On September 22 via api from CA — Scanned from CA

Form analysis 3 forms found in the DOM

Name: searchFormGET /search

<form class="c-search" autocomplete="off" id="searchForm" name="searchForm" role="search" action="/search" method="GET"
  data-seautosuggest="{&quot;queryParams&quot;:{&quot;market&quot;:&quot;en-us&quot;,&quot;clientId&quot;:&quot;7F27B536-CF6B-4C65-8638-A0F8CBDFCA65&quot;,&quot;sources&quot;:&quot;Microsoft-Terms,Iris-Products,DCatAll-Products&quot;,&quot;filter&quot;:&quot;+ClientType:StoreWeb&quot;,&quot;counts&quot;:&quot;5,1,5&quot;},&quot;familyNames&quot;:{&quot;Apps&quot;:&quot;App&quot;,&quot;Books&quot;:&quot;Book&quot;,&quot;Bundles&quot;:&quot;Bundle&quot;,&quot;Devices&quot;:&quot;Device&quot;,&quot;Fees&quot;:&quot;Fee&quot;,&quot;Games&quot;:&quot;Game&quot;,&quot;MusicAlbums&quot;:&quot;Album&quot;,&quot;MusicTracks&quot;:&quot;Song&quot;,&quot;MusicVideos&quot;:&quot;Video&quot;,&quot;MusicArtists&quot;:&quot;Artist&quot;,&quot;OperatingSystem&quot;:&quot;Operating System&quot;,&quot;Software&quot;:&quot;Software&quot;,&quot;Movies&quot;:&quot;Movie&quot;,&quot;TV&quot;:&quot;TV&quot;,&quot;CSV&quot;:&quot;Gift Card&quot;,&quot;VideoActor&quot;:&quot;Actor&quot;}}"
  data-seautosuggestapi="https://www.microsoft.com/msstoreapiprod/api/autosuggest"
  data-m="{&quot;cN&quot;:&quot;GlobalNav_Search_cont&quot;,&quot;cT&quot;:&quot;Container&quot;,&quot;id&quot;:&quot;c1c9c3m1r1a1&quot;,&quot;sN&quot;:1,&quot;aN&quot;:&quot;c9c3m1r1a1&quot;}" aria-expanded="false" style="overflow-x: visible;">
  <div class="x-screen-reader" aria-live="assertive"></div>
  <input id="cli_shellHeaderSearchInput" aria-label="Search Expanded" aria-autocomplete="list" aria-expanded="false" aria-controls="universal-header-search-auto-suggest-transparent" aria-owns="universal-header-search-auto-suggest-ul" type="search"
    name="query" role="combobox" placeholder="Search" data-m="{&quot;cN&quot;:&quot;SearchBox_nav&quot;,&quot;id&quot;:&quot;n1c1c9c3m1r1a1&quot;,&quot;sN&quot;:1,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" data-toggle="tooltip" data-placement="right"
    title="" data-original-title="Search" style="overflow-x: visible;">
  <input type="hidden" name="blog" value="/dotnet/" data-m="{&quot;cN&quot;:&quot;HiddenInput_nav&quot;,&quot;id&quot;:&quot;n2c1c9c3m1r1a1&quot;,&quot;sN&quot;:2,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" style="overflow-x: visible;">
  <button id="search" aria-label="Search" class="c-glyph" data-m="{&quot;cN&quot;:&quot;Search_nav&quot;,&quot;id&quot;:&quot;n3c1c9c3m1r1a1&quot;,&quot;sN&quot;:3,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" data-bi-mto="true" aria-expanded="false"
    style="overflow-x: visible;">
    <span role="presentation" style="overflow-x: visible;">Search</span>
    <span role="tooltip" class="c-uhf-tooltip c-uhf-search-tooltip" style="overflow-x: visible;">Search</span>
  </button>
  <div class="m-auto-suggest" id="universal-header-search-auto-suggest-transparent" role="group" style="overflow-x: visible;">
    <ul class="c-menu" id="universal-header-search-auto-suggest-ul" aria-label="Search Suggestions" aria-hidden="true" data-bi-dnt="true" data-bi-mto="true" data-js-auto-suggest-position="default" role="listbox" data-tel="jsll"
      data-m="{&quot;cN&quot;:&quot;search suggestions_cont&quot;,&quot;cT&quot;:&quot;Container&quot;,&quot;id&quot;:&quot;c4c1c9c3m1r1a1&quot;,&quot;sN&quot;:4,&quot;aN&quot;:&quot;c1c9c3m1r1a1&quot;}" style="overflow-x: visible;"></ul>
  </div>
</form>

<form id="wp-link" tabindex="-1">
  <input type="hidden" id="_ajax_linking_nonce" name="_ajax_linking_nonce" value="2511664d18">
  <h1 id="link-modal-title">Insert/edit link</h1>
  <button type="button" id="wp-link-close"><span class="screen-reader-text">Close</span></button>
  <div id="link-selector">
    <div id="link-options">
      <p class="howto" id="wplink-enter-url">Enter the destination URL</p>
      <div>
        <label><span>URL</span>
          <input id="wp-link-url" type="text" aria-describedby="wplink-enter-url"></label>
      </div>
      <div class="wp-link-text-field">
        <label><span>Link Text</span>
          <input id="wp-link-text" type="text"></label>
      </div>
      <div class="link-target">
        <label><span></span>
          <input type="checkbox" id="wp-link-target"> Open link in a new tab</label>
      </div>
    </div>
    <p class="howto" id="wplink-link-existing-content">Or link to existing content</p>
    <div id="search-panel">
      <div class="link-search-wrapper">
        <label>
          <span class="search-label">Search</span>
          <input type="search" id="wp-link-search" class="link-search-field" autocomplete="off" aria-describedby="wplink-link-existing-content">
          <span class="spinner"></span>
        </label>
      </div>
      <div id="search-results" class="query-results" tabindex="0">
        <ul></ul>
        <div class="river-waiting">
          <span class="spinner"></span>
        </div>
      </div>
      <div id="most-recent-results" class="query-results" tabindex="0">
        <div class="query-notice" id="query-notice-message">
          <em class="query-notice-default">No search term specified. Showing recent items.</em>
          <em class="query-notice-hint screen-reader-text">Search or use up and down arrow keys to select an item.</em>
        </div>
        <ul></ul>
        <div class="river-waiting">
          <span class="spinner"></span>
        </div>
      </div>
    </div>
  </div>
  <div class="submitbox">
    <div id="wp-link-cancel">
      <button type="button" class="button">Cancel</button>
    </div>
    <div id="wp-link-update">
      <input type="submit" value="Add Link" class="button button-primary" id="wp-link-submit" name="wp-link-submit">
    </div>
  </div>
</form>

#

<form id="myForm" action="#">
  <div class="modal-body">
    <div class="form-group">
      <label for="code-text">Paste your code snippet</label>
      <textarea class="form-control" id="code-text" style="height: 150px;"></textarea>
    </div>
  </div>
</form>

Text Content

Skip to main content
Microsoft
.NET Blog
.NET Blog
.NET Blog
 * Home
 * DevBlogs
 * Developer
    * Visual Studio
    * Visual Studio Code
    * Visual Studio for Mac
    * DevOps
    * Developer support
    * CSE Developer
    * Engineering@Microsoft
    * Azure SDK
    * IoT
    * Command Line
    * Perf and Diagnostics
    * Dr. International
    * Notification Hubs
    * Math in Office

 * Technology
    * DirectX
    * PIX
    * SurfaceDuo
    * Startups
    * Sustainable Engineering
    * Windows AI Platform

 * Languages
    * C++
    * C#
    * F#
    * Visual Basic
    * TypeScript
    * PowerShell Community
    * PowerShell Team
    * Python
    * Q#
    * JavaScript
    * Java
    * Java Blog in Chinese

 * .NET
    * .NET
    * .NET MAUI
    * Blazor
    * ASP.NET
    * NuGet
    * Xamarin
    * .Net Blog in Chinese

 * Platform Development
    * #ifdef Windows
    * Apps for Windows
    * Azure Depth Platform
    * Azure Government
    * Bing Dev Center
    * Microsoft Edge Dev
    * Microsoft Azure
    * Microsoft 365 Developer
    * Old New Thing
    * Windows MIDI and Music dev
    * Windows Search Platform

 * Data Development
    * Azure Cosmos DB
    * Azure Data Studio
    * Azure SQL Database
    * OData
    * Revolutions R
    * SQL Server Data Tools

 * More

Theme
 * Light
 * Dark

Login

Search Search

Cancel


ANNOUNCING BUILT-IN CONTAINER SUPPORT FOR THE .NET SDK

Chet Husk



August 25th, 202235 17



Containers have become one of the easiest ways to distribute and run a wide
suite of applications and services in the cloud. The .NET Runtime was hardened
for containers years ago. You can now create containerized versions of your
applications with just dotnet publish. Container images are now a supported
output type of the .NET SDK.


TL;DR

Before we go into the details of how this works, I want to show what a
zero-to-running containerized ASP.NET Core application looks like:

# create a new project and move to its directory
dotnet new mvc -n my-awesome-container-app
cd my-awesome-container-app

# add a reference to a (temporary) package that creates the container
dotnet add package Microsoft.NET.Build.Containers

# publish your project for linux-x64
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer

# run your app using the new container
docker run -it --rm -p 5010:80 my-awesome-container-app:1.0.0

Now you can go to http://localhost:5010 and you should see the sample MVC
application, rendered in all its glory.



For this release, you must have Docker installed and running for this sample to
work. Additionally, only Linux-x64 containers are supported.




MOTIVATION

Containers are an excellent way to bundle and ship applications. A popular way
to build container images is through a Dockerfile – a special file that
describes how to create and configure a container image. Let’s look at one of
our samples for an ASP.NET Core application’s Dockerfile here:

# https://hub.docker.com/_/microsoft-dotnet
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /source

# copy csproj and restore as distinct layers
COPY aspnetapp/*.csproj .
RUN dotnet restore --use-current-runtime  

# copy everything else and build app
COPY aspnetapp/. .
RUN dotnet publish -c Release -o /app --use-current-runtime --self-contained false --no-restore

# final stage/image
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "aspnetapp.dll"]

This project uses a multi-stage build to both build and run the app. It uses the
7.0 SDK image to restore the application’s dependencies, publish the application
to a folder, and finally create the final runtime image from that directory.

This Dockerfile works very well, but there are a few caveats to it that aren’t
immediately apparent, which arise from the concept of a Docker build context.
The build context is a the set of files that are accessible inside of a
Dockerfile, and is often (though not always) the same directory as the
Dockerfile. If you have a Dockerfile located beside your project file, but your
project file is underneath a solution root, it’s very easy for your Docker build
context to not include configuration files like Directory.Packages.props or
NuGet.config that would be included in a regular dotnet build. You would have
this same situation with any hierarchical configuration model, like EditorConfig
or repository-local git configurations.

This mismatch between the explicitly-defined Docker build context and the .NET
build process was one of the driving motivators for this feature. All of the
information required to build an image is present in a standard dotnet build, we
just needed to figure out the right way to represent that data in a way that
container runtimes like Docker could use.


HOW DOES IT WORK

A container image is made of two primary parts: some JSON configuration
containing metadata about how the image can be run, and a list of tarball
archives that represent the file system. In .NET 7, we added several APIs to the
.NET Runtime for handling TAR files and streams, and that opened the door to
manipulating container images programmatically.

This approach has been demonstrated very successfully in projects like Jib in
the Java ecosystem, Ko for Go, and even in .NET with projects like konet. It’s
obvious that a simple tool-driven approach to generate container images is
becoming more popular.

We built the .NET SDK solution with the following goals:

 * Provide seamless integration with existing build logic, to prevent the kinds
   of context gaps mentioned earlier
 * Implement in C#, to take advantage of our own tool and benefit from .NET
   runtime performance improvements
 * Integrated into the .NET SDK, so that it is straightforward for the .NET team
   to improve and service in the existing .NET SDK processes


CUSTOMIZATION

Those of you with experience writing Dockerfiles are probably wondering where
all of the complexity of the Dockerfile has gone. Where is the FROM base image
declared? What tags are used? Many aspects of the generated image are
customizable by you through the use of MSBuild properties and items (you can
read about that in detail at the documentation), but we’ve shipped a few
defaults to make getting started easier.


BASE IMAGE

The base image defines which functionality you will have available and which OS
and version you will be using. The following base images are automatically
chosen:

 * for ASP.NET Core apps, mcr.microsoft.com/dotnet/aspnet
 * for self-contained apps, mcr.microsoft.com/dotnet/runtime-deps
 * for all other apps, mcr.microsoft.com/dotnet/runtime

In all cases, the tag used for the base image is the version portion of the
TargetFramework that has been chosen for the application – for example, a
TargetFramework of net7.0 would result in a tag of 7.0 being used. These
simple-version tags are based on Debian distributions of linux – if you want to
use a different supported distro like Alpine or Ubuntu then you would need to
manually specify that tag (see the ContainerBaseImage example below).

We think that the choice of defaulting to the Debian-based versions of the
runtime images is the best choice for broad compatibility with most
applications’ needs. Of course, you are free to choose any base image for your
containers. Simply set the ContainerBaseImage property to any image name and
we’ll do the rest. For example, maybe you want to run your web application on
Alpine Linux. That would look like this:

<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:7.0-alpine</ContainerBaseImage>


IMAGE NAME AND VERSION

The name of your image will be based on the AssemblyName of your project by
default. If that’s not a good fit for you, the name of the image can be
explicitly set by using the ContainerImageName property.

An image also needs a tag, so we default to the value of the Version property.
This defaults to 1.0.0, but you are free to customize this in any way and we’ll
make use of it. This fits especially well with automated versioning schemes like
GitVersioning, where the version is derived from some configuration data in the
repository. This helps ensure that you always have a unique version of your
application to run. Unique version tags are especially important for images,
because pushing an image with the same tag to a registry will overwrite the
image that was previously stored as that tag.


EVERYTHING ELSE

Many other properties can be set on an image, like custom Entrypoints,
Environment Variables, and even arbitrary Labels (which are often used for
tracking metadata like SDK version, or who built the image). In addition, images
are often pushed to destination registries by specifying a different base
registry. In subsequent versions of the .NET SDK we plan to add support for
these capabilities in a similar manner as described above – all controlled
through MSBuild project properties.


WHEN SHOULD YOU USE THIS


LOCAL DEVELOPMENT

If you need a container for local development, now you can have one with a
single command. dotnet publish --os linux --arch x64
-p:PublishProfile=DefaultContainer will make a Debug-configuration container
image named after your project. Some users have made this even simpler by
putting these properties into a Directory.Build.props and simply running dotnet
publish:

<Project>
    <PropertyGroup>
        <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
        <PublishProfile>DefaultContainer<PublishProfile>
    </PropertyGroup>
</Project>

You could also use other SDK and MSBuild features like response files or
PublishProfiles to create groups of these properties for easier use.


CI PIPELINES

Overall, building container images with the SDK should integrate seamlessly into
your existing build processes. A sample of a minimal GitHub Actions workflow to
containerize an app is just about 30 lines of configuration:

name: Containerize ASP.NET Core application

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup .NET SDK
        uses: actions/setup-dotnet@v2
      # Package the app into a linux-x64 container based on the dotnet/aspnet image
      - name: Publish
        run: dotnet publish --os linux --arch x64 --configuration Release -p:PublishProfile=DefaultContainer
      # Because we don't yet support pushing to authenticated registries, we have to use docker to
      # login, tag and push the image. In the future none of these steps will be required!
      # 1. Login to our registry so we can push the image. Could use a raw docker command as well.
      - name: Docker Login
        uses: actions-hub/docker/login@master
        env:
          DOCKER_REGISTRY_URL: sdkcontainerdemo.azurecr.io
          DOCKER_USERNAME: ${{ secrets.ACR_USERNAME }}
          DOCKER_PASSWORD: ${{ secrets.ACR_PAT }}
      # 2. Use the tag command to rename the local container to match our Azure Container Registry URL
      - name: Tag built container with Azure Container Registry url
        uses: actions-hub/docker/cli@master
        with:
          args: tag sdk-container-demo:1.0.0 sdkcontainerdemo.azurecr.io/baronfel/sdk-container-demo:latest
      # 3. Push the renamed container to ACR.
      - name: Push built container to Azure Container Registry
        uses: actions-hub/docker/cli@master
        with:
          args: push sdkcontainerdemo.azurecr.io/baronfel/sdk-container-demo:latest

This is part of an example repo called baronfel/sdk-container-demo made to
demonstrate this end-to-end process.

There is one major scenario that we won’t be able to handle at all with
SDK-built containers, though.


RUN COMMANDS

There’s no way of performing RUN commands with the .NET SDK. These commands are
often used to install some OS packages or create a new OS user, or any number of
arbitrary things. If you would like to keep using the SDK container building
feature, you can instead create a custom base image with these changes and then
using this base image as the ContainerBaseImage as described above.

As an example, let’s say I’m working on a library that needs the libxml2 library
installed on the host in order to do some custom XML processing. I could write a
Dockerfile like this to capture this native dependency:

FROM mcr.microsoft.com/dotnet/runtime:7.0

RUN apt-get update && \
        apt-get install -y libxml2 && \
        rm -rf /var/lib/apt/lists/*

Now, I can build, tag, and push this image to my registry and use it as a base
for my application:

docker build -f Dockerfile . -t registry.contoso.com/my-base-image:1.0.0
docker push registry.contoso.com/my-base-image:1.0.0

In the project file of my application I’d set the ContainerBaseImage property to
this new image:

<Project>
  <PropertyGroup>
    ...
    <ContainerBaseImage>registry.contoso.com/my-base-image:1.0.0</ContainerBaseImage>
    ...
  </PropertyGroup>
</Project>


TEMPORARY GAPS

This is the initial preview of SDK-built container images, so there are some
features that we haven’t yet been able to deliver.


WINDOWS IMAGES AND NON-X64 ARCHITECTURES

We have focused on the Linux-x64 image deployment scenario for this initial
release. Windows images and other architectures are key scenarios we plan to
support for the full release, so watch out for new developments there.


PUSHING TO REMOTE REGISTRIES

We have not yet implemented support for authentication, which is critical for
many users. This is one of our highest priority items. In the interim, we
suggest pushing to your local Docker daemon, then using docker tag and docker
push to push the generated images to your destination. The sample GitHub Action
above shows how this can be done.


SOME IMAGE CUSTOMIZATION

Several image metadata customizations have not been implemented yet. This
includes custom Entrypoints, environment variables, and custom user/group
information. A full list can be seen on dotnet/sdk-container-builds.


NEXT STEPS

Over the release candidate phases of the .NET 7 release we will be adding new
image metadata, support for pushing images to remote registries, and support for
Windows images. You can track that progress at the milestone we’ve created for
this.

We also plan on integrating this work directly into the SDK throughout the
release. When that happens, we’ll be releasing a ‘final’ version of the package
on NuGet that will warn you of the change, and ask you to remove the Package
entirely from your project.

If you are interested in cutting-edge builds of the tool, we also have a GitHub
package feed where you can opt into trying the latest work.

If you encounter issues using the SDK container image builder, let us know and
we’ll do our best to help you out.


CLOSING THOUGHTS

We would love for those of you building Linux containers to try building them
with the .NET SDK. I’ve personally had a blast trying them out locally – I had a
good time going to some of my demo repositories and containerizing them with a
single command, and I hope you all feel the same!

Happy image building!




CHET HUSK PROGRAM MANAGER, .NET TOOLS TEAM

Follow


Posted in .NET .NET Core ASP.NET Core Containers Docker

READ NEXT

.NET Framework August 2022 Cumulative Update Preview Updates
August 2022 Cumulative Update Preview Updates for .NET Framework.
Salini Agarwal
August 26, 2022
1 comment
.NET MAUI Cloud Skills Challenge – Learn .NET MAUI, Get Stickers!
Learn how to build multi-platform apps with .NET MAUI with it the .NET MAUI
Cloud Skills Challenge, register now, complete modules, and get some stickers!
Matt Soucoup
August 29, 2022
6 comments


35 COMMENTS


LEAVE A COMMENTCANCEL REPLY

Log in to join the discussion.

 * Page 1of comments
 * Page 2of comments
 * Next comment

 * William Liu August 25, 2022 5:04 pm 0
   collapse this comment
   
   
   Does the sample at the beginning of the article require .net 7 SDK, right?
   
   Log in to Vote or Reply
   * Chet Husk August 25, 2022 5:35 pm 0
     collapse this comment
     
     
     That’s right – specifically it requires .NET 7 preview 7 or greater.
     
     Log in to Vote or Reply
     
   
 * Dan Friedman August 25, 2022 5:05 pm 0
   collapse this comment
   
   
   Nice work. Thanks for always simplifying things for us.
   
   Log in to Vote or Reply
   * Chet Husk August 26, 2022 6:50 am 0
     collapse this comment
     
     
     That’s what we’re here for! Have you had a chance to give container builds
     a try?
     
     Log in to Vote or Reply
     
   
 * Amit E August 25, 2022 8:29 pm 0
   collapse this comment
   
   
   This is a great addition and should greatly simplify containerization in some
   scerios. I hope to see an even deeper integration, maybe by adding a
   dedicated command (dotnet container?) or parameter (dotnet publish
   –container?) and reduce the need to use more obscure switches (specifically
   -p:PublishProfile=DefaultContainer).
   
   Would also be great to have a simple way to generate the dockerfile that will
   generate the same image that the publish command creates.
   
   Log in to Vote or Reply
   * Chet Husk August 25, 2022 8:51 pm 0
     collapse this comment
     
     
     I completely agree! I logged a dotnet/sdk issue a while back about making
     Publish Profiles feel more first-class (in a way that doesn’t compromise
     the overall generic nature of the .NET CLI):
     https://github.com/dotnet/sdk/issues/26161 Any feedback you have on that
     would be very welcome.
     
     Log in to Vote or Reply
     * Amit E August 26, 2022 8:51 am 0
       collapse this comment
       
       
       So assuming the publish profile is named “container”:
       
       dotnet publish --profile container
       
       That would definitely be an improvement.
       
       Log in to Vote or Reply
       
     
   
 * Diego Bonura August 25, 2022 11:53 pm 0
   collapse this comment
   
   
   So cool! what about ARM images support?
   
   Log in to Vote or Reply
   * Chet Husk August 26, 2022 6:47 am 0
     collapse this comment
     
     
     It’s on the roadmap – check out
     https://github.com/dotnet/sdk-container-builds/issues/91 for more details,
     but it should be relatively straightforward to do. Once it’s done,
     supplying a Runtime Identifier (either via the --runtime/-r CLI option or
     the RuntimeIdentifier MSBuild property) with an architecture of arm64 would
     cause us to choose the appropriate arm architecture if the chosen image
     supports it. All of the Microsoft-provided .NET base images listed in the
     article do support ARM so it should all line up.
     
     Log in to Vote or Reply
     
   
 * Howard van Rooijen August 26, 2022 12:55 am 0
   collapse this comment
   
   
   Great work. Really looking forward to integrating this into our CI/CD
   pipelines.
   
   Log in to Vote or Reply
   * Chet Husk August 26, 2022 6:49 am 0
     collapse this comment
     
     
     Thanks Howard – I’m looking forward to hearing from you and your team about
     how it works for you.
     
     Log in to Vote or Reply
     
   
 * Shawn Stoddard August 26, 2022 8:24 am 0
   collapse this comment
   
   
   Any thoughts about support software other than Docker – say PodMan for
   example?
   
   Log in to Vote or Reply
   * Chet Husk August 26, 2022 9:00 am 0
     collapse this comment
     
     
     We definitely want to support alternative container engines like podman. I
     just tested our support with podman-machine on Windows and I was able to
     push my image and run it, though I did have to use Docker CLI commands that
     transparently used my podman machine. The podman-specific commands didn’t
     run, so I’ll raise an issue on the repo about investigating that
     specifically – as a goal podman run, podman list, and all other podman
     commands should work just as well as docker commands.
     
     Log in to Vote or Reply
     * Tim Heuer August 26, 2022 3:40 pm 0
       collapse this comment
       
       
       Check it… https://imgur.com/TXR8xHv
       
       Log in to Vote or Reply
       
     * Chet Husk August 27, 2022 7:09 am 0
       collapse this comment
       
       
       Following up here – podman actually works seamlessly, it’s just you have
       to be very aware of if you’re running podman machine on Windows in
       rootless mode or not, since those modes change the storage location of
       the loaded container images.
       
       Log in to Vote or Reply
       * 晓 韩 August 29, 2022 12:49 am 0
         collapse this comment
         
         
         How about containerd & nerdctl? I suppose they will be supported as
         well? I would like to use Rancher Desktop to replace Docker Desktop for
         Windows completely.
         
         Log in to Vote or Reply
         * Chet Husk August 29, 2022 11:09 am 0
           collapse this comment
           
           
           I haven’t personally tested containerd and nerdctl, but I spoke to
           someone this morning that used this feature with Rancher and had no
           problems. I’d be very interested in your results!
           
           
           
         
       
     
   
 * nazar554 August 26, 2022 8:29 am 0
   collapse this comment
   
   
   Does this work with packages.lock.json and –locked-mode ?
   Also it would be great if SDK could use it to generate a software bills of
   materials (SBOM)
   
   Log in to Vote or Reply
   * Chet Husk August 26, 2022 9:06 am 0
     collapse this comment
     
     
     There are some pain points with packages.lock.json and publish, especially
     with runtime identifiers. This is because publish uses restore to acquire
     runtime-specific assets that aren’t part of a normal restore. There’s an
     issue over at the NuGet/Home repository that goes into the details and some
     workarounds, but we don’t have a solid set of guidance yet on how these
     features should be integrated.
     
     Log in to Vote or Reply
     
   
 * Mark Stega August 26, 2022 2:06 pm 0
   collapse this comment
   
   
   This looks to be a very useful addition to the SDK
   
   About the article:
   
   1) It would be nice to describe why the CI script uses
   actions-hub/docker/login & cli rather than just using docker commands
   2) What does having the ‘dotnet build’ accomplish that isn’t done in the
   subsequent ‘dotnet publish’ step?
   3) Why does the build have those 2 environment vars declared?
   
   About using the feature:
   
   I added this publish step to my github actions: ‘dotnet publish
   ICEBG.Web.DataServices/ICEBG.Web.DataServices.csproj –os linux –arch x64
   –configuration Azure -p:PublishProfile=DefaultContainer
   -p:Version=2022-08-26–21-29-29–WIP’. I do not seem to have an image with the
   tag I expected. After doing the publish I execute a ‘docker images -a’
   command. I don’t see an image with the expected tag. I see either 6 images as
   in:
   
   REPOSITORY       TAG                                IMAGE ID       CREATED          SIZE
   229416           6e1367aa97844c89b4a25a987bf5a0ba   9aa1a65ab488   28 seconds ago   220MB
                                           47cde3a84d9e   29 seconds ago   220MB
                                           4f0b4b1fe90b   29 seconds ago   220MB
   229416           575ed5c505ea4307943e45d0e6d6c104   f81699aabf05   31 seconds ago   220MB
                                           e4b930a957ba   32 seconds ago   220MB
                                           f8ccc4a1f9be   32 seconds ago   220MB
   node             16                                 bfb7b2a05614   9 days ago       910MB
   node             16-alpine                          5dcd1f6157bd   9 days ago       115MB
   node             14-alpine                          d12c0eadaee1   2 weeks ago      119MB
   alpine           3.13                               6b5c5e00213a   2 weeks ago      5.62MB
   alpine           3.14                               dd53f409bf0b   2 weeks ago      5.6MB
   node             14                                 52e5cabe9b9c   3 weeks ago      914MB
   buildpack-deps   buster                             c75e17448eed   3 weeks ago      804MB
   buildpack-deps   bullseye                           810420bc6608   3 weeks ago      835MB
   ubuntu           20.04                              3bc6e9f30f51   3 weeks ago      72.8MB
   ubuntu           18.04                              8d5df41c547b   3 weeks ago      63.1MB
   debian           10                                 d4729731066b   3 weeks ago      114MB
   debian           11                                 07d9246c53a6   3 weeks ago      124MB
   buildpack-deps   stretch                            9d4f40bcbdd3   2 months ago     835MB
   debian           9                                  662c05203bab   2 months ago     101MB
   moby/buildkit    latest                             a2c9241854f2   3 months ago     142MB
   node             12                                 6c8de432fc7f   4 months ago     918MB
   node             12-alpine                          bb6d28039b8c   4 months ago     91MB
   alpine           3.12                               24c8ece58a1a   4 months ago     5.58MB
   ubuntu           16.04                              b6f507652425   12 months ago    135MB
   docker           stable                             b0757c55a1fd   21 months ago    220MB
   
   or 3 images as in
   
   REPOSITORY       TAG                                IMAGE ID       CREATED          SIZE
   229416           c5540378845c43989cfd8b4dd78757c4   ed0a482e5e09   32 seconds ago   220MB
                                           931a6389bed0   33 seconds ago   220MB
                                           f2ec7d74725e   33 seconds ago   220MB
   
   Log in to Vote or Reply
   * Chet Husk August 26, 2022 3:06 pm 0
     collapse this comment
     
     
     Hi Mark, thanks for your feedback.
     
     I’ll address your points here and then look at what edits I should make to
     the blogpost.
     
     1) Since authentication isn’t solved by the new feature yet, in order to
     actually push to Azure we need to login via the Docker CLI. Then later, to
     actually take our image from the local Docker daemon to Azure Container
     Registry we use docker tag to rename the local image to match the
     destination registry and docker push to push the image to the registry.
     Both of these docker commands will not be necessary in a future release,
     the publish command itself will handle pushing to the registry.
     2) In this case nothing, I can probably delete it entirely to avoid
     confusion.
     3) I’m assuming you mean the GITHUB_USERNAME and GITHUB_TOKEN environment
     variables? Those are because this sample was written before the package was
     pushed to NuGet.org, so I was getting the package from a GitHub Packages
     feed, and those variables were part of the authentication to that feed. Now
     that the package is available on NuGet.org I can remove them entirely from
     both the sample project and this post.
     
     Finally, I’d love to help dig into why no container was built in your case.
     There are two primary causes I can immediately think of: the first is that
     you may not be on the correct version of the .NET SDK. You’ll need
     7.0.100-preview.7 or greater. The second is that your project (despite the
     name) isn’t a Web project (meaning a project with the Microsoft.NET.Sdk.Web
     SDK in its project file). We currently don’t have PublishProfile support
     for non-web projects, though we do plan to have it in a future release. See
     https://github.com/dotnet/sdk-container-builds/issues/141 for details
     there. In the meantime, if you do have a non-web project, you can publish
     the container directly by adding /p:PublishContainer to your dotnet publish
     command.
     
     If neither of these is the case, I invite you to open an issue at the
     parent repository and we can talk about getting a binlog to help dig into
     the problem. Thanks!
     
     Log in to Vote or Reply
     * Mark Stega August 27, 2022 6:28 am 0
       collapse this comment
       
       
       Chet,
       
       Nice cleanup, much easier to follow in the current form. I definitely
       have a web project using Microsoft.Net.Sdk.Web but I messed up my
       global.json file. After fixing that, the issue becomes clear: You have an
       argument on the dotnet publish line of ‘
       -p:PublishProfile=DefaultContainer’ and that profile is not part of the
       repository. My dotnet publish results in
       
       /home/runner/.dotnet/sdk/7.0.100-preview.7.22377.5/Sdks/Microsoft.NET.Sdk.Publish/targets/DotNetCLIToolTargets/Microsoft.NET.Sdk.DotNetCLITool.targets(104,11): error MSB4057: The target "PublishContainer" does not exist in the project. [/home/runner/work/ICEBG/ICEBG/ICEBG.Web.DataServices/ICEBG.Web.DataServices.csproj]
       
       which is an interesting error since I don’t reference ‘PublishContainer’
       
       My publish command is:
       
           - name: Publish, tag, and push DS image
             uses: actions-hub/docker/login@master
             env:
               DOCKER_REGISTRY_URL: ${{ secrets.REGISTRY_LOGIN_SERVER }}
               DOCKER_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
               DOCKER_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
           - run: |
               dotnet --info
               sudo docker images -a
               dotnet publish ICEBG.Web.DataServices/ICEBG.Web.DataServices.csproj --os linux --arch x64 --configuration Azure -p:PublishProfile=DefaultContainer -p:Version=${{ needs.version.outputs.suffix }}
               sudo docker images -a
       
       The expanded version of the publish command shows as:
       
       dotnet publish ICEBG.Web.DataServices/ICEBG.Web.DataServices.csproj --os linux --arch x64 --configuration Azure -p:PublishProfile=DefaultContainer -p:Version=2022-08-27--13-11-46--WIP
       
       Log in to Vote or Reply
       * Chet Husk August 27, 2022 7:12 am 0
         collapse this comment
         
         
         One of the parts of this feature was providing that default
         PublishProfile in the SDK itself, much in the same way that the
         existing default publish profiles are shipped. So if you’re running on
         preview 7 or greater you should have that profile as part of your SDK.
         The specific error shown here is what I would expect if you didn’t have
         the Microsoft.Net.Build.Containers package added to your project – it
         provides the implementation of the target listed in the error. Can you
         check your package references and make sure that package is available?
         
         Log in to Vote or Reply
         * Mark Stega August 27, 2022 8:10 am 0
           collapse this comment
           
           
           Chet,
           
           Thanks, you absolutely nailed the issue. I had totally forgotten to
           add the package.
           
           Is it expected to have multiple images created on the publish step?
           
           From ‘docker images -a’:
           
           REPOSITORY               TAG                                IMAGE ID       CREATED          SIZE
           icebg.web.dataservices   2022-08-27--15-06-14--WIP          e76e909e7988   9 seconds ago    230MB
           229416                   9682efcb28a740f3ae9c822d45451f9a   9256ae07657a   44 seconds ago   220MB
           none                     none                               e9ce4e2a4360   45 seconds ago   220MB
           none                     none                               0609c5b67892   45 seconds ago   220MB
           
           
           
         
       
     
   
 * Michal Biesiada August 27, 2022 3:22 pm 0
   collapse this comment
   
   
   Hi, really great article! Thanks for keeping us update. Good work. Just a
   quick note – hover by mouse on Twitter icon (Follow) shows:
   “https://www.instagram.com/twitter.com/chethusk”, so it could be corrected.
   Best wishes,
   
   Log in to Vote or Reply
   * Chet Husk August 31, 2022 12:46 pm 0
     collapse this comment
     
     
     Thanks! This is something up with the blog platform itself, and I’ve
     forwarded it along.
     
     Log in to Vote or Reply
     
   
 * SEUNGYONG SHIM August 28, 2022 9:03 pm 0
   collapse this comment
   
   
   Why to use kaniko, instead of docker in CI? It is not necessary.
   
   Log in to Vote or Reply
   

 * Page 1of comments
 * Page 2of comments
 * Next comment

RELEVANT LINKS

.NET Download

.NET Hello World

.NET Meetup Events

.NET Documentation

.NET API Browser

.NET SDKs

.NET APPLICATION ARCHITECTURE GUIDES

Web apps with ASP.NET Core

Mobile apps with Xamarin.Forms

Microservices with Docker Containers

Modernizing existing .NET apps to the cloud

ARCHIVE

September 2022 August 2022 July 2022 June 2022 May 2022 April 2022 March 2022
February 2022 January 2022 December 2021 November 2021 October 2021 September
2021 August 2021 July 2021 June 2021 May 2021 April 2021 March 2021 February
2021 January 2021 December 2020 November 2020 October 2020 September 2020 August
2020 July 2020 June 2020 May 2020 April 2020 March 2020 February 2020 January
2020 December 2019 November 2019 October 2019 September 2019 August 2019 July
2019 June 2019 May 2019 April 2019 March 2019 February 2019 January 2019
December 2018 November 2018 October 2018 September 2018 August 2018 July 2018
June 2018 May 2018 April 2018 March 2018 February 2018 January 2018 December
2017 November 2017 October 2017 September 2017 August 2017 July 2017 June 2017
May 2017 April 2017 March 2017 February 2017 January 2017 December 2016 November
2016 October 2016 September 2016 August 2016 July 2016 June 2016 May 2016 April
2016 March 2016 February 2016 January 2016 December 2015 November 2015 October
2015 September 2015 August 2015 July 2015 June 2015 May 2015 April 2015 March
2015 February 2015 January 2015 December 2014 November 2014 October 2014
September 2014 August 2014 July 2014 June 2014 May 2014 April 2014 March 2014
February 2014 January 2014 December 2013 November 2013 October 2013 September
2013 August 2013 July 2013 June 2013 May 2013 April 2013 March 2013 February
2013 January 2013 December 2012 November 2012 October 2012 September 2012 August
2012 July 2012 June 2012 May 2012 April 2012 March 2012 February 2012 January
2012 October 2011 September 2011 August 2011 June 2011 April 2011 March 2011
February 2011 January 2011 December 2010 November 2010 October 2010 September
2010 August 2010 July 2010 June 2010 May 2010 April 2010 March 2010 February
2010 December 2009 November 2009 October 2009 September 2009 August 2009 July
2009 June 2009 May 2009 April 2009 March 2009 February 2009 January 2009
December 2008 November 2008 October 2008 September 2008 August 2008 July 2008
June 2008 May 2008 April 2008 March 2008 February 2008 January 2008 December
2007 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007
May 2007 April 2007 March 2007 February 2007 January 2007 December 2006 November
2006 October 2006 September 2006 August 2006 July 2006 June 2006 May 2006 April
2006 March 2006 February 2006 January 2006 October 2005 July 2005 May 2005
December 2004 November 2004 September 2004 June 2004

TOPICS

.NET ASP.NET .NET Core ASP.NET Core .NET Framework Blazor Entity Framework C#
Azure Visual Studio WPF .NET MAUI ML.NET Performance Machine Learning F#
WinForms Maintenance & Updates AI Machine Learning .NET Internals Containers
Security SignalR Community Standup Conversations Developer Stories Cloud WCF
Game Development Lifecycle Debugging GC Docker Show dotnet Networking gRPC
GitHub Actions WebHooks XAML TPL Maoni Concurrency Async Visual Basic Spark for
.NET Big Data Featured Apache Static Analysis SQL Server LOH JSON Orchard Core
IoT


STAY INFORMED








INSERT/EDIT LINK

Close

Enter the destination URL

URL
Link Text
Open link in a new tab

Or link to existing content

Search

No search term specified. Showing recent items. Search or use up and down arrow
keys to select an item.

Cancel


CODE BLOCK

×
Paste your code snippet
Cancel Ok

Feedback

What's new
 * Surface Laptop Go 2
 * Surface Pro 8
 * Surface Laptop Studio
 * Surface Pro X
 * Surface Go 3
 * Surface Duo 2
 * Surface Pro 7+
 * Windows 11 apps

Microsoft Store
 * Account profile
 * Download Center
 * Microsoft Store support
 * Returns
 * Order tracking
 * Virtual workshops and training
 * Microsoft Store Promise
 * Flexible Payments

Education
 * Microsoft in education
 * Devices for education
 * Microsoft Teams for Education
 * Microsoft 365 Education
 * Education consultation appointment
 * Educator training and development
 * Deals for students and parents
 * Azure for students

Business
 * Microsoft Cloud
 * Microsoft Security
 * Dynamics 365
 * Microsoft 365
 * Microsoft Power Platform
 * Microsoft Teams
 * Microsoft Industry
 * Small Business

Developer & IT
 * Azure
 * Developer Center
 * Documentation
 * Microsoft Learn
 * Microsoft Tech Community
 * Azure Marketplace
 * AppSource
 * Visual Studio

Company
 * Careers
 * About Microsoft
 * Company news
 * Privacy at Microsoft
 * Investors
 * Diversity and inclusion
 * Accessibility
 * Sustainability

 * Sitemap
 * Contact Microsoft
 * Privacy
 * Manage cookies
 * Terms of use
 * Trademarks
 * Safety & eco
 * About our ads
 * © Microsoft 2022

Notifications