Search code examples
docker.net-coresigntool

signtool.exe fails within Docker container


I have a Target defined in my .NET Core project's csproj file that signs the built executable using signtool.exe as follows:

<Target Name="RunAfterPublish" AfterTargets="Publish">
    <Exec Command="&quot;$(MSBuildThisFileDirectory)signtool.exe&quot; sign /p &quot;mypassword&quot; /f &quot;$(MSBuildThisFileDirectory)my-code-sign-cert.pfx&quot; /fd SHA256 /d MyApp /du http://myapp.com /t http://timestamp.digicert.com/ &quot;$(PublishDir)$(AssemblyName).exe&quot;" ConsoleToMSBuild="true" />
</Target>

Publishing the app locally using dotnet publish works fine.

However, I would like to build the app into a Docker image, so I have defined the following Dockerfile:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app

COPY . ./
RUN dotnet restore
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["MyApp.exe"]

Running docker build . fails with the following output:

Step 5/9 : RUN dotnet publish -c Release -o out
 ---> Running in 51f0d0b573dd
Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  MyApp -> C:\app\bin\Release\net6.0\MyApp.dll
  MyApp -> C:\app\out\
C:\app\MyApp.csproj(11,3): error MSB3073: The command ""C:\app\signtool.exe" sign /p "mypassword" /f "C:\app\my-code-sign-cert.pfx" /fd SHA256 /d MyApp /du http://myapp.com /t http://timestamp.digicert.com/ "C:\app\out\MyApp.exe"" exited with code -1073741515.
The command 'cmd /S /C dotnet publish -c Release -o out' returned a non-zero code: 1

When I move the signtool.exe command into the Dockerfile instead, the publish succeeds, but the signtool.exe command still fails and with a different error code as when invoking it from the csproj Target (3221225781 instead of -1073741515):

Step 6/10 : RUN signtool.exe sign /p "mypassword" /f my-code-sign-cert.pfx /fd SHA256 /d MyApp /du http://myapp.com /t http://timestamp.digicert.com/ out\MyApp.exe
 ---> Running in ee6fde892c66
The command 'cmd /S /C signtool.exe sign /p "mypassword" /f my-code-sign-cert.pfx /fd SHA256 /d MyApp /du http://myapp.com /t http://timestamp.digicert.com/ out\MyApp.exe' returned a non-zero code: 3221225781

Solution

  • The signtool.exe file requires .NET Framework to be installed (it's not a .NET Core application). By default, the 6.0 tag you're using will give you an image based on Nano Server when targeting Windows containers. Nano Server does not support .NET Framework. Instead, you'll want to target Windows Server Core which does support .NET Framework.

    The currently supported .NET tags available for Windows Server Core are 6.0-windowsservercore-ltsc2019 (for Windows Server 2019) and 6.0-windowsservercore-ltsc2022 (for Windows Server 2022).

    By targeting one of these tags, you should be able to successfully execute signtool.exe as this Dockerfile shows:

    FROM mcr.microsoft.com/dotnet/sdk:6.0-windowsservercore-ltsc2019
    COPY signtool.exe .
    RUN signtool.exe
    
    C:\test> docker build .
    Sending build context to Docker daemon  397.3kB
    Step 1/3 : FROM mcr.microsoft.com/dotnet/sdk:6.0-windowsservercore-ltsc2019
     ---> debaa753a42a
    Step 2/3 : COPY signtool.exe .
     ---> 30ce3866e2da
    Step 3/3 : RUN signtool.exe
     ---> Running in 099750c36b30
    SignTool Error: A required parameter is missing.
    Usage: signtool <command> [options]
    
            Valid commands:
                    sign       --  Sign files using an embedded signature.
                    timestamp  --  Timestamp previously-signed files.
                    verify     --  Verify embedded or catalog signatures.
                    catdb      --  Modify a catalog database.
                    remove     --  Reduce the size of an embedded signed file.
    
    For help on a specific command, enter "signtool <command> /?"
    The command 'cmd /S /C signtool.exe' returned a non-zero code: 1