1

In my dockerfile I have the line

RUN [Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\oracle\instantclient_19_10", "Machine")

I get this returned, even though when I run the above command in PowerShell everything "just works"

At line:1 char:114
+ ...  = 'SilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $e ...
+                                                                  ~
Missing ')' in method call.
At line:1 char:114
+ ... SilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $env:P ...
+                                                              ~~~~
Unexpected token 'Path' in expression or statement.
At line:1 char:118
+ ... ilentlyContinue'; [Environment]::SetEnvironmentVariable(Path, $env:Pa ...
+                                                                 ~
Missing argument in parameter list.
At line:1 char:162
+ ... entVariable(Path, $env:Path + ;C:\oracle\instantclient_19_10, Machine ...
+                                                                 ~
Missing argument in parameter list.
At line:1 char:171
+ ... ntVariable(Path, $env:Path + ;C:\oracle\instantclient_19_10, Machine)
+                                                                         ~
Unexpected token ')' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordEx 
   ception
    + FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
visch
  • 707
  • 5
  • 23

2 Answers2

2

The error message implies two things:

  • PowerShell is configured as your default shell in your dockerfile (by default it is cmd.exe)

  • However, the " characters were stripped from your PowerShell command, which broke it.

Therefore, escape the " character as \":

RUN [Environment]::SetEnvironmentVariable(\"Path\", $env:Path + \";C:\oracle\instantclient_19_10\", \"Machine"\)

Alternatively, you can simply use '-quoting in this case:

RUN [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\oracle\instantclient_19_10', 'Machine')

As for why escaping " as \" is needed:

  • Presumably, what follows RUN is copied as-is to the powershell.exe -Command command line that is used behind the scenes.

  • During PowerShell's command-line parsing, unescaped " characters are removed before the resulting code is interpreted as PowerShell code. Thus, " characters that must be retained as part of the PowerShell code must be \"-escaped.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    I was 100% wrong with my description yours makes much more sense. I had it in my mind that I was already using double quotes in other places in my Dockerfile, but that just wasn't true. Thank you! – visch Oct 20 '22 at 16:14
1

Note: This answer isn't quite correct, check out the accepted answer https://stackoverflow.com/a/74142485/3684640 for the correct reason for why this is happening

This is an unfortunate clash with Docker's two forms of run commands referenced here https://docs.docker.com/engine/reference/builder/#run.

There's shell form:

RUN (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)

And there's exec form

RUN ["executable", "param1", "param2"] (exec form)

In Powershell with the command you're trying to use "[Environment]" is at the beginning which makes Docker think we are in exec form.

A potential fix that works is

RUN ["powershell.exe", "[Environment]::SetEnvironmentVariable(\"Path\", $env:Path + \";C:\\oracle\\instantclient_19_10\", \"Machine\")"]

Which works by using exec form instead of shell form, since this is in json syntax we have to escape all the necessary characters as well.

visch
  • 707
  • 5
  • 23