Repro steps:
curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v vs2017u5 -l ~/vsdbgResult:
vsdbg doesn't start
This is something fairly high on our priority list, but it isn't something that we have started on yet.
Is _we_ here the OmniSharp team or MS? This the best place to track progress?
@janaka: The work is being done by Microsoft, but this is a good place to track it. The work is largely complete. But we are hitting into a memory corruption bug that has proven very difficult to track down. Once we get to the bottom of that we think we are ready for release.
@gregg-miskelly - any news on this? I could use this right now.
Yep, keen to get a feel for progress/plans.
I just hit this issue as well. There is an issue with vsdbg and als owith remoteProcessPickerScript. It assumes a more advanced ps then what is included in the alpine images for the dotnet and aspnet images. Although it looks like you could install procps via apk add procps that ps also does not seem to work.
Any update on this @gregg-miskelly?
Sorry for the long delay. I finally published a beta release that supports Alpine. It will not yet be usable in full Visual Studio for Docker scenarios, but you can use it in VS Code.
To try the beta, follow instruction from the wiki, but instead of obtaining vsdbg using https://aka.ms/getvsdbgsh instead use https://aka.ms/getvsdbgshbeta (or replace 'sh' with 'ps1' if you want the powershell version of the script).
Let us know if you run into any problem.
Thanks @gregg-miskelly.
I've got it up and running on microsoft/dotnet:2.1-sdk-alpine, but I needed to explicitly specify the process id, I seemed to run into 2 issues:
${command:pickRemoteProcess} seems to expect that sh will be present on the container, but it needs to actually rather use /bin/ash. Tweaking the resulting command, and running this manually allows the file to run on the container, but I'm not sure how I can specify it to use ash automatically:docker-compose exec -T <docker-compose-service> /bin/ash -s < /Users/.../.vscode/extensions/ms-vscode.csharp-1.17.0/scripts/remoteProcessPickerScriptps -axww -o pid=,comm=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,args=ps: unrecognized option: xI updated my launch.json as below, I used docker-compose exec rather than docker exec so I could just use my service name in my docker-compose file, regardless of what the resultant container name is.
{
"name": ".NET Core Docker Attach (customer service)",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker-compose",
"pipeArgs": ["exec", "-T", "customer"],
"debuggerPath": "/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/src": "${workspaceRoot}/src/services/customer"
}
}
...and my Dockerfile
FROM microsoft/dotnet:2.1-sdk-alpine AS dev
WORKDIR /src
RUN apk --no-cache add curl
RUN curl -sSL https://aka.ms/getvsdbgshbeta | ash /dev/stdin -v latest -l /vsdbg
ENTRYPOINT ["dotnet", "watch", "run"]
If you have any suggestions, or would like me to test anything, please let me know.
@gregg-miskelly Well I guess were getting cutting edge over here, we are at the point in our development where we want to docker-compose all our services, and attach to any one of them to debug a full environment locally. And so, we also need to do this, ill follow up if I find anything.
@andy-g Is there a particular reason you are trying to use the sdk Builder version instead of the runtime version on alpine, and why would you be using ash instead of sh? I'm just sitting down to get this working over the next two days, but I was curious as to your approach.
@ChristopherLClark: Cool. The script at https://aka.ms/getvsdbgsh should now be able to pull down a version with Alpine support. So you don't need the beta release any longer.
@ChristopherLClark I'm using the SDK version so that I can build from within the container, allowing anyone to clone the repo and run it regardless of whether they have the dotnet SDK installed on their machine.
I'm not sure if it was a previous version, or if I just defaulted to trying to test with bash rather than sh, but you're right, sh seems to be working fine now, it's just bash that isn't present on alpine.
I'm still having my 2nd issue though: The next issue is that the contents of that file doesn't run on alpine:.
I've update my Dockerfile to use the standard getvsdbgsh (not the beta one), but I'm still having issues with the ps command failing:
Executing: docker-compose exec -T customer sh -s < /Users/andy/.vscode/extensions/ms-vscode.csharp-1.17.1/scripts/remoteProcessPickerScript
Linux
stderr: ps: unrecognized option: x
BusyBox v1.28.4 (2018-12-06 15:13:21 UTC) multi-call binary.
Usage: ps [-o COL1,COL2=HEADER]
Show list of processes
-o COL1,COL2=HEADER Select columns for display
I have the latest version of the remoteProcessPickerScript: https://github.com/OmniSharp/omnisharp-vscode/blob/master/scripts/remoteProcessPickerScript.
From what I can see, this is the command that needs to work (replace customer with the docker-compose service name, and andy with your host machines username):
docker-compose exec -T customer sh -s < /Users/andy/.vscode/extensions/ms-vscode.csharp-1.17.1/scripts/remoteProcessPickerScript.
@gregg-miskelly or @ChristopherLClark please let me know if you have a better option or suggestion or get it working on your side.
I got it working, but I needed to install procps to handle the ps command arguments.
My Dockerfile now looks like this:
FROM microsoft/dotnet:2.2-sdk-alpine AS dev
WORKDIR /src/customer.api/
RUN apk --no-cache add curl procps
RUN curl -sSL https://aka.ms/getvsdbgsh | sh /dev/stdin -v latest -l /vsdbg
ENTRYPOINT ["dotnet", "watch", "run"]
With this in place, debugging is working perfectly, using my previous launch.json section:
{
"name": ".NET Core Docker Attach (customer)",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker-compose",
"pipeArgs": ["exec", "-T", "customer"],
"debuggerPath": "/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/src": "${workspaceRoot}/src/services/customer"
}
}
@ChristopherLClark this should work for you, you'll just need to create a separate section for each of your docker-compose services - this example above is for my customer service.
@gregg-miskelly thanks for all your work in getting this to this point.
I'm ok with this, as this docker container will be for dev, I'll copy the app binaries across to a production image without the additional alpine packages before pushing into production using a multistage dockerfile.
I'm not sure what is going on, I built the dll in debug and I can't step through in the debugger. I'm seeing this in the output when the debugger successfully attaches for our app.
Loaded '/path/app.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
So, is the only way to debug this app if we use dotnet watch run?
I'm on my mobile so can't test anything at the moment, but don't worry about the watch command, it just monitors the filesystem for changes (I'm mounting my local source into the docker container), so when a file is changed, it rebuilds the app & restarts it without needing to restart the container, streamlining the development process when using docker.
So, dotnet run should do the trick for you, but I'm not sure what's necessary to get it running with a precompiled DLL, possibly the pdb's need to be included too.
@andy-g I took the effort to do the same thing with watch and mounting my local source as well. It just doesn't hit the breakpoints at all, which process should I attach to?
Edit: another peice of the puzzle I didn't understand is the sourceFileMap, what should I set it to?
This is the current launch.json
```
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core SSH Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker",
"pipeArgs": [ "exec", "-i", "app_name_1" ],
"debuggerPath": "/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/home/ExampleAccount/ExampleProject": "${workspaceRoot}"
}
}
]
}
@gregg-miskelly @andy-g Looks like i got it working, my inability to debug was not understanding the sourceFileMap.
This is awesome, good job @gregg-miskelly !! . I know you said you got it out of beta already, but its passed my testing!
Excellent!
@gregg-miskelly it may be worth just adding some examples to the documentation for alpine based containers, and specifying what packages and commands are required, from what I can see, this is what's required:
RUN apk --no-cache add curl procps
RUN curl -sSL https://aka.ms/getvsdbgsh | sh /dev/stdin -v latest -l /vsdbg
Other than that, this feels like it's ready for prime time 🎉
I'm still stuck with this:
{
"name": ".NET Core SSH Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker",
"pipeArgs": [ "exec", "-i", "vigilant_tu" ],
"debuggerPath": "/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/app": "C:\\Users\\Andrés\\Documents\\Personal\\Projects\\docker.dotnet.debug\\src\\"
}
}
I already have checked vsdbg installation, also the application is deployed in /app folder and when debugging, vscode offers me the remote application process. But the breakpoint is not hitted :(
Any suggestions?
Thanks!
Pd: Thanks to @ChristopherLClark for the launch.json example
@andy-g I am happy to add more documentation, but where would you have looked? There are notes already about adding 'procps' in https://github.com/OmniSharp/omnisharp-vscode/wiki/Attaching-to-remote-processes#configuring-docker-attach-with-launchjson
@andresrsanchez I added a Troubleshoot Breakpoints page to the wiki. Please have a look.
Thanks @gregg-miskelly for the documentation, my case is this one "The breakpoint was successfully set (no warning), but didn’t hit", I have reviewed all of the three checks and everything seems to be perfect, the code is running and vscode offers me to pick dotnet process, but the debug console only print:
Starting: "docker" exec -i clever_bardeen /vsdbg/vsdbg --interpreter=vscode
My launch.json is like this:
{
"name": ".NET Core Docker Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker",
"pipeArgs": [
"exec -i clever_bardeen"
],
"debuggerPath": "/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/app": "${workspaceRoot}"
}
}
And my Dockerfile:
FROM microsoft/dotnet:2.2-sdk AS build-env
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Debug -o out
FROM microsoft/dotnet:2.2-aspnetcore-runtime-alpine
WORKDIR /app
RUN apk add --no-cache bash
RUN apk --no-cache add curl procps
RUN curl -sSL https://aka.ms/getvsdbgsh | sh /dev/stdin -v latest -l /vsdbg
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
I have spent the last 2 days on this, and still I don't get it :(
Thanks for all
@andresrsanchez WORKDIR /app and COPY --from=build-env /app/out . might not work the way you think it works
Have you tried execing into the container and seeing if the filesystem matches what you think it should and the sourcefilemap matches what it should be based on that filesystem structure?
Also your message and the fact that its a dll, makes me wonder if you built it in debug, and that you are using the runtime image, maybe you can't debug with the runtime? These last two points are stretching but I would start with the first suggestion I made to see the filestructure.
So I thought maybe it would help to show my FULL example. It looks like you are just trying to work on a single container, but ill show the docker-compose for the full experience.
First my local filestructure for development.
Source
| - app_name
| - other_app
| - angular_proj
In my angular_proj I have my docker-compose file. I felt as this was the best place to compose all services locally.
Here is my docker-compose
version: '3'
services:
app_name:
build:
context: ../app_name
dockerfile: dev.dockerfile
ports:
- 5011:8080
env_file:
- ../app_name/.env
volumes:
- ../app_name:/folderx
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
other_app:
build:
context: ../other_app
dockerfile: dev.dockerfile
ports:
- 5010:8080
env_file:
- ../other_app/.env
volumes:
- ../other_app:/folderx
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
notice a few things here. I'm mounting to folderx this will be more clear later based on the sourcemapfile property in the launch.json file.
Here is my dev.dockerfile
FROM microsoft/dotnet:2.1-sdk-alpine AS dev
ENV ASPNETCORE_URLS http://*:8080
EXPOSE 8080
RUN mkdir /folderx
COPY . ./folderx
WORKDIR /folderx
RUN dotnet restore
WORKDIR /
RUN apk --no-cache add curl procps && \
rm -rf /var/cache/apk/*
RUN curl -sSL https://aka.ms/getvsdbgsh | sh /dev/stdin -v latest -l /vsdbg
COPY devstrap.sh /devstrap.sh
RUN sed -i -e 's/\r$//' /devstrap.sh && chmod +x /devstrap.sh
ENTRYPOINT ["/devstrap.sh"]
And the devstrap.sh. You may not want to do this exactly, but were able to keep the same dll_name and reuse this file since we make it an environment variable. This also allows keeping the project folder structure. I'll post that in a second.
#!bin/sh
if [[ -z "${DLL_NAME}" ]]; then
echo "Must pass the project name to the container. .dll will be appended to name of project"
exit 1
else
if [[ -z "${DOMAIN_PASSWORD}" || -z ${DOMAIN_PID} ]]; then
echo "DOMAIN_PID and DOMAIN_PASSWORD must be injected into the container."
exit 1
fi
fi
cd folderx/${DLL_NAME}
dotnet watch run -c debug -r alpine-x64 --no-launch-profile
exec "$@"
And the project structure. See how the dll name and the folder which contains the .csproj is the same.
app_name
| - APPName
| - APPName.csproj
| - .dockerignore
| - .env
| - .gitignore
| - dev.dockerfile
| - devstrap.sh
and finally the launch.json
"configurations": [
{
"name": ".NET Core SSH Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickRemoteProcess}",
"pipeTransport": {
"pipeProgram": "docker",
"pipeArgs": [ "exec", "-i", "app_name_1" ],
"debuggerPath": "/vsdbg/vsdbg",
"pipeCwd": "${workspaceRoot}",
"quoteArgs": false
},
"sourceFileMap": {
"/folderx": "${workspaceFolder}"
}
}
This allows me to truly make a change locally, and it reflect within the container, the project rebuilds and you are able to do all debugging. You can also truly do end to end debugging I can attach a debug session in any project at any time. While your docker-compose is running, you can also see all end to end logs.
@andy-g I am happy to add more documentation, but where would you have looked? There are notes already about adding 'procps' in https://github.com/OmniSharp/omnisharp-vscode/wiki/Attaching-to-remote-processes#configuring-docker-attach-with-launchjson
@gregg-miskelly I actually did read that wiki page while I was setting everything up, but I think I ignored that part as the alpine container did actually have ps - it was just a version that didn't support the arguments used. I probably should have gone back to it and noticed it again after I was fighting with ps failures though 🤦♂️ .
I realise I should have worked that out, but maybe something like this added in that paragraph would make things clearer:
This requires your container to have ps. If it doesn't, you can install it (on most distros using the 'procps' package), or you change this to a process id if you know what you want to debug. Alpine based containers do have ps, but the default version doesn't handle the required arguments, so you will need to install procps, with something like:
RUN apk --no-cache add procps.
@andy-g Sounds good. Done.
@ChristopherLClark truly thank you for all of your effort, finally the problem was my computer, we executed the same on different computer and it worked!!!
In the next days i'm going to release a simplified example.
Thanks!!!
Closing this issue as Alpine support was added a long time ago.
Most helpful comment
@janaka: The work is being done by Microsoft, but this is a good place to track it. The work is largely complete. But we are hitting into a memory corruption bug that has proven very difficult to track down. Once we get to the bottom of that we think we are ready for release.