dotnet / dotnet-docker

Docker images for .NET and the .NET Tools.
https://hub.docker.com/_/microsoft-dotnet
MIT License
4.42k stars 1.93k forks source link

.NET6 docker build stuck on dotnet restore #3338

Closed Neo-Ciber94 closed 2 years ago

Neo-Ciber94 commented 2 years ago

Describe the Bug

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", "ISO810_ERP.dll"]

My net usage: net usage

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

Steps to Reproduce

Clone https://github.com/Neo-Ciber94/ISO810_ERP And run cd backend && docker build -f Dockerfile.server .

Other Information

Output of docker version

Client: Cloud integration: v1.0.22 Version: 20.10.11 API version: 1.41 Go version: go1.16.10 Git commit: dea9396 Built: Thu Nov 18 00:42:51 2021 OS/Arch: windows/amd64 Context: default Experimental: true

Server: Docker Engine - Community Engine: Version: 20.10.11 API version: 1.41 (minimum version 1.12) Go version: go1.16.9 Git commit: 847da18 Built: Thu Nov 18 00:35:39 2021 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.4.12 GitCommit: 7b11cfaabd73bb80907dd23182b9347b4245eb5d runc: Version: 1.0.2 GitCommit: v1.0.2-0-g52b36a2 docker-init: Version: 0.19.0 GitCommit: de40ad0

Output of docker info

Client: Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc., v0.7.1) compose: Docker Compose (Docker Inc., v2.2.1) scan: Docker Scan (Docker Inc., 0.9.0)

Server: Containers: 1 Running: 1 Paused: 0 Stopped: 0 Images: 2 Server Version: 20.10.11 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2 Default Runtime: runc Init Binary: docker-init containerd version: 7b11cfaabd73bb80907dd23182b9347b4245eb5d runc version: v1.0.2-0-g52b36a2 init version: de40ad0 Security Options: seccomp Profile: default Kernel Version: 5.10.16.3-microsoft-standard-WSL2 Operating System: Docker Desktop OSType: linux Architecture: x86_64 CPUs: 8 Total Memory: 12.39GiB Name: docker-desktop ID: U5CE:U4D3:OMG7:YPA5:TNN5:L6IO:CRVZ:CYE4:Y3TN:7WEM:KSQV:XTS6 Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false

WARNING: No blkio throttle.read_bps_device support WARNING: No blkio throttle.write_bps_device support WARNING: No blkio throttle.read_iops_device support WARNING: No blkio throttle.write_iops_device support

mthalman commented 2 years ago

[Triage] The issue is with this part of the csproj: https://github.com/Neo-Ciber94/ISO810_ERP/blob/8d9d8dae062245457b72b690cb61cb2db962af4d/backend/ISO810_ERP.csproj#L13

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.

One way to workaround this is to not have the <Watch> items apply during a Docker restore/build. This could be done by setting an IsDockerBuild MSBuild property when running the dotnet restore and dotnet publish commands:

RUN dotnet restore /p:IsDockerBuild=true

And then modifying your project file to conditionally enable the <Watch> item if that property is not true:

<Watch Include="..\**\*.env" Condition=" '$(IsDockerBuild)' != 'true' " />
Neo-Ciber94 commented 2 years ago

[Triage] The issue is with this part of the csproj: https://github.com/Neo-Ciber94/ISO810_ERP/blob/8d9d8dae062245457b72b690cb61cb2db962af4d/backend/ISO810_ERP.csproj#L13

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.

One way to workaround this is to not have the <Watch> items apply during a Docker restore/build. This could be done by setting an IsDockerBuild MSBuild property when running the dotnet restore and dotnet publish commands:

RUN dotnet restore /p:IsDockerBuild=true

And then modifying your project file to conditionally enable the <Watch> item if that property is not true:

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

Thanks, that solved my issue, I used DOTNET_RUNNING_IN_CONTAINER instead:

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

mthalman commented 2 years ago

I had considered the use of DOTNET_RUNNING_IN_CONTAINER as a solution as well. But I realized that that would prevent you from running scenarios where you do want to use dotnet watch in the context of a container. So if that's a scenario that you'd want to support, you'd have to introduce your own MSBuild property.

NurulloSulaymonov commented 1 year ago

Hello Above problem occured when I build .net 7 project on docker

image

richlander commented 1 year ago

What is the problem? Is the build hanging at that point?

MxD-js commented 1 year ago

Same issue as @NurulloSulaymonov, just get's stuck with .net 7

I enabled -v diag on dotnet restore but nothing happens,

image

It hangs then times out after a long delay.

image
richlander commented 1 year ago

Any chance you are doing this on an Apple M1 machine?

MxD-js commented 1 year ago

I am building this on a M1, but I issued a platform flag for linux/amd64 which this will ultimately will run on.

docker build --platform linux/amd64 -t sccenter_image_test .
richlander commented 1 year ago

That's the problem. .NET doesn't support QEMU.

More context: https://github.com/dotnet/dotnet-docker/discussions/3848

MxD-js commented 1 year ago

Thanks for linking the discussion however I am using the Workaround 1 as mentioned in the discussion. I added --platform linux/amd64 to the build command, same result.

andrekiba commented 1 year ago

seems the problem is --platform linux/amd64, removing the option the build completes in few seconds... but on M1 is linux/arm64

richlander commented 1 year ago

It looks like that worked with .NET 6 but not .NET 7. I'll have to update that.

sairohith-vanna commented 1 year ago

This happens to me only when I add --platform=linux/amd64 for build, on my M1 Pro machine. It just gets stuck restore. I need to deploy the app - which is .NET 7 based - to a Kubernetes cluster that has a couple of Linux nodes, hence need to generate an AMD64 build. Is there any workaround for .NET 7 or is it advisable to just step down to .NET 6? It's just a PoC app so downgrade shouldn't matter; but end of the day it must work for .NET 7 too.

richlander commented 1 year ago

You can use workaround 2 in the doc I linked to.

It is the same approach that was used at https://github.com/dotnet/aspnetcore/issues/46306

MxD-js commented 1 year ago

Hmm. I tried Workaround 2 and getting the same result. I removed the --platfrom linx/amd64 from the command line, but the process get's stuck on dotnet restore command. This is my Dockerfile

ARG ARCH=amd64
ARG TAG=7.0-bullseye-slim-$ARCH
FROM mcr.microsoft.com/dotnet/aspnet:$TAG AS base
#####################
#PUPPETEER RECIPE
#####################
RUN apt-get update && apt-get -f install && apt-get -y install wget gnupg2 apt-utils
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' >> /etc/apt/sources.list
RUN apt-get update \
&& apt-get install -y google-chrome-stable --no-install-recommends --allow-downgrades fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf
######################
#END PUPPETEER RECIPE
######################
ENV PUPPETEER_EXECUTABLE_PATH "/usr/bin/google-chrome-stable"
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:$TAG AS build
WORKDIR /src
COPY ["sccenter_puppeteer_sharp/sccenter_puppeteer_sharp.csproj", "sccenter_puppeteer_sharp/"]
RUN dotnet restore -v diag "sccenter_puppeteer_sharp/sccenter_puppeteer_sharp.csproj"
COPY . .
WORKDIR "/src/sccenter_puppeteer_sharp"
RUN dotnet build "sccenter_puppeteer_sharp.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "sccenter_puppeteer_sharp.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "sccenter_puppeteer_sharp.dll"]
image
richlander commented 1 year ago

I think I gave some bad advice, sadly. I'll get back to you on Monday with clearer guidance. I misunderstood an aspect of how Docker works.

richlander commented 1 year ago

FYI: https://github.com/dotnet/dotnet-docker/issues/4388#issuecomment-1470996533

richlander commented 1 year ago

FYI: https://devblogs.microsoft.com/dotnet/improving-multiplatform-container-support/

douglasg14b commented 1 year ago

This seems to be an ongoing problem, why is the issue closed?

vmandic commented 1 year ago

+1 same issue here on Apple M1, dotnet7.0 SDK, trying to build and run on Apple M1 (+ I need single file, self contained and cant use bullseye-slim, doing all of this to test TieredPGO=true and other JIT optimizations).

I get to bypass some problems by specifying the RID as osx.12-arm64 but I cant get the project to start, all I get when I try to start my exe in container is:

/bin/sh: 1: ./MyApp: Exec format error

My images (dockerfile is) are:

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
...
FROM mcr.microsoft.com/dotnet/runtime-deps:7.0-alpine
...
ENTRYPOINT exec ./MyApp

Other combinations just get stuck at dotnet restore forever. Specifying docker --platform does not help out. This is really frustrating as I was hoping to get this solved when moving from netcoreapp3.1 and this has not moved an inch for supporting Apple M1. For all docker ops I have to switch to a spare Win x64 to do the related work.

douglasg14b commented 1 year ago

@vmandic Your issue is different I think, and is because .Net SDK < 7.0.3 build environment has some issues on apple silicon and a problem with QEMU. Specifically it will hang on restore.

The solution is to wait for .Net SDK v 7.0.3 to be released, or to target .Net 8 Preview in your Dockerfile mcr.microsoft.com/dotnet/nightly/sdk:8.0-preview. The SDK verison in the final app/image doesn't matter afaik as long as it's equal to or higher than the SDK version your project builds with.

Relevant blog post:

https://devblogs.microsoft.com/dotnet/improving-multiplatform-container-support/

There is unfortunately a whole rash of closed github issues that only link to closed github issues to track the problem....

Maclay74 commented 1 year ago

@vmandic Your issue is different I think, and is because .Net SDK < 7.0.3 build environment has some issues on apple silicon and a problem with QEMU. Specifically it will hang on restore.

The solution is to wait for .Net SDK v 7.0.3 to be released, or to target .Net 8 Preview in your Dockerfile mcr.microsoft.com/dotnet/nightly/sdk:8.0-preview. The SDK verison in the final app/image doesn't matter afaik as long as it's equal to or higher than the SDK version your project builds with.

Relevant blog post:

https://devblogs.microsoft.com/dotnet/improving-multiplatform-container-support/

There is unfortunately a whole rash of closed github issues that only link to closed github issues to track the problem....

I tried with 8.0 preview, still hangs on dotnet restore.


FROM mcr.microsoft.com/dotnet/nightly/sdk:8.0.100-preview.6-bookworm-slim-amd64 AS build

# Install make
RUN apt-get update && \
    apt-get install -y make build-essential libc6-dev

# Run building script
ENTRYPOINT [ "/backend/entrypoint.sh" ]

Also tried mcr.microsoft.com/dotnet/nightly/sdk:7.0.302-bullseye-slim-amd64 no luck, still hangs on restore.

But mcr.microsoft.com/dotnet/nightly/sdk:6.0-bullseye-slim-amd64 works though.

vernou commented 1 year ago

I have the same problem on Windows 10 Pro. Maybe a dedicated ticket to .NET7 (and .NET8?) is needed.

vernou commented 1 year ago

I add in the Dockerfile the instruction WORKDIR and now the restore work. Without, I think the command restore is executed at the root and this provoke the issue.

nicholasyin commented 12 months ago

+1 why was this closed as there's no clear solution to the 'restore hanging' issue.

tjhorner commented 11 months ago

Can a maintainer please re-open this issue? It's still occurring, even in the .NET 8 release candidate image.

lbussell commented 11 months ago

[Triage] This issue is about disabling dotnet Watch for Docker builds and was resolved with https://github.com/dotnet/dotnet-docker/issues/3338#issuecomment-995148905. If you are having restore issues in scenarios unrelated to dotnet watch, please open a new issue with detailed repro steps.

@nicholasyin @tjhorner

unseensenpai commented 10 months ago

Still got problem about restoring nugets on .net 7 in linux/alpine docker system.

MichaelSimons commented 10 months ago

Still got problem about restoring nugets on .net 7 in linux/alpine docker system.

Does your scenario involve dornet-watch? If not please open a new issue with steps to reproduce the issue. TIA.

MattMckenzy commented 10 months ago

I add in the Dockerfile the instruction WORKDIR and now the restore work. Without, I think the command restore is executed at the root and this provoke the issue.

I was also getting stuck on dotnet restore with .NET 8. This fixed it immediately, thanks for your comment!

lbanchero commented 8 months ago

I add in the Dockerfile the instruction WORKDIR and now the restore work. Without, I think the command restore is executed at the root and this provoke the issue.

I was also getting stuck on dotnet restore with .NET 8. This fixed it immediately, thanks for your comment!

@MattMckenzy Do you have a working example? Tried different configurations of Dockerfile and none of them seems to work.

kurt-mueller-osumc commented 8 months ago

@lbanchero and @sairohith-vanna, I'm on an apple macbook and and I have to add the following environment variable in my Dockerfile when I'm running rosetta emulation:

ENV DOTNET_EnableWriteXorExecute=0

This works for me but makes the container a bit less responsive.

See here for the full Dockerfile definition: https://github.com/kurt-mueller-osumc/dotnet-amd64/blob/main/Dockerfile#L4C1-L4C35

gregoryb commented 6 months ago

None of the suggested fixes work here. With the environment variables, the build crashes.

Any sample with WORKDIR. ?

richlander commented 6 months ago

Any sample with WORKDIR. ?

Can you elaborate on the question?

gregoryb commented 6 months ago

In a previous comment, it was mentioned that adding the WORKDIR instruction solved the problem. It doesn't solve the problem in my case. Maybe I missed something.

dotnet 8

richlander commented 6 months ago

Yes. That's this issue: https://github.com/dotnet/sdk/issues/38050