ARG substitution in RUN command not working for Dockerfile
DockerDockerfileDocker Problem Overview
In my Dockerfile I have the following:
ARG a-version
RUN wget -q -O /tmp/alle.tar.gz http://someserver/server/$a-version/a-server-$a-version.tar.gz && \
mkdir /opt/apps/$a-version
However when building this with:
--build-arg http_proxy=http://myproxy","--build-arg a-version=a","--build-arg b-version=b"
Step 10/15 : RUN wget...
is shown with $a-version
in the path instead of the substituted value and the build fails.
I have followed the instructions shown here but must be missing something else.
> My questions is, what could be causing this issue and how can i solve > it?
Docker Solutions
Solution 1 - Docker
Another thing to be careful about is that after every FROM
statements all the ARG
s get collected and are no longer available. Be careful with multi-stage builds.
You can reuse ARG
with omitted default value inside FROM
to get through this problem:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
Example taken from docs: https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
Solution 2 - Docker
Don't use -
in variable names.
Docker build will always show you the line as is written down in the Dockerfile, despite the variable value.
So use this variable name a_version
:
ARG a_version
See this example:
Dockerfile:
FROM alpine
ARG a_version
RUN echo $a_version
Build:
$ docker build . --build-arg a_version=1234
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM alpine
---> a41a7446062d
Step 2/3 : ARG a_version
---> Running in c55e98cab494
---> 53dedab7de75
Removing intermediate container c55e98cab494
Step 3/3 : RUN echo $a_version <<< note this <<
---> Running in 56b8aeddf77b
1234 <<<< and this <<
---> 89badadc1ccf
Removing intermediate container 56b8aeddf77b
Successfully built 89badadc1ccf
Solution 3 - Docker
I had the same problem using Windows containers for Windows.
Instead of doing this (Which works in linux containers)
FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"
You need to do this
FROM mcr.microsoft.com/windows/servercore
ARG TARGETPLATFORM
RUN echo "I'm building for %TARGETPLATFORM%"
Just change the variable resolution according to the OS.
Solution 4 - Docker
I spent much time to have the argument substitution working, but the solution was really simple. The substitution within RUN
needs the argument reference to be enclosed in double quotes.
ARG CONFIGURATION=Debug
RUN dotnet publish "Project.csproj" -c "$CONFIGURATION" -o /app/publish
Solution 5 - Docker
The only way I was able to substitute an ARG in a Windows Container was to prefix with $env:
, as mentioned here.
An example of my Dockerfile is below. Notice that the ARG PAT
is defined after the FROM so that it's in scope for its use in the RUN nuget sources add
command (as Hongtao suggested). The only successful way I found to supply the personal access token was using $env:PAT
FROM mcr.microsoft.com/dotnet/framework/sdk:4.7.2 AS build
WORKDIR /app
ARG PAT
# copy csproj and restore as distinct layers
COPY *.sln .
COPY WebApi/*.csproj ./WebApi/
COPY WebApi/*.config ./WebApi/
RUN nuget sources add -name AppDev -source https://mysource.pkgs.visualstudio.com/_packaging/AppDev/nuget/v2 -username usern -password $env:PAT
RUN nuget restore
# copy everything else and build app
COPY WebApi/. ./WebApi/
WORKDIR /app/WebApi
RUN msbuild /p:Configuration=Release
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.7.2 AS runtime
WORKDIR /inetpub/wwwroot
COPY --from=build /app/WebApi/. ./
The actual Docker command looks like this:
docker build --build-arg PAT=mypatgoeshere -t webapi .
Solution 6 - Docker
I had the same problem accessing build-args
in my RUN
command. Turns out that the line containing the ARG
definition should not be the first line. The working Dockerfile
snippet looks like this:
FROM centos:7
MAINTAINER xxxxx
ARG SERVER_IPS
Earlier, I had placed the ARG
definition as the first line of Dockerfile
. My docker version is v19.
Solution 7 - Docker
For me it was argument's order:
docker build . -f somepath/to/Dockerfile --build-arg FOO=BAR
did not work, but:
docker build --build-arg FOO=BAR . -f somepath/to/Dockerfile
did.
Solution 8 - Docker
There are many answers, which make sense. But the main thing is missed.
The way, how to use build arguments depends on the base image.
- For Linux image, it will work with
$ARG
- For Windows, depending on image, it can be either
$env:ARG
(e.g. for mcr.microsoft.com/dotnet/framework/sdk:4.8) or %ARG% (e.g. for mcr.microsoft.com/windows/nanoserver:1809)