1

I am following https://docs.docker.com/get-started/06_bind_mounts/#start-a-dev-mode-container on a Windows PC and am stuck here:

Run the following command. We’ll explain what’s going on afterwards:

 docker run -dp 3000:3000 \
     -w /app -v "$(pwd):/app" \
     node:12-alpine \
     sh -c "yarn install && yarn run dev"

If you are using PowerShell then use this command:

 docker run -dp 3000:3000 `
     -w /app -v "$(pwd):/app" `
     node:12-alpine `
     sh -c "yarn install && yarn run dev"

When using Command Prompt, I get errors (tried multiple variations as shown below), and when using PowerShell, I don't appear to get errors but am not running anything as showed when executing docker ps. Note that I would rather use Command Prompt and not PowerShell as I could use Linux commands with ComandPrompt on my PC.

What is the significance of backslashes when using Dockers with Command Prompt (and tick marks with PowerShell for that matter)?

I have since found that docker run -dp 3000:3000 -w /app -v "%cd%:/app" node:12-alpine sh -c "yarn install && yarn run dev" works without errors (got rid of backslashes, put on one line, and used %cd% instead of $(pwd)), but would still like to know why using the exact script in the example results in errors.

Using Command Prompt

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 \
docker: invalid reference format.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>     -w /app -v "$(pwd):/app" \
'-w' is not recognized as an internal or external command,
operable program or batch file.

C:\Users\michael\Documents\Docker\app>     node:12-alpine \
The filename, directory name, or volume label syntax is incorrect.

C:\Users\michael\Documents\Docker\app>     sh -c "yarn install && yarn run dev"
sh: yarn: command not found

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 \ -w /app -v "$(pwd):/app" \ node:12-alpine \ sh -c "yarn install && yarn run dev"
docker: invalid reference format.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 -w /app -v "$(pwd):/app" node:12-alpine sh -c "yarn install && yarn run dev"
docker: Error response from daemon: create $(pwd): "$(pwd)" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>

Using PowerShell

PS C:\Users\michael\Documents\Docker>  docker run -dp 3000:3000 `
>>      -w /app -v "$(pwd):/app" `
>>      node:12-alpine `
>>      sh -c "yarn install && yarn run dev"
849af42e78d4ab09242fdd6c3d03bcf1b6b58de984c4485a441a2e2c88603767
PS C:\Users\michael\Documents\Docker> docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS C:\Users\michael\Documents\Docker>
mklement0
  • 382,024
  • 64
  • 607
  • 775
user1032531
  • 24,767
  • 68
  • 217
  • 387
  • Unclear what you mean by "use Linux commands in command prompt"... But you'll need to look at `docker logs` to know why the container is actually failing (probably something bad in the yarn process) – OneCricketeer Aug 16 '21 at 03:50
  • @OneCricketeer, When installing git, installed tools to allow me to use `ls -l` instead of `dir`. – user1032531 Aug 16 '21 at 13:15
  • 1
    Sounds like you're using "Git Bash", which is not CMD. Basically, I'd consider that deprecated in favor of WSL2 overall – OneCricketeer Aug 16 '21 at 15:59
  • @OneCricketeer Yes I was. Through it might be causing problems (unfortunately it wasn't the culprit) but couldn't remember what it was called until seeing your comment. Will checkout WSL2. Thanks – user1032531 Aug 17 '21 at 11:57

2 Answers2

7

would still like to know why using the exact script in the example results in errors.

Because the command with the line-ending \ characters is meant for POSIX-compatible shells such as bash, not for cmd.exe

  • POSIX-compatible shells (sh, bash, dash, ksh, zsh):

    • use \ for line-continuation (continuing a command on the following line) and escaping in general.
    • use $varName to reference both environment and shell-only variables.
    • support $(...) for embedding the output from a command (...) in command lines (command substitution).
    • support both double-quoted ("...", interpolating) and single-quoted ('...', verbatim) strings; use '\'' to - in effect - include a ' inside '...'.
      (Additionally, in bash, ksh, and zsh, there are the rarely used ANSI C-quoted strings, $'...', and, in bash and ksh, perhaps even more rarely, localizable strings, $"...").
  • cmd.exe:

    • uses ^ for line-continuation and escaping in general (in unquoted arguments only).
    • uses %varName% to reference environment variables (the only variable type supported).
    • doesn't support command substitutions at all.
    • supports only "..." strings (interpolating).
  • PowerShell:

    • uses ` (the backtick) for line-continuation and escaping in general.
    • uses $env:varName to reference environment variables, $varName to reference shell-only variables.
    • supports $(...), called subexpressions, the equivalent of command substitutions (outside of double-quoted strings, (...) is usually sufficient).
    • supports both double-quoted ("...", interpolating) and single-quoted ('...', verbatim) strings; use '' to embed a ' inside '...'.
    • Note: A common pitfall is that PowerShell has more metacharacters compared to both POSIX-compatible shells and cmd.exe, notably including @ { } , ;, which therefore require individual `-escaping in unquoted arguments or embedding in quoted strings - see this answer.

Potential line-continuation pitfall: in all of the shells discussed, the escape character must be the very last character on the line - not even trailing (intra-line) whitespace is allowed (because the escape character would then apply to it rather than to the newline).

The information above is summarized in the following table:

Feature POSIX shells                     _ cmd.exe                     _ PowerShell                     _
Line-continuation / escape character Backslash (\) Caret (^) Backtick (`)
Double-quoted strings (interpolating)
Single-quoted strings (verbatim)
Get / set environment variables $varName /
export varName=...
%varName% /
set varName=...
$env:varName /
$env:varName = ...
Get / set shell-only variables $varName/
varName=...
❌ (no such variables exist, but you can limit the scope of env. vars. with setlocal) $varName/
$varName = ...
Command substitutions, subexpressions $(...) (...) / $(...), esp. in strings

Note re setting variables with respect to whitespace on either side of the = symbol:

  • In POSIX-like shells, there must not be whitespace around =.
  • In cmd.exe, such whitespace is significant and becomes part of the variable / value name, and is therefore usually to be avoided.
  • In PowerShell, such whitespace is optional - you may use it to enhance readability; any string value to be assigned requires quoting (e.g., $var = 'hi!')

See also:

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 3
    Very comprehensive and high quality answer. Especially helpful given the difficulty to search for information for these types of items. Thank you. – user1032531 Aug 16 '21 at 13:11
  • 1
    Wow, you did pretty it up! Ignore my part about input command substitutions as I was confused. – user1032531 Aug 16 '21 at 14:15
  • Got it, @user1032531. I've added a link to https://hyperpolyglot.org/shell, which is a comprehensive juxtaposition of these shells, though note that details are missing, esp. with respect to PowerShell. – mklement0 Aug 16 '21 at 14:29
2

This is character escaping.

The X Character (\ for Bash, backtick for Powershell and ^ for Windows terminal )are used to remove any specific meanings to the next characters.

When used at the end of a line, this mean that the next character (The newline character) is completely ignored.

This keep the command essentially a one-line command from the point of view of the interpreter, but allow you to break it on multiple lines for better readability.

References

Powershell - About special characters

Escape sequences begin with the backtick character [`], known as the grave accent (ASCII 96), and are case-sensitive. The backtick character can also be referred to as the escape character.

Bash manual

3.1.2.1 Escape Character

A non-quoted backslash \ is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline. If a \newline pair appears, and the backslash itself is not quoted, the \newline is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

How-to: Escape Characters, Delimiters and Quotes at the Windows command line

Escaping CR/LF line endings. The ^ escape character can be used to make long commands more readable by splitting them into multiple lines and escaping the Carriage Return + Line Feed (CR/LF) at the end of a line:

ROBOCOPY \\FileServ1\e$\users ^
\\FileServ2\e$\BackupUsers ^
/COPYALL /B /SEC /MIR ^
/R:0 /W:0 /LOG:MyLogfile.txt /NFL /NDL

[...]

A couple of things to be aware of:

A stray space at the end of a line (after the ^) will break the command, this can be hard to spot unless you have a text editor that displays spaces and tab characters. If you want comment something out with REM, then EVERY line needs to be prefixed with REM. Alternatively if you use a double colon :: as a REM comment, that will still parse the caret at the end of a line, so in the example above changing the first line to :: ROBOCOPY… will comment out the whole multi-line command.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39