A lot of people use the dotnet cli to build their projects, and its a very handy tool, but there’s a lot of version of dotnet out there these days, and maintaining build agents in your CI with all the right version can be troublesome.
So that’s where containers can help you, and make sure you are building with the right sdk.
I’ll use a recent example from a project we did in github acitons.
in this build we run
dotnet restore mySolution.sln
dotnet build mySolution.sln --configuration Debug --no-restore
dotnet test --no-build
This project in question we are using dotnet 3.1 sdk.
So to run these in docker we can simple use a docker run with the sdk container
docker run -v ${PWD}:/scr --workdir /src mcr.microsoft.com/dotnet/core/sdk:3.1-buster dotnet build mysolution.sln
This will mount the current working directory into the container and use the sdk inside to run the build.
This isn’t the best approach though, the nuget cache for the container will be lost at the end of the build as its stored in user scope.
A better approach is to use a multi-staged docker file, then it will take advantage of cache in the docker chunks. You can add docker files from teh visual studio IDE that have things preconfigured for good performance for you.

The basic docker file looks like the below
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS builder
WORKDIR /src
COPY *.sln ./
COPY ["Agoda.Api.WebApi/Agoda.Api.WebApi.csproj", "Agoda.Api.WebApi/"]
COPY ["Agoda.Api.Core/Agoda.Api.Core.csproj", "Agoda.Api.Core/"]
COPY docker-compose.dcproj ./
RUN dotnet restore "Agoda.Api.WebApi/Agoda.Api.WebApi.csproj"
COPY . .
WORKDIR "/src/Agoda.Api.WebApi"
RUN dotnet build "Agoda.Api.WebApi.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "Agoda.Api.WebApi.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Agoda.Api.WebApi.dll"]
There’s a couple of points to note here.
Firstly you can see the files are copied into the container to build, project files first, and restore is done separately. The reason for this is we create a chunk with the csproj files so that this chunk will only rebuild if the project files change (i.e. this is generally when you update your dependencies), so this chunk will remain cached on your local or on the CI agent and not rebuild unless you update the csproj.
The second thing to note is that there is multiple FROM statements, this is because it is a multi stage docker file, so it has a large builder container that starts with the SDK, and a smaller base container that the output of the build is copied to in order to have a small output container for production.
So to build this one we simply now run:
docker build . -f Agoda.Api.WebApi/Dockerfile -t agodaapi:1.0
This should be run from the root dir of your solution, and Visual Studio puts the docker file in the sub folder.
You can then run a docker push to publish your newly built container.
You can use the similar approach by using a dockerfile with your unit test project, but in that case you don’t need a multistage, you just need a normal docker file that use sdk image and runs “dotnet test” as the entrypoint.