How Dockerfile find references - docker

I would like to understand how both dockerfiles works. Specially when restoring project references.
The original dockerfile only has main project in copy, even this project has some dependecies. How are this dependencies restored?
Original
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY ["MyApplication.Api/MyApplication.Api.csproj", "MyApplication.Api/"]
RUN dotnet restore "MyApplication.Api/MyApplication.Api.csproj"
# Copy everything else and build
COPY . .
WORKDIR "/app/MyApplication.Api"
RUN dotnet build "MyApplication.Api.csproj" -c Debug -o /app/build
RUN dotnet publish -c Debug -o /app/out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "MyApplication.Api.dll"]
And this is the dockerfile generated by VisualStudio2022 when docker support is added. In this case it specifies all project references which makes sense to me.
VS2022
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["MyApplication.Api/MyApplication.Api.csproj", "MyApplication.Api/"]
COPY ["MyApplication.Common.Resources/MyApplication.Common.Resources.csproj", "MyApplication.Common.Resources/"]
COPY ["MyApplication/MyApplication.Common.Services/MyApplication.Common.Services.csproj", "MyApplication/MyApplication.Common.Services/"]
COPY ["MyApplication/MyApplication.Common.Domain/MyApplication.Common.Domain.csproj", "MyApplication/MyApplication.Common.Domain/"]
COPY ["MyApplication/MyApplication.Common.DataAccess/MyApplication.Common.DataAccess.csproj", "MyApplication/MyApplication.Common.DataAccess/"]
RUN dotnet restore "MyApplication.Api/MyApplication.Api.csproj"
COPY . .
WORKDIR "/src/MyApplication.Api"
RUN dotnet build "MyApplication.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "MyApplication.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApplication.Api.dll"]
So the exact question would be, how the first option solve references since those are not specified??
The thing is that some of my projects failed on AzureDevops pipelines since it does not find the references, but others work well with the "original" version and this does not make sense at all for me.

Related

.Net 5 Dockerize "/ChatCase.Domain/ChatCase.Domain.csproj" not found

I am new for dockerize a .Net Core project. I have been working on dockerizing my project, but when I build it, it returns an error.
How can I fix this?
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ChatCase.Api/ChatCase.Api.csproj", "ChatCase.Api/"]
COPY ["ChatCase.Framework/ChatCase.Framework.csproj", "ChatCase.Framework/"]
COPY ["ChatCase.Business/ChatCase.Business.csproj", "ChatCase.Business/"]
COPY ["ChatCase.Repository/ChatCase.Repository.csproj", "ChatCase.Repository/"]
COPY ["ChatCase.Core/ChatCase.Core.csproj", "ChatCase.Core/"]
COPY ["ChatCase.Common/ChatCase.Common.csproj", "ChatCase.Common/"]
COPY ["ChatCase.Domain/ChatCase.Domain.csproj", "ChatCase.Domain/"]
RUN dotnet restore "ChatCase.Api/ChatCase.Api.csproj"
COPY . .
WORKDIR "/src/ChatCase.Api"
RUN dotnet build "ChatCase.Api.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ChatCase.Api.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ChatCase.Api.dll"]
cd C:\Projects\ChatCase
docker build . -f ChatCase.API/Dockerfile -t chatcase

Why does this ASP.NET Core Docker Image contain this 'extra' "FROM build AS publish" multistage build step?

I'm trying to understand what the point of this line in this Docker file is:
FROM build AS publish
If I remove it, the build fails with => ERROR FROM docker.io/library/publish:latest so it's obviously needed, but I don't understand why.
It looks to me as though it's unnecessary because publish is an alias for the same image as build. The WORKDIR isn't changed - so what is this line facilitating that is not possible without? Apologies if this is not a clear question, some of these concepts are new to me.
FROM mcr.microsoft.com/dotnet/aspnet:5.0.5-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:5.0.202-buster-slim AS build
WORKDIR /src
COPY NuGet.Config /
COPY ["Something.Api.Common/Something.Api.Common.csproj", "Something.Api.Common/"]
COPY ["Something.Api.Core.WebApi/Something.Api.Core.WebApi.csproj", "Something.Api.Core.WebApi/"]
COPY ["Something.Api.Core.Domain/Something.Api.Core.Domain.csproj", "Something.Api.Core.Domain/"]
RUN dotnet restore "Something.Api.Core.WebApi/Something.Api.Core.WebApi.csproj"
COPY . .
WORKDIR "/src/Something.Api.Core.WebApi"
RUN dotnet build "Something.Api.Core.WebApi.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Something.Api.Core.WebApi.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
...
Answering this my self now. Changing the copy step allows me to remove the 'extra' line. I hadn't understood the --from argument!
COPY --from=build /app/publish .

Error message "Program does not contain a static 'Main' method suitable for an entry point"

I have an ASP.NET CORE app with a few projects inside and the following Dockerfile:
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY src/Mbv.Vans.Core/Mbv.Vans.Core.csproj Mbv.Vans.Core/
COPY src/Mbv.Vans.Common/Mbv.Vans.Common.csproj Mbv.Vans.Common/
COPY src/Mbv.Vans.Api/Mbv.Vans.Api.csproj Mbv.Vans.Api/
RUN dotnet restore Mbv.Vans.Api/Mbv.Vans.Api.csproj
COPY . .
FROM build AS publish
RUN dotnet publish Mbv.Vans.Api/Mbv.Vans.Api.csproj --no-restore -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "Mbv.Vans.Api.dll"]
On line RUN dotnet publish Mbv.Vans.Api/Mbv.Vans.Api.csproj --no-restore -c Release -o /app When it tries to build the project, it fails with error:
"Program does not contain a static 'Main' method suitable for an entry point"
Here is my .csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1591</NoWarn>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>
I searched a lot of questions regarding this issue and divide it into the following resolutions:
COPY . . is not fixing this issue
I have only one static void main
<GenereteProgramFile> false doesn't help.
Could someone can help me to beat this awfull issue?
So, I ran across this same issue and drove me insane. The solution here is to skip the build and go right to a publish.
I was helped by looking at this particular sample: https://github.com/dotnet/dotnet-docker/blob/master/samples/aspnetapp/Dockerfile.alpine-x64
As you can see in there, there is no build occurring. There is a restore, and then a publish. Why no build? I don't know. I'm investigating, but I'm happy it worked for me at least. Let me know how it goes.
Edited for additional info:
Here is the original non-working Dockerfile:
FROM microsoft/dotnet:2.2-aspnetcore-runtime-nanoserver-1809 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM microsoft/dotnet:2.2-sdk-nanoserver-1809 AS build
WORKDIR /src
COPY ["mercurynorth_netcore/mercurynorth_netcore.csproj", "mercurynorth_netcore/"]
RUN dotnet restore "mercurynorth_netcore/mercurynorth_netcore.csproj"
COPY . .
WORKDIR "/src/mercurynorth_netcore"
RUN dotnet build "mercurynorth_netcore.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "mercurynorth_netcore.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "mercurynorth_netcore.dll"]
...and here the the newly working Dockerfile:
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-alpine AS build
WORKDIR /app
# Lets do a restore of the NuGet packages, and then restore the app in a container.
COPY mercurynorth_netcore.csproj ./
RUN dotnet restore "mercurynorth_netcore.csproj"
COPY . .
RUN dotnet publish "mercurynorth_netcore.csproj" -c Release -o /app
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS final
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY --from=build /app .
ENTRYPOINT ["dotnet", "mercurynorth_netcore.dll"]
As you can see, what I generally did was remove the line:
RUN dotnet build "mercurynorth_netcore.csproj" -c Release -o /app
...as well as do some clean-up.
The general take-away is that running the build command on my dev machine(s) will work fine, but as part of building the container, it will fail.

Why does the ASP.NET Core Multi-Stage Dockerfile use 4 Stages

This is the default multi-stage Dockerfile when you click on 'Add Docker Support' in Visual Studio on an ASP.NET Core site.
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY WebApplication1.sln ./
COPY WebApplication1/WebApplication1.csproj WebApplication1/
RUN dotnet restore
COPY . .
WORKDIR /src/WebApplication1
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
Why have they chosen to use four stages, starting and finishing with the base stage. Also, why create a publish stage using the same build base image. Why does the Dockerfile not look like this with three stages:
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY WebApplication1.sln ./
COPY WebApplication1/WebApplication1.csproj WebApplication1/
RUN dotnet restore
COPY . .
WORKDIR /src/WebApplication1
RUN dotnet build -c Release -o /app
FROM build AS publish
RUN dotnet publish -c Release -o /app
FROM microsoft/aspnetcore:2.0 AS final
WORKDIR /app
EXPOSE 80
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
Is there some advantage to this that I am missing?
The file effectively equivalent to below
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY WebApplication1.sln ./
COPY WebApplication1/WebApplication1.csproj WebApplication1/
RUN dotnet restore
COPY . .
WORKDIR /src/WebApplication1
RUN dotnet build -c Release -o /app
RUN dotnet publish -c Release -o /app
FROM microsoft/aspnetcore:2.0 AS base
EXPOSE 80
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
Now the reason they may have chosen 4 build stage might be any of the two
Presentational
Future changes
So it may be that it depicts a
base -> build -> publish -> deploy the build
The size with 2 build stage would also the same as this one. So there is no obvious difference between the 2 stage and the 4 stage. It becomes a matter preference, representation and all. Nothing technologically different
There is no programatic reason for using 4 stages.
In the first stage just configuration is changed. In the third stage the image is not changed. The only use of FROM build AS publish to have a new alias.
I think there is no use of taking care of later changes in the build structure of docker. (The 4 stage code probably does that.) Use versioned images, just like in your example. E.g. 2.0 instead of latest. This way incomatibility can be avoided. If there will be changes in the way of the build, you can catch up with it.
The docker recommendation works with no csproj name specified, as using *.csproj. That works for most of the projects, producing about 350MB image-size.

asp.net core docker image cannot find the installed sdk

I have created an Asp.net core project using :
dotnet new webapi
and I have added the following Dockerfile to my project:
# https://hub.docker.com/_/microsoft-dotnet-core
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app
# copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore
# copy everything else and build app
COPY . ./
RUN dotnet publish -c release -o out
# final stage/image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
WORKDIR /app
EXPOSE 80
COPY --from=build /app/out ./
ENTRYPOINT ["dotnet", "myaspnetapp.dll"]
I can build the image but when I run it I am getting the following error :
It was not possible to find any installed .NET Core SDKs
Did you mean to run .NET Core SDK commands? Install a .NET Core SDK from:
https://aka.ms/dotnet-download
Would you please tell me what I am missing here .
My best guess is that you hand coded this Dockerfile.
I have had terrible luck with hand-written Dockerfile myself.
Add a docker file using Visual Studio.
Right Click solution.
Click Add
Click Docker Support.
You should see below Dockerfile.
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 build
WORKDIR /src
COPY ["myaspnetapp.csproj", ""]
RUN dotnet restore "./myaspnetapp.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "myaspnetapp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "myaspnetapp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "myaspnetapp.dll"]
Hopefully, that'll solve it.
I'll add more to the answer when I find out about it.

Resources