macetw
macetw

Reputation: 1820

Appending to PATH in a Windows Docker container

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)

Upvotes: 44

Views: 49445

Answers (12)

saviashan
saviashan

Reputation: 1

I faced with the same issue when trying to get dotnet and git paths added into the %PATH% on servercore:2019 Was able overcome it by

RUN cmd /C "setx /M PATH \"%PATH%;C:\\Program Files\\Git\\cmd;C:\\Program Files\\dotnet\""

Upvotes: 0

Peter
Peter

Reputation: 89

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

Upvotes: 0

Cary
Cary

Reputation: 404

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)

Upvotes: 1

UBIDA
UBIDA

Reputation: 1

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....

Upvotes: 0

Arutsudar Arut
Arutsudar Arut

Reputation: 513

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.

Upvotes: 0

TrojanName
TrojanName

Reputation: 5365

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)

Upvotes: 1

bgh
bgh

Reputation: 2120

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

ENV PATH="$WindowsPATH;C:\Foo\bin"

Upvotes: 0

user3615613
user3615613

Reputation: 71

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 :)

Upvotes: 4

Mark Nguyen
Mark Nguyen

Reputation: 7448

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

Upvotes: 10

cherishty
cherishty

Reputation: 403

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

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

Upvotes: 11

mirsik
mirsik

Reputation: 1091

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"

Upvotes: 70

cer49152
cer49152

Reputation: 141

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

Upvotes: 14

Related Questions