This is a sample that demonstrates how to use vscode to build and debug dotnet core 2.0 console application in docker container.
What we're going to achieve is to be able to build our dotnet core application or library inside a Docker container, so we don't need to install an appropriate sdk on our host machine. After we successfully build an image with the app, we need to spin up a new container and attach debugger to our app inside this container.
- First of all we need to create a docker file that will describe how we are going to build a Docker image with our application.
FROM microsoft/dotnet:2-sdk
ENV NUGET_XMLDOC_MODE skip
WORKDIR /vsdbg
# Installing vsdbg debbuger into our container
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
unzip \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /vsdbg
# Copying source files into container and publish it
RUN mkdir /app
WORKDIR /app
COPY App.csproj /app
RUN dotnet restore
COPY . /app
RUN dotnet publish -c Debug -o out
# Kick off a container just to wait debugger to attach and run the app
ENTRYPOINT ["/bin/bash", "-c", "sleep infinity"]
-
Then we create a script file dockerTask.sh that will contain utility task buildForDebug. This task is responsible for:
- stopping and removing old container(s)
- building a new image
- running a new container
-
Add task configuration to tasks.json
{
"taskName": "buildForDebug",
"suppressTaskName": true,
"args": [
"-c",
"./scripts/dockerTask.sh buildForDebug"
],
"isBuildCommand": false,
"showOutput": "always"
}
- And the last step is to create the launch configuration in launch.json, that will use task created on the previous step as a preLaunchTask.
{
"name": ".NET Core Docker Launch (console)",
"type": "coreclr",
"request": "launch", # we are going to run a new instance of our application
"preLaunchTask": "buildForDebug", # name of the task that will build and run a container
"program": "/app/out/App.dll", # path to program to run inside a container
"cwd": "/app/out", # working directory inside a container
"sourceFileMap": {
"/app": "${workspaceRoot}/src" # mapping of source code inside a container to the source code on a host machine
},
"pipeTransport": {
"pipeProgram": "docker", # use Docker as a pipe program
"pipeCwd": "${workspaceRoot}",
"pipeArgs": [
"exec -i docker.dotnet.debug_1" # attach to container and execute command of running app with attached debbuger
],
"quoteArgs": false,
"debuggerPath": "/vsdbg/vsdbg" # path to installed debugger inside a container
}
}
And that's basically it. For more details and the full example see the code in the repo.
Tested environment:
- OS: macOS Sierra 10.12.6
- Docker: 17.07.0-ce-rc1-mac21 (18848)
- dotnet: 2.0.0-preview2-006497
- vscode: Version 1.16.0-insider (1.16.0-insider)
- ms-vscode.csharp: 1.12.0
Known issues (or features?!):
- We run container in 'runContainer' task, but we start app in this container only when we decided to debug it. So, in order to do that, we have to attach to the running container and provide the name of container in launch.json. By doing that we have to keep in sync the name of the container in two files. That's not that elegant solution, and definitely is a violation of SRP.
- The other problem that arise from the #1 is that we leave container running even when we finished debugging.
For more details read these articles: