The .Net 7 release is bringing a lot of changes, and one of the most significant is the removal of the need for a Dockerfile
. Container images are now a supported output type of the .NET SDK.
You no longer need a separate Dockerfile to containerize your .NET applications. You can publish your application and it will be built into a container image.
This is a significant improvement for .NET developers who want to containerize their applications. It will make it much easier to distribute and run your applications in the cloud. In this article, we’ll take a look at what this change means for you and your applications.
Previously in Dockerfile
Create a new Web API project, and open the project in Visual Studio. In the solution explorer, right-click on the project and select Add Docker Support
. This will enable the addition of Docker functionality to the pre-existing project
The following Dockerfile was generated by Visual Studio when docker support was added. It provides a helpful starting point for configuring your application’s Docker environment. You can customize the contents of this file as needed to fit your application’s requirements. Take a look at what’s included below:
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["ApiWithDockerfile/ApiWithDockerfile.csproj", "ApiWithDockerfile/"]
RUN dotnet restore "ApiWithDockerfile/ApiWithDockerfile.csproj"
COPY . .
WORKDIR "/src/ApiWithDockerfile"
RUN dotnet build "ApiWithDockerfile.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ApiWithDockerfile.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ApiWithDockerfile.dll"]
Visual Studio will detect the type of project (aspnet) and its version (7.0), download the runtime to run the application, download the SDK for building the application, and execute necessary COPY
and dotnet restore
commands associated with the project’s csproj
.
If we want to build and run the project in docker, Visual Studio is an option. For those who prefer the command line, we can run this command from the solution root level
docker build -f ApiWithDockerfile/Dockerfile -t apiwithdockerfile:0.1 .
The following command will enable you to run the project in a local docker environment:
docker run -p 5000:80 apiwithdockerfile:0.1
You can now call the weather API http://localhost:5000/WeatherForcast
and should receive a normal response without any issues. That’s all there is to it.
The Annoying part
It can be quite difficult to maintain multiple projects while working with Dockerfiles. You need to be sure that all of the paths, variables, and ports are accurate in order for your Dockerfile to build and run as expected. Even seemingly small errors can lead to big headaches down the line. This task may quickly become overwhelming if you have several projects going within your Dockerfile.
The new part in .Net 7
In .Net 7, Microsoft made it easier than ever to deploy your apps to containers using their new Nuget package, Microsoft.NET.Build.Containers
! It allows your project to be self-aware of its ability to be deployed in a container, and after adding the Nuget package you can simply publish the application by using the dotnet publish
command in your project’s root folder – no need for a Dockerfile!
dotnet publish -os linux --arch x64 -p:PublishProfile=DefaultContainer
This will publish a new docker image with a tag/version 1.0.0
and the name of the image is the same name as the project.
Now you can use the same docker run command to launch your newly built image with a default tag of 1.0.0
docker run -p 5000:80 apiwithdockerfile:1.0.0
Using csproj properties
I think I know what your next question is – how do you run DevOps pipelines without manually adding all the variables into each publish command? The solution lies in the csproj file. Check out this example
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PublishProfile>DefaultContainer</PublishProfile>
<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:7.0</ContainerBaseImage>
<ContainerRegistry>myregistry.com:1234</ContainerRegistry>
<ContainerImageTag>1.0.1-patch2</ContainerImageTag>
</PropertyGroup>
<ItemGroup>
<ContainerPort Include="80" Type="tcp" />
<ContainerEnvironmentVariable Include="MyVariable" Value="MyValue" />
</ItemGroup>
<PropertyGroup Condition=" '$(RunConfiguration)' == 'https' " />
<PropertyGroup Condition=" '$(RunConfiguration)' == 'http' " />
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Microsoft.NET.Build.Containers" Version="0.2.7" />
</ItemGroup>
</Project>
ContainerBaseImage
: It’s possible to change the base image detected from the project to use a different runtime if it better fits your needs. Overriding the default base image provides more flexibility in terms of usage.
ContainerRegistry
If you intend to upload your image to a cloud registry
At the moment of writing, authentication for a cloud registry isn’t supported yet.
ContainerImageTag
Save the image tag, and if you need to specify multiple tags, you can use ContainerImageTags
and provide a comma-separated list. For environment variables, use the ContainerEnvironmentVariable
parameter, and specifying ports can be done with ContainerPort
.
Conclusion
In conclusion, you no longer need a Dockerfile. This is good news because it means that you can spend less time managing your Dockerfiles and more time focusing on your application. This article showed you how to use the new package Microsoft.NET.Build.Containers
and how to publish your .Net application into a docker container.
You can check the source code here in my github repository https://github.com/mhdbouk/NoDockerFileSupport/
Happy coding and catch you in the next one 👋
I simply love your blog, pal.
Thank you for your hard working
Happy 2023.
Wander
Thank you so much, Wander! I’m glad you enjoy reading my blog. Happy 2023 to you too!