Docker COPY fails in Rider when running VS generated dockerfile - visual-studio

I'm running into problems when trying to run a dockerfile that I created in VS2017 in Rider 2019.2. The Dockerfile works fine in VS2017, but since the company I work for also allows developers to use other IDE's we need the Dockerfile to work in Rider (for example) too.
I added a new Docker project wihtin my solution by adding Container Orchestrator Support in VS2017.
My .sln project structure is:
Bram.Website
> Bram.Website // contains the Dockerfile
> docker-compose // contains docker-compose.yml
The generated Dockerfile looks like this:
FROM microsoft/aspnet:4.7.2-windowsservercore-1803
ARG source
WORKDIR /inetpub/wwwrootDock
COPY ${source:-obj/Docker/publish} .
The generated docker-compose.yml is:
version: '3.4'
services:
bram.website:
image: ${DOCKER_REGISTRY-}bramwebsite
build:
context: .\Bram.Website
dockerfile: Dockerfile
I changed my JetBrains build configuration according to the information in this article: https://blog.jetbrains.com/dotnet/2018/07/18/debugging-asp-net-core-apps-local-docker-container/
My config now looks like:
My build command is:
docker build -t <image_tag> . && docker run -p 8000:80 --name bramwebsite <image_tag>
When I try to build this I get the following output:
Deploying 'bram-website Dockerfile: Bram.Website/Dockerfile'...
Building image...
Step 1/4 : FROM microsoft/aspnet:4.7.2-windowsservercore-1803
---> d58c3fe3a54e
Step 2/4 : ARG source
---> Using cache
---> 7be7e1854e6f
Step 3/4 : WORKDIR /inetpub/wwwroot
---> Using cache
---> 6d53dbdcf2cd
Step 4/4 : COPY ${source:-obj/Docker/publish} .
Error: ResponseItem.ErrorDetail[code=<null>,message=COPY failed: CreateFile \\?\C:\ProgramData\Docker\tmp\docker-builder371292226\obj\Docker\publish: The system cannot find the file specified.]
Failed to deploy 'bram-website Dockerfile: Bram.Website/Dockerfile': COPY failed: CreateFile \\?\C:\ProgramData\Docker\tmp\docker-builder371292226\obj\Docker\publish: The system cannot find the file specified.
I'm not sure if this is a problem with my config or if this is an issue in Rider or in the way VS generates the files. The folder at 'C:\ProgramData\Docker\tmp' appears to be empty. My best guess at the moment is that Rider is having difficulties with the 'source' macro that is injected by VS2017? Any help or insight is greatly appreciated.

Related

An issue with resolving directory names when building a docker container for an asp.net core 3.1 web app

Visual Studio 2019 generates a docker file whose COPY statement looks like the following due to the way that the application's folders are structured:
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["MyWebApp/MyWebApp.csproj", "MyWebApp/"]
COPY ["../../core/Logic/Logic.csproj", "../../core/Logic/"]
COPY ["../../core/Models/Models.csproj", "../../core/Models/"]
RUN dotnet restore "MyWebApp/MyWebApp.csproj"
COPY . .
WORKDIR "/src/MyWebApp"
RUN dotnet build "MyWebApp.csproj" -c Release -o /app/build
I keep getting the following error message when running docker compose command:
=> ERROR [build 4/9] COPY [../../core/Logic/Logic.csproj,
../../core/Logic/] 0.0s
=> ERROR [build 5/9] COPY [../../core/Models/Models.csproj, ../../core/Models/]
We cannot restructure the folders in VS 2019 as it has been set up in that way due to some reasons. The docker file resides in MyWebApp project's folder and the docker compose file is in the parent folder of MyWebApp folder where the solution resides. Even I moved the docker file adjacent to the docker compose file but it was not conclusive.
The following code snippet is the docker-compose file:
version: '3.4'
services:
mywebapp:
image: ${DOCKER_REGISTRY-}mywebapp
build:
context: .
dockerfile: MyWebApp/Dockerfile
ports:
- 8080:80
- 8443:443
What is the workaround or solution to address this problem?
If your file structure is:
docker-compose.yml
MyWebApp/MyWebApp.csproj
core/Logic/Logic.csproj
core/Models/Models.csproj
Your Dockerfile should be:
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["MyWebApp/MyWebApp.csproj", "MyWebApp/"]
COPY ["core/Logic/Logic.csproj", "../../core/Logic/"]
COPY ["core/Models/Models.csproj", "../../core/Models/"]
RUN dotnet restore "MyWebApp/MyWebApp.csproj"
COPY . .
WORKDIR "/src/MyWebApp"
RUN dotnet build "MyWebApp.csproj" -c Release -o /app/build
Why?
Because the current working directory is always the context directory. Context can be set using docker-compose's build.context field. In your example, the context is the solution root. So the Dockerfile is executed from that directory, irrespective or where it's placed.
You cannot access files outside the context directory.
Eg. if context resolves to /a/b/c, Dockerfile can't COPY or use files in /a/b/d

Docker in Win (Linux container): Docker Compose in Visual Studio uses hidden .yml file

In testing Docker, I used Visual Studio to containerize one project in a solution. Folder structure like this:
/AlfaModulesPoc.sln
/Modules/AlfaCom/AlaCom.csproj
/Modules/AlfaCom/Dockerfile
I did this by right-clicking the project --> Add... --> Docker Support... and choose "Linux":
VS then created the Dockerfile, that looked good on paper, but in reality could not be used since the paths in that Dockerfile was based on the Dockerfile being placed in the solution folder (2 folders "up"), but it was placed inside the project folder (as I expected).
Building the image from here did not work at all, files could not be found etc.
The workaround was to also add "Container Orchestrator Support..." which created a new project called "docker-compose" in the solution root folder, and a docker-compose.yml file that looks like this:
version: '3.4'
services:
alfacom:
image: ${DOCKER_REGISTRY-}alfacom
build:
context: .
dockerfile: Modules/AlfaCom/Dockerfile
As soon as I added this Orchestration Support, VS also proceeded in creating the image automatically and starting it. At this point, I did not pay attention to the Output logs.
When checking Visual Studio Output window, I was the expected console logs that the program gives out, and I also saw data being handled in the Redis server, since the program adds data to Redis. I also looked in the Docker Desktop application, and saw the same console logs. Looked good to me.
I then stopped it, and tried to start it manually, via console, like this:
PS C:\Git\alfa\AlfaModulesPoc> docker-compose -f "C:\Git\alfa\AlfaModulesPoc\docker-compose.yml" -p dockercompose5247976386926556655 --no-ansi up -d
but that failed with the error:
Step 6/20 : COPY
["../Submodules/Core/CoreCommons/CoreCommons/CoreCommons.csproj",
"../Submodules/Core/CoreCommons/CoreCommons/"] Service 'alfacom'
failed to build: COPY failed: Forbidden path outside the build
context: ../Submodules/Core/CoreCommons/CoreCommons/CoreCommons.csproj
()
Question 1: Why? I am using the .yml file, and that files says that context: . so why this error?
And its not until I realize that VS actually had 3 different yml files. The command VS executed was:
PS C:\Git\alfa\AlfaModulesPoc> docker-compose -f "C:\Git\alfa\AlfaModulesPoc\docker-compose.yml" -f "C:\Git\alfa\AlfaModulesPoc\docker-compose.override.yml" -f "C:\Git\alfa\AlfaModulesPoc\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose5247976386926556655 --no-ansi up -d
and it is the very hidden, auto-generated file docker-compose.vs.debug.g.yml that contains the most settings:
version: '3.4'
services:
alfacom:
image: alfacom:dev
container_name: AlfaCom
build:
target: base
labels:
com.microsoft.created-by: "visual-studio"
com.microsoft.visual-studio.project-name: "AlfaCom"
environment:
- NUGET_FALLBACK_PACKAGES=
volumes:
- C:\Git\alfa\AlfaModulesPoc\Modules\AlfaCom:/app
- C:\Users\wagge\vsdbg\vs2017u5:/remote_debugger:rw
- C:\Users\wagge\.nuget\packages\:/root/.nuget/packages:ro
entrypoint: tail -f /dev/null
labels:
com.microsoft.visualstudio.debuggee.program: "dotnet"
com.microsoft.visualstudio.debuggee.arguments: " --additionalProbingPath /root/.nuget/packages \"/app/bin/Debug/netcoreapp3.1/AlfaCom.dll\""
com.microsoft.visualstudio.debuggee.workingdirectory: "/app"
com.microsoft.visualstudio.debuggee.killprogram: "/bin/sh -c \"if PID=$$(pidof dotnet); then kill $$PID; fi\""
tty: true
Running the same 3-yml-command that VS did removes the error:
Question 2: What is it in this .yml file that fixes it? is it the C:\Git\alfa\AlfaModulesPoc\Modules\AlfaCom:/app line under volumes:?
So, the container is now running, but not working.
Any yml files that visual studio uses "behind the scenes" should be ignored it seems.
The problem is using project references, if those exits outside of your solution directory, you need to have NuGet references instead

Dockerfile doesn't seem to run while debugging in Visual Studio 2019

The past few weeks i've been working on a project which is built in C# .NET Core in Visual Studio 2019. I enabled Docker support and am using docker-compose to spin up 2 containers (it starts an identityserver4 and webapi). I've created dockerfiles for both projects and created a docker-compose file for starting up the service stack.
The issue i'm running into is that when i run the docker-compose in Visual Studio Debugging mode, it doesnt seem to run my Dockerfile. In the lasts steps in my Dockerfile, I copy some files around and execute a command. These do not get run. However when I use docker build in my commandline, it DOES execute those Dockerfile commands.
Attached my 2 docker files & docker compose.
Web API Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["Api/MyApp.Api.Core/MyApp.Api.Core.csproj", "Api/MyApp.Api.Core/"]
COPY ["Api/MyApp.Api.Base/MyApp.Api.Base.csproj", "Api/MyApp.Api.Base/"]
COPY ["Base/MyApp.Base.Contracts/MyApp.Base.Contracts.csproj", "Base/MyApp.Base.Contracts/"]
COPY ["Base/MyApp.Base.Model/MyApp.Base.Model.csproj", "Base/MyApp.Base.Model/"]
COPY ["Data/MyApp.Data.EntityFramework/MyApp.Data.EntityFramework.csproj", "Data/MyApp.Data.EntityFramework/"]
COPY ["ContactpersoonService.cs/MyApp.Services.csproj", "ContactpersoonService.cs/"]
COPY ["Apps/MyApp.Apps.Settings/MyApp.Apps.Settings.csproj", "Apps/MyApp.Apps.Settings/"]
RUN dotnet restore "Api/MyApp.Api.Core/MyApp.Api.Core.csproj"
COPY . .
WORKDIR "/src/Api/MyApp.Api.Core"
RUN dotnet build "MyApp.Api.Core.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "MyApp.Api.Core.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
COPY Api/MyApp.Api.Core/Security/Certificates /app/Security/Certificates
RUN mkdir -p /usr/local/share/ca-certificates/identityserver
RUN chmod -R 777 /usr/local/share/ca-certificates/identityserver
RUN cp /app/Security/Certificates/* /usr/local/share/ca-certificates/identityserver
RUN update-ca-certificates
ENTRYPOINT ["dotnet", "MyApp.Api.Core.dll"]
IdentityServer Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["Api/MyApp.Api.IdentityServer/MyApp.Api.IdentityServer.csproj", "Api/MyApp.Api.IdentityServer/"]
COPY ["Api/MyApp.Api.Base/MyApp.Api.Base.csproj", "Api/MyApp.Api.Base/"]
COPY ["Base/MyApp.Base.Contracts/MyApp.Base.Contracts.csproj", "Base/MyApp.Base.Contracts/"]
COPY ["Base/MyApp.Base.Model/MyApp.Base.Model.csproj", "Base/MyApp.Base.Model/"]
COPY ["Data/MyApp.Data.EntityFramework/MyApp.Data.EntityFramework.csproj", "Data/MyApp.Data.EntityFramework/"]
COPY ["Apps/MyApp.Apps.Settings/MyApp.Apps.Settings.csproj", "Apps/MyApp.Apps.Settings/"]
RUN dotnet restore "Api/MyApp.Api.IdentityServer/MyApp.Api.IdentityServer.csproj"
COPY . .
WORKDIR "/src/Api/MyApp.Api.IdentityServer"
RUN dotnet build "MyApp.Api.IdentityServer.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "MyApp.Api.IdentityServer.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
COPY Api/MyApp.Api.Core/Security/Certificates /app/Security/Certificates
RUN mkdir -p /usr/local/share/ca-certificates/identityserver
RUN chmod -R 777 /usr/local/share/ca-certificates/identityserver
RUN cp /app/Security/Certificates/* /usr/local/share/ca-certificates/identityserver
RUN update-ca-certificates
ENTRYPOINT ["dotnet", "MyApp.Api.IdentityServer.dll"]
docker-compose.yaml:
version: '3.4'
services:
myapp.api.core:
image: ${DOCKER_REGISTRY-}myappapicore
build:
context: .
dockerfile: Api/MyApp.Api.Core/Dockerfile
links:
- myapp.identity.api:identityserver
ports:
- "52008:80"
volumes:
- "C:/Projects/User/MyApp.Api/Api/MyApp.Api.Core/Security/Certificates/ca.crt:/usr/local/share/ca-certificates/identityserver/identityserver.crt:ro"
networks:
app_net:
ipv4_address: 192.168.1.200
myapp.identity.api:
image: ${DOCKER_REGISTRY-}myappapiidentityserver
build:
context: .
dockerfile: Identity/MyApp.Identity.Api/Dockerfile
ports:
- "5000:80"
- "5001:443"
volumes:
- "C:/Projects/User/MyApp.Api/Api/MyApp.Api.IdentityServer/Security/Certificates/ca.crt:/usr/local/share/ca-certificates/identityserver/identityserver.crt:ro"
networks:
app_net:
ipv4_address: 192.168.1.201
networks:
app_net:
external: true
I'm using Visual Studio 2019 (16.3.4)
This is apparently by design as a "Fast mode" optimization in Visual Studio 2019. See the documentation for debugging in containers here.
What it states is that "Fast mode" is the default behavior when debugging containers in VS 2019. In this mode, only the first stage (base) of a multi-stage build is built according to the Dockerfile. VS then handles the rest on the host machine, ignoring the Dockerfile, and shares the output to the container by using volume mounting. This means that any custom steps you add to other stages will be ignored when using the Debug configuration in VS 2019. (The reason given for this non-obvious, and therefore potentially frustrating, optimization is that builds are much slower in a container than on the local machine.) Note that this optimization only happens when using the Debug configuration. The Release configuration will use the entire Dockerfile.
Your options are:
Place your custom steps in the first (base) step of the Dockerfile.
or
Disable this optimization by editing the project file like this:
<PropertyGroup>
<ContainerDevelopmentMode>Regular</ContainerDevelopmentMode>
</PropertyGroup>
Also keep in mind that it will try to reuse a previously built container if possible, so you may need to perform a Clean or Rebuild in order to force the build to create a new version of the container.
Good luck!
** EDIT **
It seems that there is an issue when trying to use the ContainerDevelopmentMode flag after Container Orchestration Support (in this case, Docker Compose) is added. See this issue. It is suggested in the issue discussion that this flag could be used on the docker-compose.dcproj file, but there is a bug (still not fixed) that keeps that approach from working.
A third option, hinted at in my previous answer but not made explicit, would be:
Switch your solution configuration from Debug to Release.
This works, but clearly isn't ideal when you're trying to debug your application.

How to setup a docker project (dcproj) for a dotnet core Web API app in VS2017

I'm using dotnetcore to develop applications and one thing I noticed when creating a aspnetcore (2.1) web api was the option to "Enable Docker" on the project. See below:
This was really great for allowing me to run my web application against my local docker for debugging! :-D I see that I have a new .dcproj file for the docker project, a docker file in my web api and a yml file in the docker project. Everything I needed to run in debug.
Now I'm creating a dotnetcore console application (again core 2.1 is the version I'm using). Unfortunately, I dont have an "Enable Docker Support" option for console apps and would like to run my console app in my local docker instance. Visual studio version I'm running is as follows:
I had a look for and can't seem to find the docker project as a project type template. So I resorted to copying over the docker project from my web app and modifying it to run my console app... needless to say I'm not able to get this running. I get the following error when I try to launch the docker compose:
Failed to launch debug adapter
My docker file is identical to the one from the web project (that works), other than my project and dll names (these are set correctly).
My yml file is the same also, other than the names being changed also. Not sure what I'm doing wrong - has anyone managed to achieve this? I ultimately want to debug my console application when it's running in docker through Visual Studio debug.
Thanks for any pointers in advance!!
For verbosity, here's my Dockerfile:
FROM microsoft/dotnet:2.1.2-runtime-alpine3.7 AS base
WORKDIR /app
EXPOSE 52649
EXPOSE 44331
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY AI.EmitterJob.csproj AI.EmitterJob/
RUN dotnet restore AI.EmitterJob/AI.EmitterJob.csproj
COPY . .
WORKDIR /src/AI.EmitterJob
RUN dotnet build AI.EmitterJob.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish AI.EmitterJob.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "AI.EmitterJob.dll"]
And docker-compose.yml file:
version: '3.4'
services:
ai.emitterjob:
image: ${DOCKER_REGISTRY}ai_emitter
build:
context: .
dockerfile: ../AI.EmitterJob/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_HTTPS_PORT=44331
ports:
- "52649:80"
- "44331:443"
volumes:
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
Note - I know I dont need to expose ports or use volumes here (or set env vars) for the console app, but I wanted to keep changes from the web docker file that works, to a minimum.
Just in case anyone else wants to try this, I finally got it working!
When I copied over the docker file, the only line I changed was from this:
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
To this:
FROM microsoft/dotnet:2.1.2-runtime-alpine3.7 AS base
Because I'd used that alpine build before as a base image. Reverting back to the aspnetcore base image made this work fine.
Obviously, this isn't ideal for proper deployments and I need to find a sufficient replacement for the aspnetcore base image that will have the dotnetcore runtime installed.
I'm happy I can debug my console app through docker now! :-D

"Docker build path not found" in docker support Visual Studio Project

I have C# solution, with 4 projects, 3 being Dlls and 1 is the console application uses those DLLs.
I tried to use docker support on visual studio to build my docker image, it fails
My dockerfile as below:
> FROM microsoft/windowsservercore:ltsc2016
> EXPOSE 80
> EXPOSE 1433
> EXPOSE 29051
>
> COPY bin/x64/debug /root/ ENTRYPOINT
> /root/RmsMainConsole.exe
I CD into directory where my dockerfile is at and execute docker build.
Error:
Docker CLI command : docker build -t rmsmainconsole:self-hosted .
Sending build context to Docker daemon 55.61MB
Step 1/6 : FROM microsoft/windowsservercore:ltsc2016
---> 9dbf7f740334
Step 2/6 : EXPOSE 80
---> Using cache
---> ad0ad85fd107
Step 3/6 : EXPOSE 1433
---> Using cache
---> 81ba13dbd4d4
Step 4/6 : EXPOSE 29051
---> Using cache
---> 1fa3db800abf
Step 5/6 : COPY bin/x64/debug /root/
COPY failed: CreateFile \\?\C:\ProgramData\Docker\tmp\docker-builder043346063\bin\x64\debug: The system cannot find the path specified.
You can see that PATH couldn't be found.
Whereas i tried to create docker file on my .sln level.
I changed one line in my docker file.
COPY RmsMainConsole/bin/x64/debug /root/
Note: "RmsMainConsole" directory has been added.
i executed the docker build at my .sln level and i built it successfully.
Logs are:
Sending build context to Docker daemon 1.15GB
Step 1/6 : FROM microsoft/windowsservercore:ltsc2016
---> 9dbf7f740334
Step 2/6 : EXPOSE 80
---> Running in fe97cf236d5a
Removing intermediate container fe97cf236d5a
---> c31e236353b6
Step 3/6 : EXPOSE 1433
---> Running in f031fce5ecba
Removing intermediate container f031fce5ecba
---> 96c704c68ffb
Step 4/6 : EXPOSE 29051
---> Running in 365e2be43d0e
Removing intermediate container 365e2be43d0e
---> d30c3fb2214b
Step 5/6 : COPY RmsMainConsole/bin/x64/debug /root/
---> b214c1edc256
Step 6/6 : ENTRYPOINT /root/RmsMainConsole.exe
---> Running in 5c819915532a
Removing intermediate container 5c819915532a
---> 247f01bb9b82
Successfully built 247f01bb9b82
Successfully tagged rmsmainconsole:self-hosted
I noticed two difference between the successful and failed build:
1. Size on the docker context
2. The logs at step 5/6:
COPY failed: CreateFile \?\C:\ProgramData\Docker\tmp\docker-builder043346063\bin\x64\debug: The system cannot find the path specified.
and
---> b214c1edc256
How should i use visual studio docker support to build my docker image. Where did i go wrong ?
Not sure, whether I answer your question - first or second :).
I was also wondering how Visual Studio is using Docker, because Dockerfile is created within project folder, but it contains paths for COPY like it was in the root (sln) folder.
I played with it a bit and answer is pretty simple.
Visual Studio builds images from the solution folder using -f switch to point to Dockerfile.
You can watch Output window to see it running following command:
docker build -f "<path to Dockerfile>" -t <name:tag> --target base --label "com.microsoft.created-by=visual-studio" "<solution dir>"
So, I would recommend having Dockerfile in project folder and run it from the root folder using -f option like Visual Studio does it.
Does it answer your question(s)?
After some thoughts, trials and errors, the problems does not lie on docker support visual studio. Docker build has to be run at the root of my solution directory, as docker build need to be able to locate all the dependencies the image file that is depending on.
but what got me curious is, then how is docker support for visual studio come into play ? I can only Right click -> Add Docker support at my console application project.
My current solution is to manually add a docker file at the root of solution. Would be glad if anyone knows visual studio docker support has a better way to solve this ?
Thanks
I think the actual reason for this is much simpler. If you look at the docker ignore (.dockerignore) file, you'll notice that it ignores everything except for a couple of obj folders. Try removing the * at the top of the docker ignore file to test this out. Then you can selectively ignore things you have in the project folder that you'd like to copy over. I ran into this as well and it took lots of trial and error before I thought to look at the ignore file.

Resources