dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.5k stars 10.04k forks source link

Dotnet watch throws exception in Docker Linux container #38719

Open JohanPetersson opened 2 years ago

JohanPetersson commented 2 years ago

Describe the Bug

When using dotnet watch the file polling throws following exception:

watch : Polling file watcher is enabled
watch : Started
Unhandled exception. System.ArgumentException: An item with the same key has already been added. Key: /src/Startup.cs
   at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.<CheckForChangedFiles>b__23_0(FileSystemInfo f)
   at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
   at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.CheckForChangedFiles()
   at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.PollingLoop()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Steps to Reproduce

dotnet new web -f net5.0

Add Directory.Build.props to move bin and obj. The bug is however reproducible without this.

Make sure bin and obj are empty.

(on Windows)

docker run --rm -it -p 5000:80 -v ${pwd}:/src -w /src -e ASPNETCORE_URLS=http://+:80 -e ASPNETCORE_ENVIRONMENT=Development mcr.microsoft.com/dotnet/sdk:5.0 dotnet watch run --no-launch-profile

Other Information

This only happens when the project hasn't been built yet. If I start the container with just dotnet run once, shut down the container, and then change back to dotnet watch run as entrypoint, it works.

This is reproducible with .NET 6 too.

Output of docker version

20.10.10, build b485636

Output of docker info

Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Build with BuildKit (Docker Inc., v0.6.3)
  compose: Docker Compose (Docker Inc., v2.1.1)
  scan: Docker Scan (Docker Inc., 0.9.0)

Server:
 Containers: 3
  Running: 0
  Paused: 0
  Stopped: 3
 Images: 15
 Server Version: 20.10.10
 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: 5b46e404f6b9f661a205e28d59c982d3634148f8
 runc version: v1.0.2-0-g52b36a2
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 5.10.60.1-microsoft-standard-WSL2
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 12.42GiB
 Name: docker-desktop
 ID: IJEP:3W6Y:PWQF:KZOW:UBLU:PCJG:WOQ4:P2NB:B2ZP:TPMR:4PTD:BERP
 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
mthalman commented 2 years ago

Transferred to aspnetcore which owns dotnet-watch.

JohanPetersson commented 2 years ago

Any updates on this issue?

ghost commented 2 years ago

Thanks for contacting us. We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

Jawz84 commented 2 years ago

I have issues with this as well. When using a development container, I can't use dotnet watch reliably. Related: https://github.com/docker/for-win/issues/8749

DianaLaa commented 2 years ago

Same problem here. Intermittently, I get the "An item with the same key has already been added" error. This would not be so bad if only I knew what it requires of me to fix it.

ghost commented 2 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

mkArtakMSFT commented 2 years ago

@tmat could you please look into this? Thanks!

tmat commented 1 year ago

I can't reproduce it but I see a couple potential issues with the current implementation. Fixing in https://github.com/dotnet/sdk/pull/35712

Volkmire commented 1 year ago

@tmat I have similar issue

Unhandled exception. System.ArgumentException: An item with the same key has already been added. Key: /src/solution/sharedLibrary/obj/rider.project.restore.info
at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.<CheckForChangedFiles>b__23_0(FileSystemInfo f)
at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.ForeachEntityInDirectory(DirectoryInfo dirInfo, Action`1 fileAction)
at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.CheckForChangedFiles()
at Microsoft.DotNet.Watcher.Internal.PollingFileWatcher.PollingLoop()

I'm using a docker compose where service is defined something like this:

settings-api:
    image: mcr.microsoft.com/dotnet/sdk:6.0
    working_dir: /src/path/to/project
    entrypoint:
      - "/bin/sh"
      - "-c"
      - "dotnet watch run --packages /src/.packages/ --urls http://+:80"
    ports:
      - "10101:80"
    environment: []
    volumes:
      - ${PWD}:/src
    depends_on:
      rabbitmq:
        condition: service_healthy

Note that I mount my whole repository as a volume and exception seems to be triggered by shared dependency. I've also tried to change entrypoint script to dotnet build .... && dotnet watch run ..., thinking to walk around of what @JohanPetersson mentioned about having empty /bin /obj directories. This did not run either.

The only setup that did run was dotnet build && dotnet watch run --no-build --no-restore ..., but it is obviously pointless, since watch does not rebuild sources on change. But it also probably means that the issue is somehow related to the build phase in dotnet watch command.

Davane commented 11 months ago

@Volkmire I had a similar issue and I found this article https://medium.com/@saadjaved120/hot-reload-dotnet-application-in-docker-using-dotnet-watch-c41662c73104. I hope this can help you and others.

Based on the article, I think you might need to update your volumes and add these (Just replace the ProjectName with yours):

...
volumes:
      - ./:/app
      # After adding the below lines the problem went away for me
      - /app/obj/ # <- directory won't be mounted
      - /app/bin/ # <- directory won't be mounted
      - /app/ProjectName.API/obj/ # <- directory won't be mounted
      - /app/ProjectName.API/bin/ # <- directory won't be mounted