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?
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.
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:
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.)
User contributions licensed under CC BY-SA 3.0