RUN 命令中的 ARG 替换对 Dockerfile 不起作用

在我的 Dockerfile 文件中,我有以下内容:

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

然而,当使用以下方法构建这个过程时:

--build-arg http_proxy=http://myproxy","--build-arg a-version=a","--build-arg b-version=b"

在路径中用 $a-version代替替换值显示 Step 10/15 : RUN wget...,构建失败。

我已经按照指示显示的 给你,但必须缺少其他东西。

我的问题是,是什么导致了这个问题,我该怎么解决 它?

60249 次浏览

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

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

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.

Another thing to be careful about is that after every FROM statements all the ARGs 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

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 .

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.

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.

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)