6

I know that you can pass environment variables to docker-compose.

docker-compose.yml

. . .
mysql:
    image: mariadb:10.2
    ports:
     - "${DB_PORT}:3306"
. . .

$ DB_PORT=3396 docker-compose up

However this only works using bash. I am using PowerShell and am trying to find an equivalent that is only a one line command.

PS> $env:DB_PORT:3306 docker-compose up does not work. Neither does multiline

$env:DB_PORT=3396 `
>> docker-compose -up

The error I get is Unexpected token 'docker-compose' in expression or statement.

If I do it one at a time it does work...

PS> $env:DB_PORT=3396
PS> docker-compose -up

Is there not way to do this in PowerShell when the equivalent in bash is ridiculously simple?

2
  • use the newline characters '`r`n'? Commented Nov 23, 2017 at 1:04
  • 1
    Are you just trying to put two commands on the same line? If so, use ; to separate them e.g. $env:DB_PORT=3396; docker-compose -up Commented Nov 23, 2017 at 2:02

1 Answer 1

6

POSIX-like shells such as bash offer a way to set environment variables in a command-scoped way, simply by prepending <varName>=<value> pairs directly to a command, as the following example demonstrates:

$ foo=bar bash -c 'echo "[$foo]"'; echo "[$foo]"
[bar]
[]

foo=bar defines environment variable foo for the bash -c '...' child process only; the next command - echo ... - does not see this variable.


PowerShell has NO equivalent construct as of v7.4.

To add support in the future with at least similar syntax is the subject of a long-standing feature request, GitHub issue #3316.

For now, the best you can do is to define the environment variable of interest first, in a separate statement, using ;, PowerShell's statement separator. Any external utility you invoke thereafter - which invariably runs in a child process - will see it, but note that the environment variable will remain in effect in the current PowerShell session, unless you manually remove it:

# Set the env. variable, call the command that should see it,
# remove it afterwards.
PS> $env:foo = 'bar'; bash -c 'echo "[$foo]"'; $env:foo = $null
[bar]

Note how $env:foo = $null i.e., setting the environment variable to $null is the same as removing it; alternatively, you could all Remove-Item env:foo

If you also want to restore a pre-existing value afterwards:

$env:foo = 'original'

# Temporarily change $env:foo to a different value, invoke the
# program that should see it, then restore the previous value.
& { $org, $env:foo = $env:foo, 'bar'; bash -c 'echo "[$foo]"'; $env:foo = $org }

$env:foo

The above yields:

[bar]
original

showing that while the bash process saw the temporary value, bar, the original value of $env:foo was restored afterwards.


Also note another important difference:

  • In POSIX-like shells, environment variables are implicitly surfaced as shell variables - they share the one and only namespace the shell has for variables.

  • By contrast, PowerShell surfaces environment variables only via the $env:<varName> namespace (e.g., $env:foo), which is distinct from the (prefix-less) namespace for PowerShell's own variables (e.g., $foo).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.