Appending to PATH in a Windows Docker container
Asked Answered
H

11

42

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)

Hymeneal answered 7/2, 2017 at 14:53 Comment(2)
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 github.com/docker/docker/issues/30192Nephrosis
@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.Hymeneal
G
67

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"

Gast answered 29/3, 2018 at 6:55 Comment(5)
PS equiv: RUN setx /M PATH $($Env:PATH + ';C:\Foo\bin)Pyrazole
@Pyrazole - thanks! Just missing a final single quote before the last paren.Inshore
We tried your solution today, and ran into the trouble that setx did not work but only ENV, as suggested here: github.com/PowerShell/PowerShell-Docker/issues/164 I'm quite puzzled; but we will soon switch to linux containers anyway...Periodontics
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 github.com/StefanScherer/dockerfiles-windows/tree/…. In other words, the above is equivalent to having an interactive powershell session and doing setx /M PATH "$Env:Path;C:\Foo\bin"Ezekielezell
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 thisEzekielezell
C
14

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
Carchemish answered 5/7, 2017 at 11:52 Comment(2)
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?Alack
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.Adsorbate
I
10

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

RUN setx path '%path%;C:\Foo\bin'
Ingar answered 6/6, 2018 at 9:9 Comment(1)
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.Luthanen
S
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

Swarth answered 25/2, 2020 at 16:27 Comment(2)
This works for me! Tested on Windows Nano Server 1909Observe
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\""Mv
P
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 :)

Parthinia answered 6/7, 2021 at 16:5 Comment(1)
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\")Spenserian
P
0

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

ENV PATH="$WindowsPATH;C:\Foo\bin"
Proliferation answered 29/7, 2022 at 12:47 Comment(1)
For me the PATH variable looks like this afterwards: ;C:\Foo\bin. It seems like you cannot access the current PATH/WindowsPATH variable within the ENV command.Lamelliform
E
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)
Eel answered 3/2, 2023 at 15:23 Comment(0)
C
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.
Coltun answered 29/3, 2023 at 10:49 Comment(0)
M
0

i have used mirsik solution.
My problem was that I had directories with spaces and unknown version numbers.

Ex: "C:\Program Files\Prog\Vers_*\bin"

this was the solution for my problem:

  1. navigate to the directory and create a symbolic link from the destination folder and put it to a reachable place (C:)

RUN powershell -Command "cd 'C:\Program Files\Prog\Vers_*\bin';$path = (Get-Location).Path; New-Item -ItemType SymbolicLink -Path 'C:\' -Name 'Prog.lnk' -Target $path"

  1. add the symbolic link to PATH

RUN setx /M PATH "%PATH%;C:\Prog.lnk\"

It's not a pretty workflow, but it worked for me....

Melodious answered 27/10, 2023 at 6:35 Comment(0)
H
0

My solution works. I hope you can be inspired by the example code below where I installed the Gitlab release-cli into my Windows docker image.

# escape=`

FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

# ... # Here you add your other business logic

# Install Gitlab release-cli
ARG RELEASE_CLI_URL="https://gitlab.com/gitlab-org/release-cli/-/releases/v0.16.0/downloads/bin/release-cli-windows-amd64.exe"
ARG RELEASE_CLI_LOCATION="C:\GitLab\Release-CLI\bin"
ADD $RELEASE_CLI_URL "$RELEASE_CLI_LOCATION\release-cli.exe"
# Add the path of release-cli.exe to the environment variable PATH in Windows
RUN $NEW_PATH = '{0};{1}' -f $RELEASE_CLI_LOCATION, $env:PATH ; `
    [Environment]::SetEnvironmentVariable('PATH', $NEW_PATH, [EnvironmentVariableTarget]::Machine)
Hexarchy answered 20/12, 2023 at 21:57 Comment(0)
I
0

I hit this issue too when trying to get nodejs installed on a windows container.

This is what eventually got my path working

FROM mcr.microsoft.com/windows/nanoserver:ltsc2022
ARG NODE_PATH="C:\Program Files\nodejs"

# add node to PATH
ENV PATH "C:\Windows\System32;${NODE_PATH}"

and when trying to use powershell (pwsh.exe) with nanoserver this worked for me too

FROM mcr.microsoft.com/powershell:lts-7.2-nanoserver-ltsc2022
ARG NODE_PATH="C:\Program Files\nodejs"

# add node to PATH
ENV PATH "C:\Windows\system32;C:\Program Files\PowerShell;${NODE_PATH}"

CMD ["pwsh.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]

Here is the full working docker file https://gist.github.com/pflannery/9144abad685f3cf722a6213bfcb1fc59

Interactive answered 16/6 at 5:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.