Unable to consume ARG or ENV variables in RUN commands

I am attempting to consume ARG or ENV variables from a RUN or CMD statement on Docker in Windows Server 2016, but no matter what I try, the variable is never interpolated. Take this Dockerfile for example:

FROM microsoft/windowsservercore

ARG azureArchive="Microsoft.Azure.ServiceFabric.WindowsServer.5.3.311.9590.zip"

SHELL ["powershell", "-command"]

# This works, ${azureArchive} is interpolated to the above value
ADD ${azureArchive} /

# This one doesn't, ${azureArchive} is always treated literally
RUN Expand-Archive ${azureArchive} $env:temp\AzureServiceFabric

# additionally, how can I set WORKDIR from a Powershell variable?
#WORKDIR $env:temp\AzureServiceFabric

I’ve tried this with both Powershell and CMD- the result is the same. Any help would be greatly appreciated.

1 Like

A simple test works for me:

C:\code\repros\win-arg-env> cat .\Dockerfile
FROM microsoft/nanoserver

SHELL ["powershell", "-command"]

ARG foo=bar

RUN echo $Env:foo
C:\code\repros\win-arg-env> docker build --no-cache -t win-arg-env .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM microsoft/nanoserver
 ---> 787d9f9f8804
Step 2/4 : SHELL powershell -command
 ---> Running in 561248e5b034
 ---> 3f3d73723742
Removing intermediate container 561248e5b034
Step 3/4 : ARG foo=bar
 ---> Running in b5fc507ca1fa
 ---> 36bc6bf2763e
Removing intermediate container b5fc507ca1fa
Step 4/4 : RUN echo $Env:foo
 ---> Running in 44674c5c5d65
 ---> 53fdcd8ad1ba
Removing intermediate container 44674c5c5d65
Successfully built 53fdcd8ad1ba

Okay clearly I misunderstood something here. You’re accessing the Dockerfile ARG “foo” from $env:foo, instead of $foo. $env is Powershell, so how’d it get populated? Is that what ARG is actually doing: populating a Shell variable?

I just tried the same script using the default Windows shell and I was able to echo %foo%. I thought it was Docker performing the substitution. Rather, Docker just exposes the variable to the current shell.

Thank you for clearing this up!


It seems that you must use $env:arg or %arg% when using powershell or cmd, but you must use $arg when using docker commands.

C:\>cat .\Dockerfile
FROM microsoft/nanoserver
ARG foo=bar
RUN echo %foo%
RUN mkdir %foo%
RUN cd
C:\>docker build --no-cache -t win-arg-env .
Sending build context to Docker daemon  21.32MB
Step 1/6 : FROM microsoft/nanoserver
 ---> 2bee0eeea2d3
Step 2/6 : ARG foo=bar
 ---> Running in 5c8973d0ad31
Removing intermediate container 5c8973d0ad31
 ---> 4ad0d9867da2
Step 3/6 : RUN echo %foo%
 ---> Running in a09ce99260f9
Removing intermediate container a09ce99260f9
 ---> 2338fdc53445
Step 4/6 : RUN mkdir %foo%
 ---> Running in 2b27b9678c4a
Removing intermediate container 2b27b9678c4a
 ---> 1b6c6424f97c
Step 5/6 : WORKDIR $foo
Removing intermediate container a2d9fbc2c54e
 ---> 010f823cc576
Step 6/6 : RUN cd
 ---> Running in f3831f891f8e
Removing intermediate container f3831f891f8e
 ---> cde9c8901355
Successfully built cde9c8901355

Also the ARG command must come after the FROM command.