How to use dotnet tools inside a container? - docker

I'm experimenting Visual Studio Code Remote.
I want to use SonarScanner for code quality analysis. I've followed the guides and installed the tool on host but when I try to use it from the container, I get:
# dotnet sonarscanner -h
No executable found matching command "dotnet-sonarscanner"
On host:
$ dotnet sonarscanner -h
SonarScanner for MSBuild 4.7.1
Using the .NET Core version of the Scanner for MSBuild
Usage:
SonarScanner.MSBuild [begin|end] /key:project_key [/name:project_name] [/version:project_version] [/d:sonar.key=value] [/s:settings_file]
When executing the begin phase, at least the project key must be defined.
Other properties can dynamically be defined with '/d:'. For example, '/d:sonar.verbose=true'.
A settings file can be used to define properties. If no settings file path is given, the file SonarQube.Analysis.xml in the installation directory will be used.
Only the token should be passed during the end phase, if it was used during the begin phase.

this post can help you!
Install dotnet core tool Dockerfile
we can run a dotnet tool global command inside a container setting the following line:
ENV PATH="${PATH}:/root/.dotnet/tools"
Dockerfile
FROM microsoft/dotnet:2.1-sdk as build-env
WORKDIR /src
COPY question-metrics-api/question-metrics-api.csproj question-metrics-api/
COPY question-metrics-data/question-metrics-data.csproj question-metrics-data/
COPY question-metrics-domain/question-metrics-domain.csproj question-metrics-domain/
COPY tests/question-metrics-domain-tests/question-metrics-domain-tests.csproj tests/question-metrics-domain-tests/
RUN dotnet restore tests/question-metrics-domain-tests
RUN dotnet restore question-metrics-api/question-metrics-api.csproj
COPY . .
#Run tests
RUN dotnet test tests/question-metrics-domain-tests/question-metrics-domain-tests.csproj
#Begin Sonar
RUN dotnet tool install -g dotnet-sonarscanner
ENV PATH="${PATH}:/root/.dotnet/tools"
RUN dotnet sonarscanner begin /k:"question-metrics-api" /d:sonar.host.url="http://sonarqube:9000" /d:sonar.login="7ed84e09a17a31e783fa8522d876e27fe4624977"
RUN dotnet build
RUN dotnet sonarscanner end /d:sonar.login="7ed84e09a17a31e783fa8522d876e27fe4624977"

Got It! I've found an article explaining it.
It was just including this instructions on Dockerfile.
ENV SONNARSCANNER_VERSION 2.3.38
RUN dotnet tool install --global dotnet-sonarscanner --version $SONNARSCANNER_VERSION
ENV PATH="/root/.dotnet/tools:${PATH}"
ENTRYPOINT ["dotnet-sonarscanner"]

Related

Can't produce coverage in Docker container

I'm having trouble getting coverlet to run in my docker container. My problems seems similar to this issue, although the problem persists, and there are some differences.
Setup
.NET 6 tests project.
References have Microsoft.NET.Test.Sdk v17.2.0 (latest), and coverlet.collector v3.1.2 (latest)
I'm running the tests in a Dockerfile, like so:
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
COPY ["src/MyAPI/", "src/MyAPI/"]
COPY ["tests/MyAPI.Handlers.Tests/", "tests/MyAPI.Handlers.Tests/"]
WORKDIR "/tests/MyAPI.Handlers.Tests"
RUN dotnet restore "MyAPI.Handlers.Tests.csproj" --configfile NuGet.config
FROM build AS publish
WORKDIR /tests/MyAPI.Handlers.Tests
RUN dotnet publish "MyAPI.Handlers.Tests.csproj" -c Release -o /tests/publish --no-restore
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS final
WORKDIR /tests
COPY --from=publish /tests/publish .
ENTRYPOINT ["dotnet", "test", "MyAPI.Handlers.Tests.dll", "--collect:\"XPlat Code Coverage\""]
So i am doing a dotnet publish, and running the tests from there. That should mean that everything is there, that needs to run the tests / coverage.
When i run, i get this error:
Data collection : Unable to find a datacollector with friendly name '"XPlat Code Coverage"'.
What i've confirmed:
Command works outside docker fine (e.g if i do a dotnet publish, then dotnet test with coverage)
I've listed the files in the directory in the container, and confirmed the coverlet DLL's are there
Any suggestions would be great! Thanks in advance :)
I tried by removing \" from argument and it worked.
ENTRYPOINT ["dotnet", "test", "MyAPI.Handlers.Tests.dll", "--collect:XPlat Code Coverage"]

How to change host platform type to linux/arm from linux/amd on Visual Studio 2019 configuration?

I want to deploy a Blazor app to QNAP(TS-230).
So, I build a Docker image by Visual Studio 2019.
QNAP is one of NAS, and is ARM system.
So, I have changed a dockerfile to following config.
#FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim-arm64v8 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["BlazorApp4/BlazorApp4.csproj", "BlazorApp4/"]
RUN dotnet restore "BlazorApp4/BlazorApp4.csproj"
COPY . .
WORKDIR "/src/BlazorApp4"
RUN dotnet build "BlazorApp4.csproj" -c Release -o /app/build
Then build, I encountered following an error message.
error CTC1015: WARNING: The requested image's platform (linux/arm64) does not match the detected host platform (linux/amd64) and no specific platform was requested
How to change target the host platform?
A reproduce step is here:
Execute VS2019
Select Blazor Server App
Select .NET 3.1
Check Enable Docker
Select Docker host to "Linux"
Select Public, Docker Container Repository.
Select "Docker hub"
Enter my username, and password
Change target runtime to "linux-arm"
build
Please teach me, How to change host platform type to linux/arm.
Best regard.
I have resolved by myself.
I used "buildx" that is provided by Docker.
This tool can build for specified platform by setting --platform parameter.
"buildx" is explained by following page.
https://docs.docker.com/buildx/working-with-buildx/
And then, I did two change to Dockerfile.
First an using runtime/sdk image change to following.
FROM mcr.microsoft.com/dotnet/aspnet:3.1-buster-slim-arm64v8 AS base
FROM mcr.microsoft.com/dotnet/sdk:3.1-buster-arm64v8 AS build
Second is that I added -r linux-arm64 parameter to dotnet restore, dotnet build, and dotnet publish.
RUN dotnet restore "*.csproj" -r linux-arm64
RUN dotnet build "*.csproj" -r linux-arm64 -c Release -o /app/build
RUN dotnet publish "*.csproj" -r linux-arm64 -c Release -o /app/publish
Then at last, I executed following command, I succeed !!!!!!!
docker buildx build -f <Dockerfile path> --platform linux/arm64 -t <dockerhud path> --push .
Attention, If you don't specify "-f" parameter, Relative paths writtern on Dockerfie is invalid.

Is there a way to export files during a docker build?

I do a multistage build right now. The first stage compiles with credentials for my internal repos and I just keep the binaries as per this example: https://github.com/dotnet/dotnet-docker/blob/master/documentation/scenarios/nuget-credentials.md
But I want to run in CI server and need to provider the CI server with test and coverage reports. It would be most elegant to do this in the build layer but how do I get files out of a docker image during build?
For example:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app
# Copy csproj and restore as distinct layers
COPY *.csproj .
COPY ./nuget.config .
RUN dotnet restore
# Copy and publish app and libraries
COPY . .
############ Get this files out #####################
# Generate test report. copy this to external directory
RUN dotnet test --logger trx
# Generate coverage report. copy this to external directory
RUN dotCover.sh dotnet --output=myRep.html --reportType=HTML -- test
#######################################################
RUN dotnet publish -c Release -o out --no-restore
FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS runtime
WORKDIR /app/
COPY --from=build /app/out ./
ENTRYPOINT ["dotnet", "dotnetapp.dll"]
So I want to be able to run docker build and have it dump a test and coverage report to the current directory where docker build command was run. Is this possible? It would make this seamless for CI because all server must do is run docker build and it get reports
docker build supports an --output flag. I think it requires BuildKit (DOCKER_BUILDKIT=1). Here's one example usage.
https://docs.docker.com/engine/reference/commandline/build/ - then find --output on the page
https://docs.docker.com/engine/reference/commandline/build/#output

How to create a docker image from dotnet core 2.2 and powershell core?

I'm trying to "dockerize" a dotnet standard library, for now I'm using a simple docker file, to build and pack it using just dotnet cli commands.
# Build stage
FROM microsoft/dotnet:2.2-sdk as build
ARG Version
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet build -p:Version=$Version -c Release --no-restore
RUN dotnet pack -p:Version=$Version -c Release --include-symbols --no-restore --no-build -o /src/.artifacts
I want to be able to run a powershell script ci.ps1 from my docker file, but there is no powershell core installed in the dotnet:2.2-sdk.
Is there any examples out there on how to run powershell core scripts from inside a dotnet image ? How can I create my own image from powershell core and dotnet sdk ?
Thanks
This is the exact use case I recently needed to implement, and you can indeed get Powershell Core up and running from a .NET Core SDK image - in my case the below was done against image mcr.microsoft.com/dotnet/core/sdk:2.2-stretch.
The full solution looks something like as follows:
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
...
FROM build AS final
WORKDIR /app
COPY --from=publish /app/publish .
RUN dotnet tool install --global PowerShell \
&& ln -s /root/.dotnet/tools/pwsh /usr/bin/pwsh
Where:
dotnet tool install --global PowerShell installs PowerShell into the container. However this alone is not quite good enough because as observed in #amirtharaj-rs answer, the command pwsh will not work unless invoked from the PowerShell installation directory.
For example, you may encounter something like:
root#a1d30119664d:/app# pwsh
bash: pwsh: command not found
ln -s /root/.dotnet/tools/pwsh /usr/bin/pwsh creates a link called pwsh which points to where PowerShell is installed. This is the key line which enables pwsh to be invoked from anywhere:
root#a1d30119664d:/app# pwsh
PowerShell 6.2.4
Copyright (c) Microsoft Corporation. All rights reserved.
https://aka.ms/pscore6-docs
Type 'help' to get help.
If the above does not work, then you may need to ensure that the execute bit is set on /usr/bin/pwsh. You can check this by running ls -l /usr/bin/pwsh.
If you do need to set the execute bit, add chmod 755 /root/.dotnet/tools/pwsh to the Dockerfile RUN command. So the complete RUN command would look something like:
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
...
FROM build AS final
WORKDIR /app
COPY --from=publish /app/publish .
RUN dotnet tool install --global PowerShell \
&& ln -s /root/.dotnet/tools/pwsh /usr/bin/pwsh
&& chmod 755 /root/.dotnet/tools/pwsh
If interested, I learnt the above via the discussion history on this Github issue: https://github.com/Microsoft/azure-pipelines-agent/issues/1862.
dotnet global tool provide powershell support which can be used as pwsh.
FROM mcr.microsoft.com/dotnet/core/sdk:2.2
USER ContainerAdministrator
WORKDIR /app
RUN dotnet tool install --global PowerShell
RUN setx /M PATH "%PATH%;C:\Users\ContainerUser\.dotnet\tools"
COPY ["publish/"," ."]
ENTRYPOINT ["C:\\Users\\ContainerAdministrator\\.dotnet\\tools\\pwsh.exe", "C:\\app\\PowershellScript.ps1"]
even after setting path i am not able use pwsh (powershell ) directly but after going inside installed path ..it provide powershell functionality

Install dotnet core tool Dockerfile

I have an .net core application where I would like to make a SonarBuild inside a container.
So I have a Dockerfile like this:
FROM microsoft/aspnetcore-build as build-env
WORKDIR /src
COPY question-metrics-api/question-metrics-api.csproj question-metrics-api/
COPY question-metrics-data/question-metrics-data.csproj question-metrics-data/
COPY question-metrics-domain/question-metrics-domain.csproj question-metrics-domain/
COPY tests/question-metrics-domain-tests/question-metrics-domain-tests.csproj tests/question-metrics-domain-tests/
RUN dotnet restore tests/question-metrics-domain-tests
RUN dotnet restore question-metrics-api/question-metrics-api.csproj
COPY . .
#Run tests
RUN dotnet test tests/question-metrics-domain-tests/question-metrics-domain-tests.csproj
#Begin Sonar
RUN dotnet tool install --global dotnet-sonarscanner
RUN dotnet sonarscanner begin /k:"question-metrics-api" /d:sonar.host.url="http://sonarqube:9000" /d:sonar.login="7ed84e09a17a31e783fa8522d876e27fe4624977"
RUN dotnet build
RUN dotnet sonarscanner end /d:sonar.login="7ed84e09a17a31e783fa8522d876e27fe4624977"
#End Sonar
RUN dotnet publish question-metrics-api/question-metrics-api.csproj -c Release -o publish
FROM microsoft/aspnetcore as runtime-env
COPY --from=build-env src/question-metrics-api/publish .
EXPOSE 80
ENTRYPOINT [ "dotnet", "question-metrics-api.dll" ]
When I try to build this dockerfile I got an error:
Step 11/19 : RUN dotnet tool install --global dotnet-sonarscanner
---> Running in 78719975f3b0
No executable found matching command "dotnet-tool"
How can I install dotnet tool from aspnetcore-build image?
Update
Ok, If I use the base image microsoft/dotnet:2.1-sdk I don't get anymore No executable found matching command "dotnet-tool" error, now I get No executable found matching command "dotnet-sonarscanner"
How can I use sonarscanner tool in this scenario?
As I have read in this thread: https://github.com/dotnet/dotnet-docker/issues/520, we can run a dotnet tool global command inside a container setting the following line:
ENV PATH="${PATH}:/root/.dotnet/tools"
So my final Dockerfile is like:
FROM microsoft/dotnet:2.1-sdk as build-env
WORKDIR /src
COPY question-metrics-api/question-metrics-api.csproj question-metrics-api/
COPY question-metrics-data/question-metrics-data.csproj question-metrics-data/
COPY question-metrics-domain/question-metrics-domain.csproj question-metrics-domain/
COPY tests/question-metrics-domain-tests/question-metrics-domain-tests.csproj tests/question-metrics-domain-tests/
RUN dotnet restore tests/question-metrics-domain-tests
RUN dotnet restore question-metrics-api/question-metrics-api.csproj
COPY . .
#Run tests
RUN dotnet test tests/question-metrics-domain-tests/question-metrics-domain-tests.csproj
#Begin Sonar
RUN dotnet tool install -g dotnet-sonarscanner
ENV PATH="${PATH}:/root/.dotnet/tools"
RUN dotnet sonarscanner begin /k:"question-metrics-api" /d:sonar.host.url="http://sonarqube:9000" /d:sonar.login="7ed84e09a17a31e783fa8522d876e27fe4624977"
RUN dotnet build
RUN dotnet sonarscanner end /d:sonar.login="7ed84e09a17a31e783fa8522d876e27fe4624977"
Hope that helps someone!
FROM microsoft/aspnetcore-build as build-env
That's the issue. Look at the dockerhub page for this: https://hub.docker.com/r/microsoft/aspnetcore-build/. See how it says that it only supports versions 1.1 and 2.0:
Latest images for 2.1 and newer are now available on microsoft/dotnet. See this link for more details about migrating to 2.1.
dotnet tool is only available in 2.1 and later. That's why doing RUN dotnet tool install --global dotnet-sonarscanner fails. dotnet doesn't know about a dotnet tool command at all. It tries to look for dotnet-tool in your $PATH, as a fallback, but no such thing exists either.
You actual fix was:
FROM microsoft/dotnet:2.1-sdk as build-env
Because this uses the new 2.1 SDK, which does know of the dotnet tool command.

Resources