docker-compose build copy failed - c#

I'm trying to upload my project to a Digital Ocean droplet using docker i'm stuck in this stage, where COPY fails whenever i run docker-compose build.
Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["iCoose.API/iChoose.API.csproj", "iCoose.API/"]
COPY ["iChoose.Business.Entities/iChoose.Business.Entities.csproj", "iChoose.Business.Entities/"]
COPY ["iChoose.Business.Services/iChoose.Business.Services.csproj", "iChoose.Business.Services/"]
COPY ["iChoose.Common.Core/iChoose.Common.Core.csproj", "iChoose.Common.Core/"]
COPY ["iChoose.DataAccess.Data/iChoose.DataAccess.Data.csproj", "iChoose.DataAccess.Data/"]
RUN dotnet restore "iCoose.API/iChoose.API.csproj"
COPY . .
WORKDIR "/src/iCoose.API"
RUN dotnet build "iChoose.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "iChoose.API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "iChoose.API.dll"]
docker-compose.yml:
#docker-compose
version: '2'
services:
app:
build:
context: ./
dockerfile: Dockerfile
https-portal:
image: steveltn/https-portal:1
ports:
- '80:80'
- '443:443'
links:
- app
restart: always
environment:
DOMAINS: 'domain.com -> http://app:5000'
STAGE: 'production'
When I run the 'docker-compose build' command in the servers terminal it starts building until it gets to the first COPY command, where I get:
ERROR: Service 'app' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder987069796/iCoose.API/iChoose.API.csproj: no such file or directory.
I checked the files and there is no directory in that path after the 'tmp' folder, which is empty.

The Dockerfile and docker-compose.yaml files should be right next to sln and csproj file.
When you create a new project in Visual Studio and leave put project file inside the project folder this issue might occure.
Make sure you have sln and csproj in the same folder.
Also, the Dockerfile and 'docker-compose.yaml` in the same folder too.
Deeper answer:
Dockerfile contains instructions for the docker engine on how to create a docker image for your application.
Each line is a layer of docker image.
FROM
COPY
RUN
CMD
All these commands will create a new docker image, which are cache by the engine for next run.
Because these images are Linux based and linux uses cgroup and namespaces to create isolated environment which is the feature on which docker is built. This isolated environment has a special folder which is appearing in the error message.

Related

Azure Devops Pipeline - file not found in build context

Getting an error in the Azure DevOps Pipeline:
Step 7/17 : COPY ["demo6/demo6.csproj", "demo6/"]
COPY failed: file not found in build context or excluded by .dockerignore: stat demo6/demo6.csproj: file does not exist
NOTES-run the pipeline in diagnostics mode and the .sln file exists
##[debug]cwd=/home/vsts/work/1/s
##[debug] /home/vsts/work/1/s/demo6.sln (file)
##[debug] /home/vsts/work/1/s/demo6/demo6.csproj (file)
I have a multi-project Asp.Net Core solution with the folder structure and projects as follows:
demo6
|--demo6/demo6.csproj
|--demo6.api/demo6.api.csproj
The app is demo6 which references demo6.api which is a class library.
This is in GitHub in a repository demo6. I modified the autogenerated Dockerfile to add the extra demo6/ to see if that works but no.
Appreciate any help.
Dockerfile below:
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["demo6/demo6.csproj", "demo6/"]
RUN dotnet restore "demo6/demo6.csproj"
COPY . .
WORKDIR "/src/demo6"
RUN dotnet build "demo6.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "demo6.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "demo6.dll"]
Also tried this:
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["demo6/demo6/demo6.csproj", "ddemo6/"]
RUN dotnet restore "ddemo6/demo6.csproj"
COPY . .
WORKDIR "/src/ddemo6"
RUN dotnet build "demo6.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "demo6.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "demo6.dll"]
Got this error:
Step 7/17 : COPY ["demo6/demo6/demo6.csproj", "ddemo6/"]
COPY failed: file not found in build context or excluded by .dockerignore: stat demo6/demo6/demo6.csproj: file does not exist
##[error]COPY failed: file not found in build context or excluded by .dockerignore: stat demo6/demo6/demo6.csproj: file does not exist
here's the repo structure
The reason of file not found error may be the relative path of the Dockerfile and the csproj are different. Try to set the Dockerfile in the root of the solution should solve your error.
Also you need to add a buildContext with the csproj folder.
buildContext: Path to the build context
Also, here is a case you can refer to.
One more possible cause of COPY failed: no source files were specified is .dockerignore file present in your workspace
Look for .dockerignore file because of docker’s CLI (command line interface) it sends context to the docker daemon to load the .dockerignore file.
If the .dockerignore file exist in the context than it might be possible there is exclude entry to ignore the build directory
# ignore or exclude build directory
*/build*
*/*/build*

How to lower down the size of dockerized .Net Core apps?

I normally use Rider for that but for reproduction purposes I will describe the process by using the terminal
I created a .Net 5 Web Api and want to add Docker support for it. I tried to get into it by playing around with a sample app. So with the terminal I create a new Web Api
mkdir project
cd project
dotnet new sln
dotnet new webapi -o Api
dotnet sln add ./Api
I check that everything is fine with
cd Api
dotnet run
call https://localhost:5001/weatherforecast in the browser
close with ctrl + c
Inside the Api project I create a Dockerfile with this content
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet
WORKDIR /app
EXPOSE 80
COPY --from=build /app/out .
ENTRYPOINT [ "dotnet", "Rest.dll" ]
I also create a .dockerignore file with this content
.git
Dockerfile
bin/
obj/
I'm building the image with
docker build -t api .
When I now run
docker images
this image has a size of 209MB. I would like to know if this is "the best/right way to go" or if there is something I can improve in the Dockerfile or .dockerignore file.
Thanks in advance
You can base your Dockerfile off a smaller image. Searching the catalogue of available images in the Microsoft container registry (MCR) here, the Linux alpine (5.0-alpine) is probably the most lightweight. Note that for the other distros, there may be a regular and slim variant, where the regular is the SDK environment and the slim is the production environment.
Then you can structure your Dockerfile as follows to move the artefacts from the build output in the SDK image to the final lightweight deployment image:
FROM mcr.microsoft.com/dotnet/core/runtime:3.1-buster-slim AS base
WORKDIR /app
# Main build (SDK environment)
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
RUN dotnet restore "webapi.csproj"
COPY . .
WORKDIR "/src/webapi"
RUN dotnet build "webapi.csproj" -c Release -o /app/build
# Publish build outputs to /app dir
FROM build AS publish
RUN dotnet publish "webapi.csproj" -c Release -o /app/publish
# Final deployment image
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "api.dll"]
In my example, I've used the Debian buster SDK image for the build stage and the buster slim for deployment.

Docker Copy failed with ASP.net Core

I am trying to run my ASP.net Core application with docker, but for some reasons each time I try with different approach with the Dockerfile I fail by copying the directory.
What am I doing wrong? I tried the step by step guide in Microsoft web using my own proj but with unsuccess.
The cmd error I recieve:
C:\dev\Dmail\Dmail.API>docker build -t aspnetapp .
Sending build context to Docker daemon 21.79MB
Step 1/18 : FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
---> 47da1e9634dc
Step 2/18 : WORKDIR /app
---> Using cache
---> bf490aa67962
Step 3/18 : EXPOSE 80
---> Using cache
---> d172deff350a
Step 4/18 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
---> 4a651b73be3d
Step 5/18 : WORKDIR /src
---> Using cache
---> c607b7f04e23
Step 6/18 : COPY ["Dmail.API/Dmail.API.csproj", "Dmail.API/"]
COPY failed: stat /var/lib/docker/tmp/docker-builder531905822/Dmail.API/Dmail.API.csproj: no such file or directory
C:\dev\Dmail\Dmail.API>
Here is my DockerFile:
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Dmail.API/Dmail.API.csproj", "Dmail.API/"]
COPY ["Dmail.Core/Dmail.Core.csproj", "Dmail.Core/"]
COPY ["Dmail.Data/Dmail.Data.csproj", "Dmail.Data/"]
RUN dotnet restore "Dmail.API/Dmail.API.csproj"
COPY . .
WORKDIR "/src/Dmail.API"
RUN dotnet build "Dmail.API.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Dmail.API.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Dmail.API.dll"]
So after long time of searching the web for a solution I managed to solve my problem.
First of all the Dockerfile was generated automatically by Visual Studio by pressing add onto the ASP.net project and then Docker Support.
The Visual Studio locate the file inside the project. What I did in order to solve the problem was to move the file as it is to the solution folder which is for me Dmail. For example my files were like this:
Dmail(solution)
Dmail.API(proj)
Dmail.Core(proj)
Dmail.Data(proj)

Docker build fails when project reference and nuget feed added

I'm new to docker and I'm trying to create docker image/container in my local machine. It is working fine if I've a simple project without any project reference and private nuget feed. I'm getting the below errors when I do docker build (from src\Account\Account.host folder) after adding a project reference and private nuget feed.
Skipping project "/Shared/SharedComponent/SharedComponent.csproj" because it was not found.
error NU1101: Unable to find package . No packages exist with this id in source(s): nuget.org
I tried to modify it but getting copying files out of context errors. My questions are:
- is it possible to run docker build with the below folder structure?
- do i need to use docker compose if i want to stick with the same folder structure?
- I've got other project where i need to add another docker file but I'm just testing with one project which doesnt seems to be working.
Project folder structure
Shared
++ SharedComponent
+++ ShareComponent.csproj
+++ Other files
Account
++Account.Host
+++ Account.Host.csproj (SharedComponent.csproj reference added)
+++ Dockerfile
+++ Other files
Dockerfile
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /src
COPY ["Account.Host.csproj", "./"]
RUN dotnet restore "./Account.Host.csproj"
COPY . .
RUN dotnet build "Account.Host.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "Account.Host.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Account.Host.dll"]
Docker build needs to be able to see the whole project when it builds, so it can determine if any of the files have changed (among other things).
You probably need to run docker build from the root directory of the project, and tell it where the Dockerfile is, like this:
docker build -t the_name_of_the_image -f Account/Account.Host/Dockerfile
The above might not be quite right, but the directory structure you posted didn't render right :(

How to use "dotnet watch run" with .Net Core 3, Visual Studio 2019 and docker

I'm playing with docker and .NET Core 3 using Visual Studio 2019. I containerize my application by adding the Dockerfile to my project (right click on the project -> Add -> Docker Support) and I was able to launch it, but now I want to use dotnet watch run inside the container.
This is the generated Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
WORKDIR /src
COPY ["DockerTestApp/DockerTestApp.csproj", "DockerTestApp/"]
RUN dotnet restore "DockerTestApp/DockerTestApp.csproj"
COPY . .
WORKDIR "/src/DockerTestApp"
RUN dotnet build "DockerTestApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "DockerTestApp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "DockerTestApp.dll"]
and I modified it like so:
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
ENV DOTNET_USE_POLLING_FILE_WATCHER 1
WORKDIR /src
EXPOSE 80
EXPOSE 443
COPY ["DockerTestApp/DockerTestApp.csproj", "DockerTestApp/"]
RUN dotnet restore "DockerTestApp/DockerTestApp.csproj"
ENTRYPOINT ["dotnet", "watch", "run"]
The container started with dotnet watch run but any file change isn't detected and the rebuild is not triggered.
Should I have to mount a volume from my code directory to the container in order to make it work?
Thanks.
UPDATE
with this Dokerfile
FROM mcr.microsoft.com/dotnet/core/sdk:3.0
ENV DOTNET_USE_POLLING_FILE_WATCHER 1
WORKDIR /app
COPY . .
ENTRYPOINT dotnet watch run --urls=https://+:5001 --project DocketTestApp.csproj
and this docker-compose.yml
version: '3.4'
services:
dotnet-watch-docker-example:
container_name: dotnet_watch_docker_example
image: giuseppeterrasi/dotnet-watch-docker-example
build:
context: ./DocketTestApp/
ports:
- 5001:5001
volumes:
- './DocketTestApp/:/app/'
depends_on:
- db
db:
image: mysql
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: testPassword
MYSQL_DATABASE: testDB
MYSQL_USER: testUser
MYSQL_PASSWORD: test
It works, but if I add a DbContext, Visual Studio misses the Entity Framework reference if the container is started. If I stop the container and reload Visual Studio everything is ok.
Why?
You can omit using a custom Dockerfile when you want to run dotnet watch run locally.
Consider the following docker-compose.yml file:
version: '3.4'
services:
dotnet-watch-docker-example:
container_name: dotnet_watch_docker_example
image: mcr.microsoft.com/dotnet/core/sdk:3.0
ports:
- 5001:5001
volumes:
- ./DockerTestApp:/app
working_dir: /app
command: dotnet watch run
Instead of creating a custom image from the base dotnet sdk image, the compose file simply starts a container based on the base dotnet sdk image. It then creates a volume that maps the local directory containing your project to the directory /app inside the container. It then sets the working directory inside the container to /app, and lastly, it runs the dotnet watch run command inside the container.
To fix your problem with the Entity framework reference, add the following Directory.Build.props file inside the project directory. This file instructs MSBUILD to place /bin and /obj files in different directories (container/local) dependent upon the executing environment. This way, no conflicts emerge.
<Project>
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/obj/**/*</DefaultItemExcludes>
<DefaultItemExcludes>$(DefaultItemExcludes);$(MSBuildProjectDirectory)/bin/**/*</DefaultItemExcludes>
</PropertyGroup>
<PropertyGroup Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' == 'true'">
<BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/container/</BaseIntermediateOutputPath>
<BaseOutputPath>$(MSBuildProjectDirectory)/bin/container/</BaseOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(DOTNET_RUNNING_IN_CONTAINER)' != 'true'">
<BaseIntermediateOutputPath>$(MSBuildProjectDirectory)/obj/local/</BaseIntermediateOutputPath>
<BaseOutputPath>$(MSBuildProjectDirectory)/bin/local/</BaseOutputPath>
</PropertyGroup>
</Project>
Change the entry point like this,
ENTRYPOINT dotnet watch run --no-restore
This will rebuild the server whenever new changes occurs.
Files inside the obj/ and the bin/ folders have to be different on your local machine and inside the Docker container. If they overlap, you’ll get errors.
To resolve that issue, you can change the location of the obj/ and bin/ as
#Mike Hawkins explained.
But there is also an another solution.
Bind mount volume override your docker bin/ and obj/ directories with local bin/ and obj/, to avoid this overriging, you have to tell docker that bin/ and obj/ folders shouldn't be overwritten from outside. That can be achived with another (anonymous) volume. Docker evaluates all your volumes and if they are overlapping, the longer internal path is leading the way.
You can define this volume in the Dockerfile
VOLUME ["/app/path/to/bin"]
VOLUME ["/app/path/to/obj"]
Or in the docker-compose
volumes:
- ./DockerTestApp:/app
- /app/path/to/bin
- /app/path/to/obj
The disadvantage of this approach is need of explicitly typing all bin/ and obj/ folder paths from the entire solution.

Categories