Azure DevOps Pipeline: COPY failed: stat /var/lib/docker/…: no such file or directory

Summary

Running a docker build task in an Azure DevOps pipeline causes no such file or directory error.

...
Step 7/26 : COPY ["Hello-Blazor/Hello-Blazor.csproj", "Hello-Blazor/"]
COPY failed: stat /var/lib/docker/tmp/docker-builder890404231/Hello-Blazor/Hello-Blazor.csproj: no such file or directory
##[error]COPY failed: stat /var/lib/docker/tmp/docker-builder890404231/Hello-Blazor/Hello-Blazor.csproj: no such file or directory
##[error]The process '/usr/bin/docker' failed with exit code 1
Finishing: Build an image

The error occurs when the pipeline task build context does not match the build context defined in the Dockerfile. By default it assumes the Dockerfile directory which is not always the case for Visual Studio generated solutions/projects. A buildContext attribute can be added to the pipeline task to explicitly set the build context directory required by the Dockerfile.

... 
buildContext: '$(Build.SourcesDirectory)/Hello-Blazor/'
...

Description

For the detailed cause of this error refer to http://torbenp.com/2020/07/copy-failed-no-such-file-or-directory/
The Azure Pipeline task needs to be explicitly configured to execute the docker build from the parent folder defined by the Dockerfile as it will otherwise assume the Dockerfile folder as the build context. The following shows the default pipeline task without an explicit build context.

...
    - task: Docker@2
      displayName: Build an image
      inputs:
        command: build
        dockerfile: '$(Build.SourcesDirectory)/Hello-Blazor/Hello-Blazor/Dockerfile'
        tags: |
          $(tag)
...

This can create a COPY build failure with the following details:

COPY error from Azure DevOps Pipeline
Azure DevOps Pipeline COPY Error

To make the parent folder of the Dockerfile the build context, add the ‘buildContext’ attribute to the pipeline task configuration.

...
    - task: Docker@2
      displayName: Build an image
      inputs:
        command: build
        dockerfile: '$(Build.SourcesDirectory)/Hello-Blazor/Hello-Blazor/Dockerfile'
        buildContext: '$(Build.SourcesDirectory)/Hello-Blazor/'
        tags: |
          $(tag)
...

COPY failed: stat /var/lib/docker/tmp/docker-builder392878620/Hello-Blazor/Hello-Blazor.csproj: no such file or directory

Summary

Running docker build within the Dockerfile folder causes no such file or directory error.

C:\Hello-Blazor\docker build --force-rm -t helloblazor:latest .
Sending build context to Docker daemon  2.653MB
...
COPY failed: stat /var/lib/docker/tmp/docker-builder392878620/Hello-Blazor/Hello-Blazor.csproj: no such file or directory

Move up one folder (parent folder of Dockerfile) to change the build context and provide path to the Dockerfile.

C:\docker build -f .\Hello-Blazor\Dockerfile --force-rm -t helloblazor:latest .

Description

When building a Docker image from a Visual Studio generated Dockerfile, such as a .NET Core project, the error ‘no such file or directory’ can occur if the right build context is missing. In Visual Studio generated solutions and projects, the Solution file (.sln) is often in a parent folder to the Project files and their individual Dockerfiles. This makes the Visual Studio solution folder the root build context to build all projects and this build context is assumed in the compiler generated Dockerfile for projects.

C:.
+---Hello-Blazor.sln    //Build Context
+---Hello-Blazor
|   +---Hello-Blazor.csproj
|   +---Dockerfile

The autogenerated Dockerfile for multi-staged builds will show the solution folder build context in the COPY and RUN operations.

...
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["Hello-Blazor/Hello-Blazor.csproj", "Hello-Blazor/"]
RUN dotnet restore "Hello-Blazor/Hello-Blazor.csproj"
...

To build the Docker image, use the solution folder as the build context (current folder) and use the -f parameter to pass the Dockerfile path instead of building directly from the Dockerfile folder.

C:\docker build -f ./Hello-Blazor/Dockerfile --force-rm -t helloblazor:latest .