1

I'm trying to make a docker image out of a local build environment that uses .NET 3.5. I try enable the feature but get an error.

This is my minimalized docker file for reproducing the problem:

FROM mcr.microsoft.com/dotnet/framework/sdk
RUN powershell "Install-WindowsFeature -Name NET-Framework-Features -Verbose"

This is the output:

Sending build context to Docker daemon  72.74MB
Step 1/2 : FROM mcr.microsoft.com/dotnet/framework/sdk
 ---> 88afad8be364
Step 2/2 : RUN powershell "Install-WindowsFeature -Name NET-Framework-Features -Verbose"
 ---> Running in 0a377584126e
VERBOSE: Installation started...
VERBOSE: Continue with installation?
VERBOSE: Prerequisite processing started...
VERBOSE: Prerequisite processing succeeded.
Install-WindowsFeature : The request to add or remove features on the
specified server failed.
Installation of one or more roles, role services, or features failed.
The service cannot be started, either because it is disabled or because it has
no enabled devices associated with it. Error: 0x80070422
At line:1 char:1
+ Install-WindowsFeature -Name NET-Framework-Features -Verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (@{Vhd=; Credent...Name=localh
   ost}:PSObject) [Install-WindowsFeature], Exception
    + FullyQualifiedErrorId : DISMAPI_Error__Failed_To_Enable_Updates,Microsof
   t.Windows.ServerManager.Commands.AddWindowsFeatureCommand

Success Restart Needed Exit Code      Feature Result
------- -------------- ---------      --------------
False   No             Failed         {}
VERBOSE: Installation succeeded.


The command 'powershell -Command $ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; powershell "Install-WindowsFeature -Name NET-Framework-Features -Verbose"' returned a non-zero code: 1

Building and running the bare image without the attempted install (Step 2/2) and checking the features show 3.5 is an option:

C:\>powershell "Get-WindowsFeature net*"

Display Name                                            Name                       Install State
------------                                            ----                       -------------
[ ] .NET Framework 3.5 Features                         NET-Framework-Features         Available
    [ ] .NET Framework 3.5 (includes .NET 2.0 and 3.0)  NET-Framework-Core               Removed
    [ ] HTTP Activation                                 NET-HTTP-Activation            Available
    [ ] Non-HTTP Activation                             NET-Non-HTTP-Activ             Available
[X] .NET Framework 4.8 Features                         NET-Framework-45-Fea...        Installed
    [X] .NET Framework 4.8                              NET-Framework-45-Core          Installed
    [ ] ASP.NET 4.8                                     NET-Framework-45-ASPNET        Available
    [X] WCF Services                                    NET-WCF-Services45             Installed
        [ ] HTTP Activation                             NET-WCF-HTTP-Activat...        Available
        [ ] Message Queuing (MSMQ) Activation           NET-WCF-MSMQ-Activat...        Available
        [ ] Named Pipe Activation                       NET-WCF-Pipe-Activat...        Available
        [ ] TCP Activation                              NET-WCF-TCP-Activati...        Available
        [X] TCP Port Sharing                            NET-WCF-TCP-PortShar...        Installed
[ ] Network Virtualization                              NetworkVirtualization            Removed

I tried enabling NET-Framework-45-ASPNET and that appears to work just fine, but then again it is listed as Available whereas NET-Framework-Core is listed as Removed.

Looking more into how to fix the Removed state suggests a folder with .cab-files from an OS install ISO should be listed as -Source. But OS name returned by cmd sysinfo yields plain Microsoft which has no corresponding ISO. I tried downloading Windows Server 2019 ISO and use its source/sxs as -Source, hoping for the best, but with same erroneous result and output (new Dockerfile):

FROM mcr.microsoft.com/dotnet/framework/sdk
# Copy sources/sxs from Windows Server 2016 ISO
COPY sources\sxs2016 C:\sources\sxs
RUN powershell "Install-WindowsFeature NET-Framework-Features -Source C:\sources\sxs -Verbose"

Any ideas how to make this work?

  • you need to point the -Source parameter to the full path of the ISO source/sxs files, either from a network share, or mounted from the local machine. Install-WindowsFeature Net-Framework-Core -source \\network\share\sxs or -source D:\sources\sxs docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/… – Smeerpijp Nov 4 '19 at 11:05
  • @Smeerpijp Fixed. Tried with both Server 2019 and 2016, still failing. At least one more error to find. – Andreas Nov 4 '19 at 12:36
  • @Andreas - Update your question to reflect that fact. Verify the ISOs matched the version you have installed. – Ramhound Nov 4 '19 at 13:11
  • @Ramhound Edited. As workaround I'm gonna try use a base image where 3.5 is already enabled (FROM microsoft/dotnet-framework-build:3.5). No disaster yet... – Andreas Nov 4 '19 at 13:32
  • @Smeerpijp Yes. I've verified it by omitting the Install-WindowsFeature line from the Dockerfile and then run it manually from within the running docker instance (docker run -it mydocker:latest). Have you tried running the Dockerfile yourself? I'd be mighty surprised if you get a different behavior. – Andreas Nov 4 '19 at 13:46
3

The error is occurring because it is trying to use the Windows Update service, which is disabled in the base containers. This is true even when directly providing a local path with the source to the installers.

The simplest change that makes the original Dockerfile work is to just enable the Windows Update service before installation:

FROM mcr.microsoft.com/dotnet/framework/sdk
RUN powershell "Set-Service -Name wuauserv -StartupType Manual; Install-WindowsFeature -Name NET-Framework-Features -Verbose"

The same approach works in a Powershell script where the .NET Framework 3.5 source has been copied locally:

Set-Service -Name wuauserv -StartupType "Manual"
write-output "Installing Windows Feature .net framework 35"
Install-WindowsFeature -Name NET-Framework-Features -Source C:\NET-Framework35-Features -Verbose

This might still be preferable compared to what Microsoft is using in the official image for sake of simplicity and maintainability. They directly reference specific versions and update those as needed.

| improve this answer | |
1

I found the solution in the Dockerfile for mcr.microsoft.com/dotnet/framework/runtime:3.5:

# escape=`

FROM mcr.microsoft.com/windows/servercore:1903

# Install .NET Fx 3.5
RUN curl -fSLo microsoft-windows-netfx3.zip https://dotnetbinaries.blob.core.windows.net/dockerassets/microsoft-windows-netfx3-1903.zip `
    && tar -zxf microsoft-windows-netfx3.zip `
    && del /F /Q microsoft-windows-netfx3.zip `
    && DISM /Online /Quiet /Add-Package /PackagePath:.\microsoft-windows-netfx3-ondemand-package~31bf3856ad364e35~amd64~~.cab `
    && del microsoft-windows-netfx3-ondemand-package~31bf3856ad364e35~amd64~~.cab `
    && powershell Remove-Item -Force -Recurse ${Env:TEMP}\*

# Apply latest patch
RUN curl -fSLo patch.msu http://download.windowsupdate.com/d/msdownload/update/software/updt/2019/09/windows10.0-kb4515871-x64_03a6aec54b0ca2fc40efcff09a810064f5d2ae60.msu `
    && mkdir patch `
    && expand patch.msu patch -F:* `
    && del /F /Q patch.msu `
    && DISM /Online /Quiet /Add-Package /PackagePath:C:\patch\Windows10.0-kb4515871-x64.cab `
    && rmdir /S /Q patch

# ngen .NET Fx
ENV COMPLUS_NGenProtectedProcess_FeatureEnabled 0
RUN \Windows\Microsoft.NET\Framework64\v2.0.50727\ngen uninstall "Microsoft.Tpm.Commands, Version=10.0.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=amd64" `
    && \Windows\Microsoft.NET\Framework64\v2.0.50727\ngen update `
    && \Windows\Microsoft.NET\Framework\v2.0.50727\ngen update

The difference from what I tried would seem to be:

  • Download the netfx3-on-demand-package from "microsoft docker assets".
  • Install it using DISM and point out the package path instead of source path.

The Dockerfile also applies a patch of some sort and updates ngen. (Not sure if it is relevant but honestly too afraid to make changes to this witchcraft recipe.)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.