Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: WCOW: add powershell.exe dir to default PATH for backward compatibiliy #5446

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

profnandaa
Copy link
Collaborator

@profnandaa profnandaa commented Oct 23, 2024

The current default PATH has been set to the most basic subset for both nanoserver and servercore.

const DefaultPathEnvWindows = "c:\\Windows\\System32;c:\\Windows;

The path to powershell.exe is conspicuously missing hence breaking the developer experience for most workloads that depend on PS.

This fix proposes to append ;C:\\Windows\\System32\\WindowsPowerShell\\v1.0 to that list to support PS scenarios, that make a big chunk of workloads, especially legacy ones, migrating from on-prem to cloud.

Fixes #4901, microsoft/Windows-Containers#500
Ref #3158

Basic Test

# note, only servercore+ has powershell
FROM mcr.microsoft.com/windows/servercore:ltsc2022
RUN powershell -C Write-Host "hello powershell!!"

On classic docker build:

Step 2/2 : RUN powershell -C Write-Host "hello powershell!!"
 ---> Running in e06539ef3f11
hello powershell!!

Buildkit before fix:

> [2/2] RUN powershell -C Write-Host "hello powershell!!":
1.684 'powershell' is not recognized as an internal or external command,
1.684 operable program or batch file.
------
Dockerfile:2
--------------------
   1 |     FROM mcr.microsoft.com/windows/servercore:ltsc2022
   2 | >>> RUN powershell -C Write-Host "hello powershell!!"
   3 |

Buildkit after fix:

#5 [2/2] RUN powershell -C Write-Host "hello powershell!!"
#5 5.916 hello powershell!!
#5 DONE 7.1s

Implication for nanoserver:

This does not any way break the experiences for those using nanoserver base image, as much as PS and the C:\\Windows\\System32\\WindowsPowerShell\\v1.0 path is not present on nanoserver.

Transition users to using ENV:

Users coming from classic docker build will need to transition from using RUN setx /M to ENV as a way of persisting environment variables in the images.

We can take a hit on not supporting backward compatibility for RUN setx /M, as opposed to not supporting both RUN setx /M and RUN powershell as it is the case right now.

Alternative considered:

We thought of an option to ask the Windows platform team to add a default Config.Env.PATH in the config file for the base image. However, this causes a regression for RUN setx /M on the classic docker build. There could be a couple of more people too that might be depending on Config.Env = null as it is currently. See:

PS> docker inspect mcr.microsoft.com/windows/servercore:ltsc2022

Here is the regression details when we set ENV in the base image.

FROM mcr.microsoft.com/windows/servercore:ltsc2022 AS newbase
ENV PATH="C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps"

FROM newbase
RUN setx /M PATH "C:\my\path;%PATH%"
RUN echo %PATH%
PS> docker build --no-cache -t profnandaa/servercore-path-tests .

<snip>
Step 5/5 : RUN echo %PATH%
---> Running in 785633e2a31c
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps
   ^
   | ~~~~~~~~~ notice "C:\my\path" is missing, meaning `setx /M` is not persisting as before.

Current RUN setx /M behavior:

FROM mcr.microsoft.com/windows/servercore:ltsc2022
RUN setx /M PATH "C:\my\path;%PATH%"
RUN echo %PATH%
PS> docker build --no-cache -t profnandaa/servercore-path-tests .

<snip>

Step 3/3 : RUN echo %PATH%
---> Running in 3bacb0b27bad
C:\my\path;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps;
   ^
   |~~~~ `setx /M` persists.

setx vs. ENV has been discussed in details in #5445

@thaJeztah
Copy link
Member

Curious; would this case work if the PATH was not set at all? Re;

i.e., are we tapering over the actual bug (that no PATH should be set, as it overrides the default Windows behavior of controlling this through the windows registry?)

@profnandaa
Copy link
Collaborator Author

profnandaa commented Oct 23, 2024

Curious; would this case work if the PATH was not set at all? Re;

i.e., are we tapering over the actual bug (that no PATH should be set, as it overrides the default Windows behavior of controlling this through the windows registry?)

@thaJeztah -- I was suggesting here #5445 that we are at a cross-road to decide to either go for registry-backed or config-backed environment variables. Going for both ends up in confusion, especially in cases where there are name collusions (and config takes precedence). For instance if you attempt to do this with registry-backed PATH env like it is in classic docker-build:

FROM <any official base image>
ENV PATH "$PATH;C:\\my\\added\\path"
RUN echo PATH=%PATH%

You just end up with PATH=;C:\\my\\added\\path, since config.Env is null in the official base images.

We can carry on the conversations on #5445 -- will appreciate your input.

The current default `PATH` has been set to the most basic subset for both
`nanoserver` and `servercore`.

```go
const DefaultPathEnvWindows = "c:\\Windows\\System32;c:\\Windows;
```

The path to `powershell.exe` is conspicuously missing hence breaking the
developer experience for most workloads that depend on PS.

This fix proposes to append `;C:\\Windows\\System32\\WindowsPowerShell\\v1.0`
to that list to support PS scenarios, that make a big chunk of workloads,
especially legacy ones, migrating from on-prem to cloud.

Fixes moby#4901, microsoft/Windows-Containers#500
Ref moby#3158

Implication for nanoserver:
===========================
This does not any way break the experiences for those using `nanoserver` base image,
as much as PS and the `C:\\Windows\\System32\\WindowsPowerShell\\v1.0` path is not present
on `nanoserver`.

Transition users to using `ENV`:
==============================
Users coming from classic `docker build` will need to transition from using `RUN setx /M`
to `ENV` as a way of persisting environment variables in the images.

We can take a hit on not supporting backward compatibility for `RUN setx /M`, as opposed
to not supporting both `RUN setx /M` and `RUN powershell` as it is the case right now.

Alternative considered:
=======================
We thought of an option to ask the Windows platform team
to add a default `Config.Env.PATH` in the config file for the base image.
However, this causes a regression for `RUN setx /M` on the classic `docker build`.
There could be a couple of more people too that might be depending on `Config.Env = null`
as it is currently. See `docker inspect mcr.microsoft.com/windows/servercore:ltsc2022`.

Here is the regression details when we set `ENV` in the base image.

```
PS> type .\Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2022 AS newbase
ENV PATH="C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps"

FROM newbase
RUN setx /M PATH "C:\my\path;%PATH%"
RUN echo %PATH%

PS> docker build --no-cache -t profnandaa/servercore-path-tests .

Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM mcr.microsoft.com/windows/servercore:ltsc2022 AS newbase
---> e64ba0f4256b
Step 2/5 : ENV PATH="C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps"
---> Running in ab3dc4921d7d
---> Removed intermediate container ab3dc4921d7d
---> f57b0a2d0e28
Step 3/5 : FROM newbase
---> f57b0a2d0e28
Step 4/5 : RUN setx /M PATH "%PATH%;C:\my\path;"
---> Running in 6ca6171334a0

SUCCESS: Specified value was saved.
---> Removed intermediate container 6ca6171334a0
---> 6d2870e2f91d
Step 5/5 : RUN echo %PATH%
---> Running in 785633e2a31c
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps
   ^
   | ~~~~~~~~~ notice "C:\my\path" is missing, meaning `setx /M` is not persisting as before.

---> Removed intermediate container 785633e2a31c
---> ed490181b903
Successfully built ed490181b903
Successfully tagged profnandaa/servercore-path-tests:latest
```

Current `RUN setx /M` behavior:

```
PS> type .\Dockerfile

FROM mcr.microsoft.com/windows/servercore:ltsc2022
RUN setx /M PATH "%PATH%;C:\my\path;"
RUN echo %PATH%

PS> docker build --no-cache -t profnandaa/servercore-path-tests .

Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM mcr.microsoft.com/windows/servercore:ltsc2022
---> e64ba0f4256b
Step 2/3 : RUN setx /M PATH "C:\my\path;%PATH%"
---> Running in 5502dd679495

SUCCESS: Specified value was saved.
---> Removed intermediate container 5502dd679495
---> 0b59f38e2da4
Step 3/3 : RUN echo %PATH%
---> Running in 3bacb0b27bad
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps;C:\my\path;
                    ^
                    |~~~~ `setx /M` persists.
---> Removed intermediate container 3bacb0b27bad
---> cda1b4cd27ff
Successfully built cda1b4cd27ff
Successfully tagged profnandaa/servercore-path-tests:latest
```

`setx` vs. `ENV` has been discussed in details in moby#5445

Signed-off-by: Anthony Nandaa <[email protected]>
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the C:\\Windows\\System32\\WindowsPowerShell\\v1.0" path set by default in the servercore and nanoserver base images? If not then what is the default there?

@profnandaa
Copy link
Collaborator Author

Thanks for TAL @tonistiigi --

Is the C:\\Windows\\System32\\WindowsPowerShell\\v1.0" path set by default in the servercore and nanoserver base images? If not then what is the default there?

Yes, servercore has PowerShell path set among others (which we don't need for our scenario). nanoserver doesn't have it coz it's a small image that has most bulky features like PS stripped off. However, us including it here won't break anything.

Here are the details:

PS> docker run mcr.microsoft.com/windows/servercore:ltsc2022 cmd /c echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ContainerAdministrator\AppData\Local\Microsoft\WindowsApps

PS> docker run mcr.microsoft.com/windows/nanoserver:ltsc2022 cmd /c echo %PATH%
C:\Windows\system32;C:\Windows;

And as I have detailed in #5445, both servercore and nanoserver don't set the PATH (nor any other env vars) in the configs but in registry. If set in the image config, it breaks RUN setx ... for classic docker build.

PS> docker inspect mcr.microsoft.com/windows/servercore:ltsc2022 
...
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": null, <------ this
            "Cmd": [
                "c:\\windows\\system32\\cmd.exe"
            ],
     ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

buildkit WCOW cannot seemingly run RUN powershell ..., while vanilla dockerd can
4 participants