Docker Images can be generated in dotnet projects without a Dockerfile. Did you know?
Did you know that you can generate Docker Images in dotnet projects? Traditionally we would use a Dockerfile to generate Docker Images, but that's not the only way.
Dockerize a console app
Consider that you have a console app and you want to generate a Docker Image for it. You can do it by adding some additional lines to your .csproj
file.
Before:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
After:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ContainerRepository>console</ContainerRepository>
<ContainerImageTag>1.2.3</ContainerImageTag>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Build.Containers" Version="8.0.100-rc.2.23480.5" />
</ItemGroup>
</Project>
When you compare you will notice the addition of ContainerRepository
, which represents the Image name, and ContainerImageTag
, which represents the Image tag.
There are many more attributes that you can use to match Dockerfile capabilities on dotnet, check the official Microsoft documentation.
Because this is not a Web project, the package reference to Microsoft.NET.Build.Containers
needs to be added to the console project.
At the time of this writing, the latest version of
Microsoft.NET.Build.Containers
is8.0.100-rc.2.23480.5
.
Then run the following CLI command:
dotnet publish -r linux-x64 /t:PublishContainer
You will notice that the os
is linux
and the architecture
is x64
, represented together by r
, the Runtime Identifier
. When the command above is run, dotnet CLI is going to generate a Dockerfile leveraging the package Microsoft.NET.Build.Containers
inferring:
- Which base image to use.
- Which version of the base image to use.
- Where to push the generated image.
To run the image locally as a container, run the following command:
docker run console:1.2.3
Dockerize a web app
Similarly to the console app, the same can be done for web projects. The only difference is that the package reference to Microsoft.NET.Build.Containers
is not needed, as the project leverages Microsoft.NET.Sdk.Web
sdk.
Before:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
</Project>
After:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<ContainerRepository>weatherapi</ContainerRepository>
<ContainerBaseImage>mcr.microsoft.com/dotnet/aspnet:8.0</ContainerBaseImage>
<ContainerImageTag>1.0.0</ContainerImageTag>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
</Project>
When you compare you will notice the addition of ContainerRepository
, which represents the Image name, ContainerBaseImage
representing the base image and ContainerImageTag
, which represents the Image tag.
There are many more attributes that you can use to match Dockerfile capabilities on dotnet, check the official Microsoft documentation.
Then run the following CLI command:
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer
To run the image locally as a container, run the following command:
docker run -p 5000:8080 weatherapi:1.0.0
In .NET 8.0, the internal port number for web projects starts on port 8080
by default. This is because of the rootless execution on port 8080, not requiring root permission as if it would run on port 80.
Check the repository example on PlayGoKids repository to validate the commands yourself.