Freddx L.
Freddx L.

Reputation: 635

docker build stuck on dotnet restore

I'm trying to create a docker image of a .NET 6 project, but is stuck during dotnet restore while using +12GB of RAM.

My project structure is:

- backend/
- frontend/

Where I just cd in the backend/ and run docker build .

enter image description here

This is the output of the console currently:

[+] Building 276.4s (15/19)
 => [internal] load .dockerignore                                                                                                           0.0s 
 => [internal] load build definition from Dockerfile.server                                                                                 0.0s 
 => [internal] load metadata for mcr.microsoft.com/dotnet/sdk:6.0                                                                           0.6s 
 => [internal] load metadata for mcr.microsoft.com/dotnet/aspnet:6.0                                                                        0.6s 
 => [stage-1 1/3] FROM mcr.microsoft.com/dotnet/aspnet:6.0@sha256:9ca180a6a0a0ec39209437e5e0986caf17b7d91473d9c34bb6191e47a7b500aa          0.0s 
 => [build-env 1/6] FROM mcr.microsoft.com/dotnet/sdk:6.0@sha256:ca4344774139fabfb58eed70381710c8912900d92cf879019d2eb52abc307102           0.0s 
 => [internal] load build context                                                                                                           0.2s 
 => => transferring context: 3.69kB                                                                                                         0.2s 
 => CACHED [stage-1 2/3] WORKDIR /app                                                                                                       0.0s 
 => CACHED [build-env 2/6] WORKDIR /app                                                                                                     0.0s 
 => CACHED [build-env 3/6] COPY *.csproj ./                                                                                                 0.0s 
 => [build-env 4/6] RUN dotnet restore                                                                                                    270.2s

My csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>enable</Nullable>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <NoWarn>1701;1702;1705;1591;10102;</NoWarn>
    <DefaultItemExcludes>**\node_modules\**;$(DefaultItemExcludes)</DefaultItemExcludes>
  </PropertyGroup>

  <ItemGroup>
    <Watch Include="..\**\*.env" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="AutoMapper" Version="10.1.1" />
    <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
    <PackageReference Include="BCrypt.Net-Next" Version="4.0.2" />
    <PackageReference Include="dotenv.net" Version="3.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="6.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Certificate" Version="5.0.12" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
  </ItemGroup>

</Project>

This is my Dockerfile:

# syntax=docker/dockerfile:1
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

ARG Config=Debug
ENV ASPNETCORE_URLS=http://*:5000

# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore

# Copy everything
COPY . .

# Publish
RUN dotnet publish -c ${Config} -o /app/publish

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/publish .
ENTRYPOINT ["dotnet", "myapp.dll"]

My net usage: net usage

This is a pass result (1 hour) building: enter image description here

Upvotes: 3

Views: 8526

Answers (4)

MichaelM
MichaelM

Reputation: 1109

On the GitHub issue (probably) made by the poster here, there is a comment which states the following:

Because the project is being placed in a directory that is directly under the root of the container, this path causes a scan of the entire container's file system. This slows things down tremendously.

In other words, the COPY and RUN dotnet restore command are potentially being made in the root of the Docker container, which causes .NET to scan the entire container file system, which causes the restore command to "freeze up".

A potential solution is to ensure you are placing the files into a new directory by using the WORKDIR instruction.

WORKDIR /app

COPY *.csproj .

RUN dotnet restore

Note, that you will need to update subsequent jobs to point to the new path (in the example above, '/app').

Upvotes: 1

elshev
elshev

Reputation: 1573

In my case the .csproj file didn't contain any <Watch/> tag but the dotnet restore step stuck anyway. I found the solution in this GitHub comment. In Dockerfile, instead of using version 6.0:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build

I used version 8.0:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build

Upvotes: -2

kudzanayi
kudzanayi

Reputation: 101

In a different case, I thought my application was stuck on the restore, however it was stuck on the build. You can also add the following to flags to your dotnet restore command as well as your dotnet build command to get more information when your build is running -v diag

# RUN dotnet restore "Myproject.Ticketing/Myproject.Ticketing.csproj"
# So instead of just the line at the top, add the -v diag flag like below

RUN dotnet restore -v diag "Myproject.Ticketing/Myproject.Ticketing.csproj"
RUN dotnet build "Myproject.Ticketing.csproj" -c Release -o /app/build -v diag

Remember, this is in the Dockerfile. What I did was I first put -v diag on the dotnetrestore and that's when I realized after looking at the output that it was actually passing that stage. Next I removed it from the restore and put the same flag on the build line, this is because there was just a lot of information being output, so I just wanted to limit the output.

Well, the conclusion was that, for me, the last phrase written on the output was

warnaserror+:NU1605 (TaskId:105)

Which after googling gave me

A dependency package specified a version constraint on a higher version of a package than restore ultimately resolved.

https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu1605

So although my application was building and working great in development, there was a library I was depending on that depends on .Net Core 3.1 but yet I am using .Net 6, and the docker container being built is also building on top of .Net 6

Don't ask me how it works, it just did.

I got the -v flag from reading this article which also helps with the whole hanging problem https://tsuyoshiushio.medium.com/solving-flaky-dotnet-restore-issue-only-on-docker-failed-to-retrieve-information-cd847573c3f2

For a list of the meanings and options you can put on the dotnet command,

eg -v diag is short for --verbosity diagnostic (so lots of info since you want to diagnose a proble) you can view https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-restore#options

Upvotes: 2

Freddx L.
Freddx L.

Reputation: 635

Solved, the problem was in my .csproj

 <ItemGroup>
    <Watch Include="..\**\*.env" />
  </ItemGroup>

I changed it to:

  <ItemGroup>
    <Watch Include="..\**\*.env" Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' != 'true'" />
  </ItemGroup>

Upvotes: 3

Related Questions