I was on the lookout for a solution to a problem in Docker that needed to do the following:
Create a Docker Image for a bunch of compiled ASP.NET
.dllfiles and try reducing the
Sounds simple, right? But it turned out to be a bit more messy than I imagined. To top it off,
I have NEVER even programmed in .NET so I was feeling like a visually impaired person made to
navigate his way through a dark room with furniture scattered all over!
Keeping the whole Maritime theme alive with Docker (and Kubernetes), I jumped into the sea of
Docker Hub with millions of containers and found out that Microsoft hosts all the .NET related
container images as .NET by Microsoft registry.
Gentle reminder that I have never even thought of .NET before in my life, so just trying to figure out
whether I need an one or more of the following images:
- ASP.NET Core Runtime
- .NET Runtime
- .NET Runtime Dependencies
- .NET Monitor Tool
- .NET Samples
was a side-mission in its own right.
A quick deep-dive into Microsoft's Docker .NET Docs made me think I only need the following docker image:
So packing everything in a simple
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal WORKDIR /DotNetVoyage COPY ./appsettings.json /DotNetVoyage/Server-Files/ # Copy every '.dll' file I was handed COPY ./* /DotNetVoyage/Server-Files/ CMD [ "dotnet", "Server-Files/Server.dll" ]
Building it locally and accessing the App initially on the dedicated ports seemed to work just fine and I thought
I was getting off work a bit early today. I jinxed myself.
Upon some API testing of the image I started seems some logs that were strange to my non .NETian brain.
The specified framework can be found at: It was not possible to find any compatible framework version The framework 'Microsoft.AspNetCore.App', version '5.0.0' (x64) was not found. - The following frameworks were found: 6.0.6 at [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] You can resolve the problem by installing the specified framework and/or SDK.
I was head scratching as to how I can make my runtime which is
6.0.0 potentially have an SDK version that must
5.0.0 SDK on it. It got worse, I found out I needed the now defunct and not supported
2.1 version of the SDK
Unaware if there was a way to introduce the different SDKs into the already slimmed container image, I had lost hope
and decided to build an image with maybe
However, upon asking the Slack Community and rummaging through some StackExchange queries, I traced out a plan that was
pretty familiar to me: Using Multi-Stage Docker Builds.
I use Multi-Stage Docker builds almost everyday for work and so I decided to design my container image as follows:
Stage 1: pull SDK 2.1 1.1: find out which directory do the SDK Files persist Stage 2: pull SDK 5.1 2.1: find out which directory do the SDK Files persist Stage Prod: Pull the 6.0.0 Runtime Prod.1: copy all the SDK Files (from Stage 1 and Stage 2) to the same directory here in Prod Stage Prod.2: copy all the DLL files from host and run the dedicated DLL
A quick pull:
docker pull mcr.microsoft.com/dotnet/sdk:2.1
and check within the container:
docker run -it --rm --name=sdk21-check mcr.microsoft.com/dotnet/sdk:2.1 dotnet --list-sdks
Gotcha! the directory for the SDKs is
what I mean by this is whether Docker is smart enough to directly pull an image either using
instructions without me having to create
Stage 1 and
Stage 2 using syntax such as:
FROM mcr.microsoft.com/dotnet/sdk:2.1 as base21 FROM mcr.microsoft.com/dotnet/sdk:5.0 as base50
It turns out that
COPY is extremely flexible! with the
COPY --from instruction in the
is completely capable of pull the image from a registry and the dedicated directories can be copied easily!
Final Checks for
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal # Add those missing SDKs here ## Syntax: COPY --from=<registry/image:version> image_directory ProdStage__dest_directory COPY --from=mcr.microsoft.com/dotnet/sdk:2.1 /usr/share/dotnet /usr/share/dotnet/ COPY --from=mcr.microsoft.com/dotnet/sdk:5.1 /usr/share/dotnet /usr/share/dotnet # List all the SDKs / Runtimes available in the container CMD ["dotnet", "--list-sdks", "dotnet", "--list-runtimes"]
build the image and run it and the output will be similar to:
Microsoft.AspNetCore.All 2.1.30 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.30 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 5.0.17 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.30 [/usr/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 5.0.17 [/usr/share/dotnet/shared/Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.6 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Voilá ! Runtimes
v2.1 all in the same container !!
FROM mcr.microsoft.com/dotnet/aspnet:6.0-focal # Add those missing SDKs here ## Syntax: COPY --from=<registry/image:version> image_directory ProdStage__dest_directory COPY --from=mcr.microsoft.com/dotnet/sdk:2.1 /usr/share/dotnet /usr/share/dotnet/ COPY --from=mcr.microsoft.com/dotnet/sdk:5.1 /usr/share/dotnet /usr/share/dotnet WORKDIR /DotNetVoyage COPY ./appsettings.json /DotNetVoyage/Server-Files/ # Copy every '.dll' file I was handed COPY ./* /DotNetVoyage/Server-Files/ CMD [ "dotnet", "Server-Files/Server.dll" ]
Just another day on the decks with Docker !!
Get in touch if you feel like dropping on suggestions, feedbacks or criticism!