Code Monkey home page Code Monkey logo

Comments (7)

jterry75 avatar jterry75 commented on May 19, 2024

@jhowardmsft - I believe this is a known issue but can you confirm?

from docker-powershell.

jterry75 avatar jterry75 commented on May 19, 2024

Oh. I misread. I believe the issue is that you cant pass the params to docker like that. The REST API is a bit different from the CLI in that it does some fancy parsing. You really need to execute:

Start-ContainerProcess -ContainerIdOrName first -Command @("powershell", "(dir c:)")

@swernli - Can you confirm that you always have to separate args in PS execution?

from docker-powershell.

artisticcheese avatar artisticcheese commented on May 19, 2024

So -Command parameter always expects string[2] where first element is executable and second one is parameter?

from docker-powershell.

jterry75 avatar jterry75 commented on May 19, 2024

@swernli - Bump for the holidays

from docker-powershell.

swernli avatar swernli commented on May 19, 2024

@jterry75 @artisticcheese This one is a bit weird, so bear with me. The short explanation is that docker expects the command parameter in their JSON to be the array of tokenized strings for the command you want to execute, so it can be an array of any length. What you are doing above works, since the items in the parens can be considered one token. Another command that has several tokens, such as "cmd /c echo test" could be represented as "cmd","/c echo test" or "cmd","/c","echo","test" and I believe either would work. Alternatively, when using the cmdlet, you could forgo the explicit -Command and just make sure your command is the last parameter provided, and then just type it normally on the commandline (with proper escapes for any powershell characters like "-"). For example:
> Run-ContainerImage microsoft/nanoserver powershell echo test
This method has some big conveniences and some annoying quirks, and understanding them requires the longer explanation...

Cmdlets that include the Command parameter have it decorated with ValueFromRemainingArguments = true as you can see at https://github.com/Microsoft/Docker-PowerShell/blob/master/src/Docker.PowerShell/Cmdlets/StartContainerProcess.cs#L20. What this means is that if the -Command parameter name is not explicitly provided, then powershell will just populate the command from whatever elements are left at the end of the cmdlet invocation after processing all other parameters. This is as close as we could get to the behavior of the docker CLI, which relies on the tokenizing of the shell it executes in for translating input from the user into a string array. If we had made the Command parameter a single string instead of string[] then we would have to tokenize it ourselves, and that would be a pretty complex bit of code. Unfortunately, ValueFromRemainingArguments uses powershell’s cmdline logic, which means extra escape characters may have to used to differentiate between elements you want powershell to evaluate and elements that should be passed along as-is to the parameter. Your use of parenthesis above is a good example, in fact. If I try to use the remaining arguments trick for that, I get an error:
PS > Run-ContainerImage microsoft/nanoserver -Isolation HyperV -RemoveAutomatically powershell (dir c:\)
Invoke-ContainerImage : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Command'.
Specified method is not supported.
At line:1 char:1
+ Run-ContainerImage microsoft/nanoserver -Isolation HyperV -RemoveAuto ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-ContainerImage], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Docker.PowerShell.Cmdlets.InvokeContainerImage
This is because powershell, when it sees the (dir c:\), actually evaluates it and tries to insert the resulting array of objects as an item into the Command string array. What you really want is powershell to ignore the parenthesis and just pass them through as tokens instead of evaluating them, so you have to escape them using a backtick:
PS C:\Windows\system32> Run-ContainerImage microsoft/nanoserver -Isolation HyperV -RemoveAutomatically powershell `(dir c:\`)
This will produce the correct result. The same would have to be done with the "-" and "$" characters to prevent the host powershell window from trying to interpret them.

It's not pretty, but it's the closest we could get to something that would allow callers to write container commands without having to manually tokenize the command in a string array themselves.

from docker-powershell.

artisticcheese avatar artisticcheese commented on May 19, 2024

Damn, I hoped going to powershell route on managing lifecycle of container instead of relying on ugly "docker" commands will prevent what you just described above happening. But seems this UNIX born theater followed to powershell wrapper as well.

from docker-powershell.

swernli avatar swernli commented on May 19, 2024

Yeah, it's definitely annoying. If there were some generic tokenize function in .NET somewhere, we might have been able to use that and simplify this, but we couldn't find anything. And tokenizing input is an annoying problem, especially when you factor in how many special characters may or may not change the behavior and the fact that which characters are considered special changes between shells and platforms. So both docker CLI and cmdlet take the same approach: punt the problem to the shell itself, and let the user figure out how to say what they mean.

I've run into the same problem when executing cmd commands from within powershell and vice versa; in general, interop between multiple shell paradigms is not well solved, and containers bring that to the forefront due to the desire to specify a command within another command.

from docker-powershell.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.