37

I need to append to the PATH within a Windows Docker container, and I've tried many permutations.

ENV PATH=%PATH%;C:\\Foo\\bin
ENV PATH=$PATH;C:\\Foo\\bin
ENV PATH="%PATH%;C:\Foo\bin"
ENV PATH="$PATH;C:\Foo\bin"
RUN "set PATH=%PATH%;C:\Foo\bin"

None of these work: they don't evaluate the preexisting PATH variable.

What is the right syntax to append to the PATH? Can I even append to the PATH inside Docker? (I can on similar Linux containers)

macetw
  • 1,640
  • 1
  • 17
  • 26
  • Environment variables which you pass to Docker container are only visible for processes executed by docker executable. They will not be visible machine wide. But if you are ok with that then why not just read this variable during start up and append it PATH variable once inside container instead. Issue with environment variables not visible system wide is here https://github.com/docker/docker/issues/30192 – Gregory Suvalian Feb 07 '17 at 14:58
  • 1
    @GSA, if there is no solution, I'd consider that an answer, too. But I'm surprised that the "Append to the PATH for my container environment" isn't a solved user-story for Windows containers. – macetw Feb 07 '17 at 15:10

8 Answers8

61

Unfortunately ENV won't work, because windows environment variable work a little differently than linux. more info

As of now the only way to do this is through RUN

But you don't need to create a separate file to do this. This can be done by the following much simpler one line command:

RUN setx path "%path%;C:\Foo\bin"

mirsik
  • 981
  • 8
  • 10
  • 26
    PS equiv: RUN setx /M PATH $($Env:PATH + ';C:\Foo\bin) – JasonCoder Aug 21 '18 at 15:44
  • 9
    @JasonCoder - thanks! Just missing a final single quote before the last paren. – Glenn Sep 12 '18 at 20:30
  • We tried your solution today, and ran into the trouble that setx did not work but only ENV, as suggested here: https://github.com/PowerShell/PowerShell-Docker/issues/164 I'm quite puzzled; but we will soon switch to linux containers anyway... – Hermann.Gruber Dec 18 '19 at 15:57
  • PS equiv 2: `RUN setx /M PATH \"$Env:PATH;C:\Foo\bin\"`. Spent a couple extra irritating hours *re*-finding out that you need to escape the double quote `\"` in Dockerfile-windows-powershell to have a literal double quote in the command. See https://github.com/StefanScherer/dockerfiles-windows/tree/789fa0b54c0d0263fa9464025cfe12ec2fe0cd6c/quotes. In other words, the above is equivalent to having an interactive powershell session and doing `setx /M PATH "$Env:Path;C:\Foo\bin"` – solstice333 Mar 07 '23 at 02:19
  • Actually, it's a bit more complicated than I initially realized. You may also want to be aware of the three types of environment variable: Machine/System, User, Process. See [this](https://github.com/solstice333/docker-env-var-repro#reliable-ways-for-setting-environment-variables-in-windows-docker-powershell) – solstice333 Mar 08 '23 at 22:59
13

You can set environment variables permanently in the container using a powershell script.

Create a powershell script in yout docker context (e.g. setpath.ps1 ) containing this:

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Foo\bin", [EnvironmentVariableTarget]::Machine)

Add this script to your container dockerfile and RUN the script. Add something like this to your dockerfile:

ADD ./setpath.ps1 c:/MyScripts/setpath.ps1
RUN powershell -Command c:\MyScripts\setpath.ps1
cer49152
  • 131
  • 1
  • 4
  • This does not work for me. The PATH variable is the same as before, regardless of whether I have this line in my dockerfile. Any ideas? – Jonas Sourlier Aug 21 '18 at 12:05
  • 1
    This worked for me on a dotnet framework container (4.7.1). Only thing I would add was to get any "RUN powershell..." command to work properly I had to add the ENTRYPOINT ["powershell.exe"] line to the top of the dockerfile after the FROM. – Khoward Dec 09 '22 at 17:31
10

[Environment]::SetEnvironmentVariable is a good way, but will not work in nanoserver. The best choice is:

RUN setx path '%path%;C:\Foo\bin'
mpromonet
  • 11,326
  • 43
  • 62
  • 91
cherishty
  • 373
  • 2
  • 5
  • 13
  • This is giving me `ERROR: The system cannot find registry path specified.` for the image `mcr.microsoft.com/dotnet/sdk:7.0` ... That image doesn't have powershell ot try the powershell solution. But suggestion of Mark Nguyen, using `USER ContainerAdministrator` and then using the `/M` flag for `setx` does work. – nl-x Jul 21 '23 at 13:28
10

This worked for me:

USER ContainerAdministrator
RUN setx /M PATH "%PATH%;C:/your/path"
USER ContainerUser

As seen in the .net sdk Dockerfile: https://github.com/dotnet/dotnet-docker/blob/20ea9f045a8eacef3fc33d41d58151d793f0cf36/2.1/sdk/nanoserver-1909/amd64/Dockerfile#L28-L29

Mark Nguyen
  • 7,168
  • 9
  • 31
  • 41
  • This works for me! Tested on Windows Nano Server 1909 – Vitalii Ilchenko Oct 31 '20 at 10:24
  • Awsome, thanks. Worked on Server 2019 with `mcr.microsoft.com/dotnet/framework/sdk:4.7.2` image. Since all my other commands in the dockerfile use escaped backslash as a path separator I modified the command to `RUN "setx /M PATH \"%PATH%;C:\\Program Files\\Git\\bin\""` – Jürgen Steinblock Mar 13 '23 at 09:35
2

Despite all previous answers, I've faced an issue in some environments. Basically on a custom local test environment the setx using the %PATH%;C:\foo\bar way works even when the folder has spaces like C:\Program Files. That though didn't work when trying it on our production environment. Checking what Microsoft do when they install the base packages on their own images it turns out a better and more reliable way is to use the command this way:

RUN setx /M PATH $(${Env:PATH} + \";${Env:ProgramFiles(x86)}\foo\bar\")

This way docker will be able to get the proper paths and properly update the PATH data.

Edit: I've fixed the missing trailing \ in the command, thanks to Robin Ding :)

  • Missing \ at the end: ```RUN setx /M PATH $(${Env:PATH} + \";${Env:ProgramFiles(x86)}\foo\bar\")``` Also works with space: ```RUN setx /M PATH $(${Env:PATH} + \";${Env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\")``` – Robin Ding Aug 03 '21 at 07:10
0

The following works for me in nanoserver-1809 (from this GitHub issue):

ENV PATH="$WindowsPATH;C:\Foo\bin"
bgh
  • 1,986
  • 1
  • 27
  • 36
0

My answer is similar to mirsik's but has no need for a separate script. Just put this in your Dockerfile

RUN $env:PATH = 'C:\Foo\bin;{0}' -f $env:PATH ; \
[Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine)
TrojanName
  • 4,853
  • 5
  • 29
  • 41
0

The below commands worked for me in a Dockerfile with the base image mcr.microsoft.com/windows/servercore:ltsc2019.

(My scenario was to set Java in the PATH. It works even if there are spaces in the path)

(Make sure to update JAVA_HOME environment variable, with your application/tool)

ENV JAVA_HOME="C:\Program Files\Java\jdk-17"

RUN $newPath = ('{0}\bin;{1}' -f $env:JAVA_HOME, $env:PATH); \
     [Environment]::SetEnvironmentVariable('PATH', $newPath, [EnvironmentVariableTarget]::Machine)

CMD ["java", "--version"]

On a side note, I did get errors like below when trying some of the other answers here (for reasons like - there were spaces in the path, or, Env variable ${Env:ProgramFiles} was not getting resolved properly, etc.)

  • The term 'C:\Program' is not recognized as the name of a cmdlet.
  • Unexpected token '\Java\jdk-17\bin' in expression or statement.
Arutsudar Arut
  • 195
  • 1
  • 13