Azure / service-fabric-mesh-preview

Service Fabric Mesh is the Service Fabric's serverless offering to enable developers to deploy containerized applications without managing infrastructure. Service Fabric Mesh , aka project “SeaBreeze” is currently available in private preview. This repository will be used for tracking bugs/feature requests as GitHub issues and for maintaining the latest documentation.
MIT License
82 stars 13 forks source link

Visual Studio debugging experience seems "hostile" to the dockerfile experience #142

Open drub0y opened 6 years ago

drub0y commented 6 years ago

I'm finding the F5 experience for debugging SF Mesh applications to be rather "hostile" to the typical dockerfile experience.

When I define my dockerfile, that's what I expect my image to end up being. However, the debugging experience seems to be taking the approach of only using the first stage of my multi-stage build and then everything after that is lost. I understand what it's doing with respect to getting the debugging infrastructure on there, but I feel like it just completely stomps on everything a docker developer is used to with respect to the dockerfile experience.

Being able to control the --target param would be a good first step so that if there are multiple stages before the project build we can at least get past all of those. Maybe this exists, but I'm not finding it? However, there are also scenarios where the final image being built isn't just the output of the project itself and in fact may not even be running the outputs of the project itself, but rather some other command that might be discovering the outputs of the project being built at runtime. I have a specific example if more details are necessary, but I'll spare those details for now.

Is this something that is being looked into being improved?

sgreenmsft commented 6 years ago

This is a compromise that we made in order to make the development experience fast. It turns out that compiling your application in a container after every code change significantly slows down the development inner-loop.

However, if you'd prefer that VS build the entire dockerfile instead, you can switch to the Release configuration or add the property <SFAppDevelopmentMode>Regular</SFAppDevelopmentMode> to your csproj file.

drub0y commented 6 years ago

@sgreenmsft So, first, thank you for letting me know about that SFAppDevelopmentMode property as I'd still like to build in Debug configuration for the other obvious reasons. (Tangentially I would suggest starting a document on all the props that the SF MSBuild targets support because that's a space that often goes forgotten on the documentation front. Maybe I'll even open a separate issue about that after this one so it doesn't get lost!)

I do understand the need to trade off here. Like I said, something that might even help for the 80% case would be the ability to control the --target parameter rather than the tooling just assuming the first layer. That would take care of what I suspect might be the 80% of cases where devs really only care about phases leading up to the project itself. Another MSBuild prop could fit the bill IMHO... might I propose SFAppDockerMultiStageBuildTarget? When present, the tooling can target that versus the default behavior of just taking the first layer. Obviously this should eventually surface up through the VS tooling experience into the UI somewhere as well; perhaps the property pane for SF App project?

Now, for the other, more complicated "20%" scenario where the dev really wants to control the final image themselves, it's really about them making sure the debugger infrastructure gets put into place, right? I feel like, in this case, punting the responsibility of getting MSVMON on the image and started is fair for now, but, in the case that I've set the SFAppDevelopmentMode=Regular will the tooling still attempt to attach to the container for debugging? I can test that out of course.

sgreenmsft commented 6 years ago

Regarding debugging -- If you run docker inspect on the running container you'll see that the tools volume mount the msvsmon folder into the container (at c:\remote_debugger) and also override the container entrypoint to start msvsmon instead of the original entrypoint (by default "dotnet web1.dll"). Once the container is up and running, Visual Studio connects and tells msvsmon to launch your compiled assembly. All of this always happens when you F5 from Visual Studio -- regardless of the selected Configuration or the SFAppDevelopmentMode value -- so debugging will just work and you'll never need to worry about getting msvsmon in the container.

sgreenmsft commented 6 years ago

@BigMorty - See above regarding request for ability to select a specific target when building a project's dockerfile.

drub0y commented 6 years ago

Sure, I understand how it works it's magic. 😊 I'd actually already done a bunch of reverse engineering (using inspect) to figure out how the tooling is accomplishing this before even writing up this issue and it's a great out-of-the-box experience, but, again, it puts limitations on more advanced scenarios and I'm asking if there's some other things we can do to support those scenarios where more control is given over the docker image and we're still enabling this awesome ability to debug.

So, first, is being able to control the --target explicitly via a build property a fair request? It seems like a no brainer. Is that something we can get added?

Second, do you see a way to support the ability to debug in the case where I'm asking you not to muck with my image at all because I want to be in full control from end-to-end? What I was proposing is that, in that scenario, the developer is completely responsible for getting the MSVSMON debugging infrastructure on there, but, once it's there, SF tooling can "notice" that it's there and connect up to it. If it can't it can simply give a warning that it was unable to attach, give a link to the docs on enabling the scenario and carry on debugging whatever other projects it was able to attach to. For the record, right now this is what happens:

image

BigMorty commented 6 years ago

@drub0y - Thanks for using the new VS tools targeting SF Mesh, it is great you are taking the time and providing feedback to make the new tools awesome! I have logged your request for control the --target that is used rather. I have not logged an item as of yet for your second question regarding VS not touching your image at all when you want to debug. Can you tell me why it is important that we don't do the minimal set of work @sgreenmsft describes above?

drub0y commented 6 years ago

@BigMorty Thanks and no problem, I really want to ensure we offer the "best darn container debugging experience out there"® for our customers. 😆

Ok, so, first I can take the cheap way out and just use the scenario where a development team has already made an investment in writing their dockerfiles a specific way and they just want to those images to work with minimal investment to also get MSVSMON on them to partake in the debugging experience. There are multi-stage builds out there already where building/publishing the code is not the last stage.

Now, let me tell you about my specific scenario. I was putting together a PoC where I wanted to self-host the Azure Functions Runtime on an SF Mesh image. While it also happens to use a multi-stage build process, the more important part is that the CMD that I need to run is not dotnet MyProjectAssembly.dll. Instead I need to start up the Azure Function Host with dotnet C:\\runtime\\Microsoft.Azure.WebJobs.Script.WebHost.dll. On top of that there are a few more things I do in the final stage of my build (post building/publishing my project) with respect to environment variables, though, upon reflection, I could technically do those earlier with the knowledge that the SF tooling is going to mount my project's assemblies at c:\app... though, side note, strongly coupling to that is never a "good thing" and I'd prefer SF add an environment variable that I can just refer to to find out where the project was mounted.

So with a fresh brain early Monday and writing this up, there seems to be another option here that might be easier. First, we need that control over --target for sure, but if that's there I think if the SF tooling gave the ability to control exactly what command (and params) it should send through MSVSMON instead of assuming just dotnet MyProjectAssembly.dll that would also seem to solve this project. Something like this under the Debug properties of the project for example (which is just UI over an MSBuild property of course):

Debug Command Mock Up

BigMorty commented 6 years ago

LOL, love the new mantra! "Build the best darn container debugging experience out there"® 😂

Thanks for describing your Azure function runtime scenario, makes total sense. I have logged two additional work items to track this request and the request for environment variable for volume mount location.

Thanks again! Mike "BigMorty" Morton

sgreenmsft commented 6 years ago

@drub0y - We've made some changes to try to enable your scenario. The next version of the VS tools for Mesh will have:

sgreenmsft commented 6 years ago

@drub0y - We've also added a property DockerfileFastModeStage that can be used in the service project csproj file to specify the desired build stage for use during F5 (fast mode being a reference to the mode where we volume map the assemblies compiled on the host into the running container instead of building inside of the container).

BigMorty commented 6 years ago

@drub0y - Based on the four additions @sgreenmsft mentioned above, are you ready to close this issue?

drub0y commented 6 years ago

This sounds like some really good progress!!! I haven't had the bandwidth to go put this all together to see how it all comes together to enable the exact scenario I was going for. Reading through the new features it does seem like the boxes are checked to enable this, but I almost wonder if it's still a little too coupled to executing .NET right now...?

Looks like we've now got control over the entry point and arguments via properties now which is great for my exact scenario, but, if I'm reading this right, the "command" I was suggesting be exposed is still locked to dotnet only. What if I'm integrating with an application that requires I run a random batch file or executable and that's going to eventually load my assembly into it?

So maybe a property named SFDebugLaunchCommand that defaults to dotnet $(SFAppLaunchEntryPoint) $(SFAppLaunchArguments), but that I can completely override to be something like c:\mypath\myCustomExecutable.exe --somearg=123 if I really need to?

sgreenmsft commented 6 years ago

We're limited in what we can achieve with regard to debugging an arbitrary executable. In order to debug inside of a container we have to volume mount the appropriate debugger (onecoremsvsmon in the case of .NET Core on Windows, vsdbg in the case of .NET Core on Linux, msvsmon in the case of .NET Framework). Then, we have to launch the debugger using the correct settings for the project type (e.g. the mechanism for launching debugging of a .NET Framework ASP.NET project differs entirely from a .NET Core console app on Linux). Consequently we make the simplifying assumption that the type of code you intend to debug matches the project type -- i.e. for .NET Core projects we require launches use "dotnet".

Crewman123 commented 5 years ago

Can you also add a variable to modify the volume mount path, that defaults to the output directory?

In my case I have 2 projects that build in a bin folder and I would like to volume mount the "bin" directory for debugging (F5 or Ctrl+F5). Project2 contains libs and tools project1 needs at runtime.

In the above example if I debug "project1", the volume "bin/project1" is mapped to the "C:\app" directory. I would like to map the "bin" directory to "C:\app" directory for debugging.

smailliwnosaj commented 3 months ago

After doing a google search, this blog seems to be the only place on the interwebs where there is a reference to the SFAppLaunchEntryPoint feature. Is there any documentation on this feature? Is it still supported?

dazinator commented 3 months ago

I thought service fabric mesh was long dead @smailliwnosaj