The new .NET SDK supports creating Docker images without using Dockerfiles – just by using the .NET CLI – with .NET 7. At this time, it’s just a preview and some features are not yet available, but I had to try it anyway.
This article shows what I had to change with an existing ASP.NET Core Web API project that’s deployed to Azure Container Apps using GitHub actions.
Removing the Dockerfile
The ASP.NET Core application already contains a previously created Dockerfile as shown in the next image. The Dockerfile uses a multi-stage build process to build the application. For building the application, the base image used is mcr.microsoft.com/dotnet/sdk:7.0 which includes the .NET SDK. Because the web application references some libraries, the libraries need to be built as well. After using the CLI command dotnet restore to restore the NuGet packages, unit tests run with dotnet test, and the application is built with dotnet build.
> When creating the Dockerfile, I decided to run the unit tests directly from within the Dockerfile. This way it was not required to install the preview version of the .NET SDK with the build agent, as this version of the SDK was already available with the base image.
In another stage, the files needed for publishing are created with dotnet publish. The final stage makes use of the base image mcr.microsoft.com/dotnet/aspnet:7.0 which includes the ASP.NET Core runtime.
Now I’m just getting rid of this Dockerfile.
> Some months ago I had some work creating this Dockerfile. With the next project I can spare this time. One issue why removing the Dockerfile helps is explained in the article link below (Announcing built-in container support for the .NET SDK) describing the Docker build context. I always had to specify the context explicitly when building the image because some configuration files are in a base directory from the location of the Dockerfile.
Instead of using a Dockerfile, the NuGet package Microsoft.NET.Build.Containers needs to be added.
Using the dotnet publish enhancements
To support the dotnet publish command, the project file can be changed to include the elements RuntimeIdentifier
and PublishProfile
:
To locally build the application, I just used dotnet publish
. If the RuntimeIdentifier
and PublishProfile
elements are not included, these values can be supplied as arguments to the dotnet publish
command:
dotnet publish CodeBreaker.APIs.sln --os linux --arch x64 -p:PublishContainer=DefaultContainer,ContainerImageName=codebreakerapi
Just using dotnet publish, the image is built – without creating a Dockerfile, without specifying the base images. With ASP.NET Core applications, the base image used is mcr.microsoft.com/dotnet/aspnet with the tag of the .NET version used.
These are the images used automatically:
- ASP.NET Core apps: mcr.microsoft.com/dotnet/aspnet
- Self-contained apps: mcr.microsoft.com/dotnet/runtime-deps
- Other .NET apps: mcr.microsoft.com/dotnet/runtime
By default, the Debian distribution is used. To specify a different base image, the image can be specified the the ContainerBaseImage
element:
mcr.microsoft.com/dotnet/aspnet:7.0-alpine
The default name of the image created uses the AssemblyName
. This name is automatically converted to lowercase as required
Publishing with GitHub Actions
To automatically build and publish the application to Azure Container Apps, I’m using GitHub Actions.
Previous Version using the Docker CLI
The next image shows the previous version I was using:
- docker/setup-buildx-action to setup docker
- docker/login-action to login to the Azure Container Registry (ACR)
- docker/build-push-action to build the Docker image, and to publish the image to ACR.
With the build-push-action I specified the tags, the Dockerfile, and the Docker context, and set the push configuration to push the image after building it.
New Version using the .NET CLI
With the updated version, the Docker commands can be replaced by using the .NET CLI.
- actions/setup-dotnet to setup .NET – .NET previously was only used within the Dockerfile
- dotnet test to run the unit tests, which was done within the Dockerfile previously
- dotnet publish to build the Docker image
In a future version, dotnet publish might be the last command needed to publish the image to the ACR. However, currently dotnet publish does not support authenticating with a container registry. That’s why some docker commands are still used:
- actions-hub/docker/login to login to ACR
- actions-hub/docker/cli with the argument tag to tag the image for publishing it to the repository
- actions-hub/docker/cli with the argument push to push the image to the repository
> Authentication is an important feature; this enhancement is planned for .NET 7 RC1 (see the link below).
With the previous version of the GitHub Action, I didn’t use the .NET CLI at all – just the Docker commands. Now, .NET is configured with the actions/setup-dotnet action.
Deploying the image from ACR to Azure Container Apps was not changed between the previous version and the updated version. I left this code in the images to show how this works.
Take away
The .NET CLI is the command that can be used to create, build, test, and publish .NET applications. Having features for building containers built-in to this CLI reduces complexity and makes it easier to use for .NET developers.
Enjoy learning and programming!
Christian
Thank you for your support of my blog by buying a coffee. During these months all the coffees (and more) will be used to support the Ukraine.

More Information
More information about creating ASP.NET Core services is available in my book:
Professional C# and .NET – 2021 Edition
Related Information
Announcing built-in container support for the .NET SDK
GitHub Repo – SDK Container Builds
SDK Container Builds – Design and implement authentication to registries
Docker Reference Documentation
Image Shipping Container ID 28175631 © Tutku Tetik | Dreamstime.com
It seems somehow the formatting is broken a bit:
> include the elements and:
> the image can be specified the the “ element:
LikeLiked by 1 person
@Markus Schaber – thanks for this information! Using the WordPress Markdown element, WordPress removed the angle bracket content within the markdown code element. Changed it.
LikeLike