fsprojects / Paket

A dependency manager for .NET with support for NuGet packages and Git repositories.
https://fsprojects.github.io/Paket/
MIT License
2.02k stars 520 forks source link

dotnet paket restore failed while building docker image #3885

Open im-avi opened 4 years ago

im-avi commented 4 years ago

Description

The command "dotnet paket restore" exited with code 1.

Repro steps

Please provide the steps required to reproduce the problem

  1. Install paket as .Net core Local tool POCs\HelloDI> dotnet new tool-manifest POCs\HelloDI> dotnet tool install paket POCs\HelloDI> dotnet paket init

  2. add /bin & /obj to .dockerignore file at root folder

    .git
    **/bin/
    **/obj/
  3. add package to .csproject POCs\HelloDI> cd .\src\HelloDI.Console\ POCs\HelloDI\src\HelloDI.Console> dotnet paket add Microsoft.Extensions.Configuration.Json --interactive

  4. Docker file contents (src\HelloDI.Console\Dockerfile)

ARG VERSION=3.1-alpine3.12
FROM mcr.microsoft.com/dotnet/core/sdk:$VERSION as build-env
WORKDIR /HelloDI.Console

COPY /src/HelloDI.Console/*.csproj .
RUN dotnet restore

COPY . .
RUN dotnet publish src/HelloDI.Console/HelloDI.Console.csproj --output /out/ --configuration Release

FROM mcr.microsoft.com/dotnet/core/runtime:$VERSION as runtime
WORKDIR /HelloDI.Console
COPY --from=build-env /out .

ENTRYPOINT ["dotnet", "HelloDI.Console.dll"]
  1. Local Msbuild successful. POCs\HelloDI\src\HelloDI.Console> cd ..\.. POCs\HelloDI> dotnet build

Output

Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Paket version 5.247.4
  The last restore is still up to date. Nothing left to do.
  Performance:
   - Runtime: 228 milliseconds
  Paket version 5.247.4
  Starting restore process.
  Performance:
   - Runtime: 1 second
  Restored D:\@aviWin10.workspace\@POCs\HelloDI\tests\HelloDI.Console.Tests\HelloDI.Console.Tests.csproj (in 9.3 sec).
  1 of 2 projects are up-to-date for restore.

.....
  1. Error during-Build Docker image POCs\HelloDI> docker build -t hello-di/console:0.1 -f ./src/HelloDI.Console/dockerfile .

Output

Step 5/11 : RUN dotnet restore
 ---> Using cache
 ---> a3b73898202f
Step 6/11 : COPY . .
 ---> 65085b0c2d6f
Step 7/11 : RUN dotnet publish src/HelloDI.Console/HelloDI.Console.csproj --output /out/ --configuration Release
 ---> Running in f16be0b6c474
Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Run "dotnet tool restore" to make the "paket" command available.
/HelloDI.Console/.paket/Paket.Restore.targets(171,5): error MSB3073: The command "dotnet paket restore" exited with code 1. 
[/HelloDI.Console/src/HelloDI.Console/HelloDI.Console.csproj]
The command '/bin/sh -c dotnet publish src/HelloDI.Console/HelloDI.Console.csproj --output /out/ --configuration Release' returned a non-zero code: 1

Expected behavior

dotnet paket restore should execute successfully.

Actual behavior

error at dotnet paket restore

Known workarounds

remove **/obj/ from .dockerignore

baronfel commented 4 years ago

This is a problem with your docker file.

You need to run dotnet tool restore to ensure that the paket tool is installed for your repository before paket an be used to restore your dependencies.

Alternatively, since you've restored already in your dockerfile you can pass the --no-restore flag to dotnet publish to skip restoring at all, which should not trigger paket.

im-avi commented 4 years ago
  1. COPY . . in dockerfile copies .packet directory to build context current folder.
  2. As per documentation dotnet restore implicitly calls dotnet tool restore
  3. donet restore should use .paket\Paket.Restore.targets which should implicitly create *.csproj.paket.props , *.csproj.paket.references.cached, *.csproj.netcoreapp3.1.paket.resolved during dotnet publish process.

While in current case restore is looking for *.csproj.paket.props , *.csproj.paket.references.cached, *.csproj.netcoreapp3.1.paket.resolved files in /obj folder not creating them if they do not exist.

baronfel commented 4 years ago

Thanks for the detailed breakdown, everything you say makes sense to me now

As per documentation dotnet restore implicitly calls dotnet tool restore

Any details on this? Apparently this has changed since I first started using dotnet tools. Right now I have dotnet tool restore in basically every CI/CD pipeline I use.

im-avi commented 4 years ago

https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-restore#name https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-restore#project-specific-tooling

im-avi commented 4 years ago

This is a problem with your docker file.

You need to run dotnet tool restore to ensure that the paket tool is installed for your repository before paket an be used to restore your dependencies.

Alternatively, since you've restored already in your dockerfile you can pass the --no-restore flag to dotnet publish to skip restoring at all, which should not trigger paket.

Just tried above suggestion : As I am trying to containerize a single project from multi-project solution

  1. Updated docker file
    
    ARG VERSION=3.1-alpine3.12
    FROM mcr.microsoft.com/dotnet/core/sdk:$VERSION as build-env
    WORKDIR /HelloDI

COPY /.config/dotnet-tools.json .config/dotnet-tools.json RUN dotnet tool restore

COPY HelloDI.sln . COPY paket.dependencies . COPY paket.lock . COPY src/HelloDI.Console/HelloDI.Console.csproj src/HelloDI.Console/HelloDI.Console.csproj COPY src/HelloDI.Console/paket.references src/HelloDI.Console/paket.references RUN dotnet restore src/HelloDI.Console/HelloDI.Console.csproj

COPY . .

RUN dotnet publish src/HelloDI.Console/HelloDI.Console.csproj --output /out/ --configuration Release --no-restore

FROM mcr.microsoft.com/dotnet/core/runtime:$VERSION as runtime WORKDIR /HelloDI.Console COPY --from=build-env /out .

ENTRYPOINT ["dotnet", "HelloDI.Console.dll"]

2. Build docker image 
`POCs\HelloDI> docker build -t hello-di/console:0.1 -f ./src/HelloDI.Console/dockerfile .`

### Expected behavior

- Output should be
`Successfully tagged hello-di/console:0.1`

### Actual behavior

- Error while publishing

Step 13/17 : RUN dotnet publish src/HelloDI.Console/HelloDI.Console.csproj --output /out/ --configuration Release --no-restore ---> Running in e3337125a4cc Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core Copyright (C) Microsoft Corporation. All rights reserved.

Paket version 5.247.4 The last restore is still up to date. Nothing left to do. Performance:

Known workarounds

ramondeklein commented 3 years ago

I encountered the same issue and it seems that during build-time it explicitly invokes dotnet-paket instead of dotnet paket. I created a symlink in my Dockerfile to ensure that the file can be run. My Dockerfile looks like this:

FROM mcr.microsoft.com/dotnet/sdk:5.0
WORKDIR /app

# Make sure we have enough to restore all packages
COPY paket.dependencies paket.lock .config/dotnet-tools.json ./
RUN dotnet tool restore
RUN echo "#!/bin/sh" > /usr/local/bin/dotnet-paket && echo "dotnet `find /root/.nuget/packages/paket -name paket.dll` \$*" >> /usr/local/bin/dotnet-paket && chmod 755 /usr/local/bin/dotnet-paket
RUN dotnet paket restore

# Copy source code
COPY . ./

# Pubish output
RUN dotnet publish -c Release --framework net5.0 --runtime linux-x64 -o /out/x64 MyAmazingProject/MyAmazingProject.csproj

The important line is the RUN echo ... to create the dotnet-paket command. I am not a big fan of using find, because it may result in multiple binaries. I did use it to not break my Dockerfile when I upgrade paket.