Docker Community Forums

Share and learn in the Docker community.

SHELL ["powershell", "-Command"] and quote issues


(Awsteele) #1

So I was very excited to see native Docker support in Windows Server 2016. I created a Dockerfile similar to the following and ran into a bit of trouble:

# escape=`
FROM microsoft/nanoserver
SHELL ["powershell", "-Command"]

RUN Add-Content C:\path\to\file.txt "This is my message"

It exploded :frowning: because of the quotes. This is the output:

docker build .
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM microsoft/nanoserver
 ---> e14bc0ecea12
Step 2/3 : SHELL powershell -Command
 ---> Running in 69e4802ba983
 ---> ef2271e9628a
Removing intermediate container 69e4802ba983
Step 3/3 : RUN Add-Content C:\path\to\file.txt "This is my message"
 ---> Running in ed88985731db
Add-Content : A positional parameter cannot be found that accepts argument 
'is'.
At line:1 char:1
+ Add-Content C:\path\to\file.txt This is my message
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Add-Content], ParameterBin 
   dingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell 
   .Commands.AddContentCommand
 
The command 'powershell -Command Add-Content C:\path\to\file.txt "This is my message"' returned a non-zero code: 1

What can be done about this? I can escape the quotes, but it’s ugly and feels like I shouldn’t need to do that. Single quotes aren’t always an option because I’d like to make use of string interpolation.

Any pointers / tips?

EDIT: Interestingly, the Dockerfile reference for the SHELL command switches from using double quotes to single quotes in its examples. Is this a known issue?


(Awsteele) #2

Some further research / notes that may help: When I compile the following program as app.exe and then use SHELL ["app.exe"], everything works: the quotes don’t disappear and the RUN command works just fine. But of course this is a hack and it’d be great if I didn’t have to do this.

using System;
using System.Diagnostics;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var startInfo = new ProcessStartInfo {
                FileName = "powershell.exe",
                Arguments = "-Command - ",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                RedirectStandardInput = true,
            };

            var process = new Process {
                StartInfo = startInfo,
            };

            process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
            process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);
            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            var cmd = Environment.CommandLine.Substring(7);
            var inp = process.StandardInput;
            inp.WriteLine(cmd);
            inp.Close();

            process.WaitForExit();
        }
    }
}

(Spencerjohnson627) #3

Use “powershell.exe” instead of “powershell”.