-
Notifications
You must be signed in to change notification settings - Fork 507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add debugging support for .NET Core in Docker containers #500
Add debugging support for .NET Core in Docker containers #500
Conversation
Merge from Microsoft/vscode-docker:master
Merge from Microsoft/vscode-docker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding some initial comments, but still in the process of reviewing.
Also I got this error when I F5'ed:
Building Docker image...
> Sending build context to Docker daemon 2.504MB
>
>
> Step 1/16 : FROM microsoft/aspnetcore:2.0 AS base
> 2.0: Pulling from microsoft/aspnetcore
> 55cbf04beb70: Pulling fs layer
> 2ad9fb8b9d3d: Pulling fs layer
> 7debd121b442: Pulling fs layer
> 76fbad01d0bd: Pulling fs layer
> 1cba46fa0c00: Pulling fs layer
> 76fbad01d0bd: Waiting
> 1cba46fa0c00: Waiting
> 7debd121b442: Download complete
> 76fbad01d0bd: Verifying Checksum
> 76fbad01d0bd: Download complete
> 55cbf04beb70: Verifying Checksum
> 55cbf04beb70: Download complete
> 1cba46fa0c00: Verifying Checksum
> 1cba46fa0c00: Download complete
> 2ad9fb8b9d3d: Verifying Checksum
> 2ad9fb8b9d3d: Download complete
> 55cbf04beb70: Pull complete
> 2ad9fb8b9d3d: Pull complete
> 7debd121b442: Pull complete
> 76fbad01d0bd: Pull complete
> 1cba46fa0c00: Pull complete
> Digest: sha256:8bd7808981568a92b7f1d0aa4bab07ef811e6417898847d9caf698a4a788ab11
> Status: Downloaded newer image for microsoft/aspnetcore:2.0
> ---> db030c19e94b
> Step 2/16 : WORKDIR /app
> ---> 78f936151ff7
> Removing intermediate container 62a22a04608f
> Step 3/16 : EXPOSE 80
> ---> Running in 721a55e2bb1e
> ---> cab04bc7c223
> Removing intermediate container 721a55e2bb1e
> Successfully built cab04bc7c223
> Successfully tagged hellodotnetcore.csproj:dev
Docker image cab04bc7c223 built.
Acquiring the latest .NET Core debugger...
Debugger acquired.
Starting container...
Unable to start container: Error: Command failed: docker run -dt -P --name hellodotnetcore.csproj-dev -v "/Users/ericjizba/TestRepos/hellodotnetcore:/app:rw" -v "/Users/ericjizba/.vsdbg/debian.8-x64/vs2017u5:/remote_debugger:ro" -v "/Users/ericjizba/.nuget/packages:/root/.nuget/packages:ro" -v "/usr/local/share/dotnet/sdk/NuGetFallbackFolder:/root/.nuget/fallbackpackages:ro" --entrypoint tail cab04bc7c223 -f /dev/null
docker: Error response from daemon: Mounts denied:
The path /usr/local/share/dotnet/sdk/NuGetFallbackFolder
is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> File Sharing.
See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.
.
Does that mean anything to you? I admittedly haven't investigated much and plan to look into it further.
dockerExtension.ts
Outdated
ctx.subscriptions.push( | ||
vscode.debug.onDidChangeActiveDebugSession( | ||
session => { | ||
if (session === undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get if (session === undefined)
. How do you know the session was a docker debug session? Doesn't this event fire for any debug session?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intent is to shutdown any containers used for Docker debugging still running when debugging ends in VS Code, whether from the ending session or a previous one. I'm not sure it matters which kind of session was ending, in that if there are no containers running it's a no-op and if there are, then we'd still want them shutdown.
(As far as I know, VS Code only supports one debugging session at a time.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just concerned because this code will be run for every user that has the docker extension installed - even if they never touch the 'docker-netcoreapp' experience (well - every user once we get rid of the feature flag). No matter how perfect the code is today (which could change in the future) I would prefer to have some checking here to prevent the docker extension from affecting users that are debugging entirely different things.
Can you use onDidTerminateDebugSession
and check session.type === 'docker-netcoreapp'
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran into issues with onDidTerminateDebugSession
when the VS Live Share extension was installed, as it may "wrap" other debug adaptors, even when not actively used. In that case, the returned type
is the Live Share adaptor. It exposes the underlying adaptor type via a custom request, but when a session is terminated you cannot make custom requests.
Instead, I add a "session manager" that's informed by my debug adaptor when debugging is about to start, at which time it starts listening to the termination event. Then, on termination, it performs the necessary cleanup and stops listening for future events. This should limit it the cleanup to running only when the user has attempted to debug within a Docker container, but no more than once per attempt.
debugging/netcoreapp/fsProvider.ts
Outdated
} | ||
|
||
export class LocalFileSystemProvider implements FileSystemProvider { | ||
public async dirExists(path: string): Promise<boolean> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a look at the 'fs-extra' npm module (already a dependency of this extension). It has promisified versions of all the 'fs' methods, plus some extra helper methods. Hopefully it's enough that you can get rid of LocalFileSystemProvider
completely, but it should at least make this a lot smaller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, hadn't realized that was already in use. Updated to use that instead. (The use of the provider structure itself is an intentional abstraction of the file system for (future) testing purposes.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the desire to plan ahead, but I'm also not a fan of over-complicating code before it's actually needed. How soon do you plan to write the tests? Are you sure the tests need an abstraction and can't just run against the real thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Abstracting/mocking the file system tends to be handy, in that it can simplify/eliminate test initialization/cleanup code as well as avoids collisions if/when tests run in parallel. I've added some sample tests; I'd love to add more as time allows.
debugging/netcoreapp/appStorage.ts
Outdated
import * as path from 'path'; | ||
import { FileSystemProvider } from "./fsProvider"; | ||
|
||
export interface MementoAsync { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The extensionContext already has a memento - globalState or workspaceState depending on your needs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppStorage
represents a state at the "application" or "project" level, which may often be sub-workspace-state. (You might have several applications within the workspace folder, say, if using VS Code to open a solution created by VS comprised of several individual ASP.NET projects.) It's intended to be used for things that are specific to the application (e.g. cache settings used to build/run its Docker images/containers) and not dependent on which folder was opened in VS Code (e.g. the solution level or project level folder) to edit that project. This parallels how VS stores such data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay I'll have to try out the scenario you described. I just want to make sure we're following VS Code conventions here, which may be different than VS. In general, VS Code has a much bigger reliance on the fact that the project is at the root of the workspace. They also have a concept of 'multi-root' workspaces, which might be how they handle the multi-project scenario you're describing (which is handled appropriately by workspaceState)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good to have a meeting to discuss how we expect users to manage these types of projects/solutions in vscode. Do we have actual customer usage data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I setup a time for us to meet and go through Stephen's questions.
I'll have to look into that too. Does that path exist on your machine? What folders are shared in your Docker preferences? (Mine does not explicitly state that |
@EricJizbaMSFT Did you happen to recently install OS X Mojave (10.14)? I'm now seeing that same Docker mount error after doing so. I had to manually add |
It looks like we ran into this issue with the VS for Mac Docker Tools and submitted a request to allow programmatic additions to the shared folder list. So strange that I hadn't run into this issue until now on my machine. I'll add instructions to the user to add the shared folder in the |
I've added a "prerequisite check" that the shared folder exists in the user's Docker preferences. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've addressed my biggest blockers so I'll go ahead and approve. (Only thing that's debatably a blocker for me is telemetry - definitely need that before releasing)
I do want to say I'm still not a huge fan of the Provider pattern for the following reasons:
- I think it makes the code unnecessarily complicated
- I think tests are more effective if they're running against the 'real thing'
- I think you might be using patterns that were helpful testing against VS but are less necessary when testing VS Code (which is a lot easier from my experience)
All that being said - I think it's a philosophical discussion that doesn't have a "correct" answer and thus isn't worth blocking a PR.
Thanks for your contribution!
…/philliphoff/vscode-docker into philliphoff-netcoreapp-debugging
…/philliphoff/vscode-docker into philliphoff-netcoreapp-debugging
Merge from vscode-docker master
Requested access to the OneNote in order to add test cases.
Ran through the basic scenario on Ubuntu (and added prerequisite check for user inclusion in |
Ok, so all comments should now be addressed one way or another. @StephenWeatherford Let me know if there's anything else I can do. |
return this.resolveDockerDebugConfiguration(folder, debugConfiguration); | ||
return callWithTelemetryAndErrorHandling( | ||
'debugCoreClr', | ||
async () => await this.resolveDockerDebugConfiguration(folder, debugConfiguration)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: debugCoreClr doesn't seem to say what it's really doing. How about "resolveDebugConfiguration"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose debugCoreClr
as that was effectively what was being done (i.e. an attempt to initiate debugging of .NET Core in Docker) even though resolveDebugConfiguration
is what VS Code happens to name the interface function (and PMs looking at the telemetry data typically care more about the intent than the implementation specifics). I'm amenable to other IDs or schemes; are there any conventions/restrictions in the naming (as the codebase uses a couple different styles)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's what it's effectively doing, it's fine, thanks.
Other than the suggested rename of telemetry, ship it! Thanks! |
Many thanks to @EricJizbaMSFT and @StephenWeatherford for their very thorough review! |
Adds support for debugging .NET Core applications within Docker containers, in a manner similar to that performed by Visual Studio's Docker-related tooling.
The basic feature set is:
The feature is disabled by default, using the new
docker.debugging.enabled
setting.