ARG

指令


ARG <name>[=<default value>]

描述

ARG 构建参数,主要是在 build 构建镜像过程中使用。Dockerfile 中的 ARG 指令定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 ` –build-arg <参数名>=<值>` 来覆盖修改。

在 Docker 1.13 之前的版本,要求 --build-arg 中使用的参数名,必须在 Dockerfile 中用 ARG 定义过了;换句话说,就是 --build-arg 指定的参数,必须在 Dockerfile 中定义了,如果对应参数没有定义,则会报错退出构建。从 1.13 开始,这种严格的限制被放开,不再报错退出,而是显示警告信息,并继续构建。这对于使用 CI 系统,用同样的构建流程构建不同的 Dockerfile 的时候比较有帮助,避免构建命令必须根据每个 Dockerfile 的内容修改。

ARG 构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会保存在这些环境变量的。但不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。

Dockerfile 中包含一个或多个ARG指令。例如,以下是有效的Dockerfile:


FROM busybox

ARG user1

ARG buildno...

ARG 默认值

ARG指令可以可选地包括一个默认值:


FROM busybox

ARG user1=someuser

ARG buildno=1...

如果 ARG 指令具有默认值,并且在构建时未传递任何值,那么构建器将使用该默认值。

预定义的 ARG

Docker 具有一组预定义 ARG 变量,可以在没有定义的情况下使用这些 变量

  • HTTP_PROXY

  • http_proxy

  • HTTPS_PROXY

  • https_proxy

  • FTP_PROXY

  • ftp_proxy

  • NO_PROXY

  • no_proxy

要使用这些参数,只需使用以下标志在命令行中传递它们即可:


--build-arg <varname>=<value>

默认情况下,这些预定义变量不会出现在 docker history 的输出中,这样可以降低意外泄露 HTTP_PROXY 变量中的敏感身份验证信息的风险。

例如,可以考虑使用以下命令构建以下 Dockerfile


--build-arg HTTP_PROXY=http://user:pass@proxy.lon.example.com

Dockerfile文件:


FROM ubuntuRUN echo "Hello World"

在这种情况下,HTTP_PROXY 变量的值在不会显示在 docker history 中,也不会被缓存。

如果要更改配置,比如代理服务器已更改为 http://user:pass@proxy.sfo.example.com,后续的构建也不会获取到之前的缓存信息。

如果您需要覆盖此默认的行为,则可以通过在 Dockerfile 中添加 ARG 的 如下语句来做到这一点:


FROM ubuntu

ARG HTTP_PROXY

RUN echo "Hello World"

构建此 Dockerfile 时,HTTP_PROXY 会保留在 docker history 中。

ARG 范围

ARG 具有一定的范围。例如,考虑以下Dockerfile:


FROM busybox

USER ${user:-some_user}

ARG user

USER $user...

用户通过调用以下命令来构建此文件:


$ docker build --build-arg user=what_user .

第2行的 USER 的值为 some_user,因为 user 变量在第3行才定义。第4行的USER值为 what_user,因为user变量在它之前定义了并且在命令行给user变量赋值为 what_user。在 ARG 指令定义变量之前引用这个变量的,都会得到空值。即第二行是无效的,因为在第二行时没有声明user变量,无法使用。

ARG 对缓存的影响

ARG 变量不像 ENV 变量始终存在于镜像中。不过 ARG 变量会以类似的方式对构建缓存产生影响。如果 Dockerfile 中定义的 ARG 变量的值与之前定义的变量值不一样,那么就有可能产生“cache miss”。比如RUN指令使用ARG定义的变量时,ARG变量的值变了之后,就会导致缓存失效,即无法获取到该变量。

例如,考虑以下两个Dockerfile:


FROM ubuntu

ARG CONT_IMG_VER

RUN echo $CONT_IMG_VER


FROM ubuntu

ARG CONT_IMG_VER

RUN echo hello

如果 --build-arg CONT_IMG_VER=<value> 在命令行上指定,则在两种情况下,第2行上的指定都不会导致高速缓存未命中。第3行确实会导致缓存未命中。ARG CONT_IMG_VER 导致RUN行被标识为与正在运行的CONT_IMG_VER=<value>echo hello 相同,因此,如果进行了 更改,则会遇到缓存未命中的情况。

考虑同一命令行下的另一个示例:


FROM ubuntu

ARG CONT_IMG_VER

ENV CONT_IMG_VER $CONT_IMG_VER

RUN echo $CONT_IMG_VER

在此示例中,高速缓存未命中发生在第3行。之所以发生未命中,是因为变量中的变量值ENV引用了该ARG变量,并且该变量是通过命令行更改的。在此示例中,该ENV 命令使 image镜像 包含该值。

如果一条ENV指令覆盖ARG了同名的一条指令,例如Dockerfile:


FROM ubuntu

ARG CONT_IMG_VER

ENV CONT_IMG_VER hello

RUN echo $CONT_IMG_VER

第3行不会导致缓存未命中,因为值 CONT_IMG_VER 是一个常量(hello)。结果,RUN(第4行)使用的环境变量和值在两次构建之间不会改变。

使用ARG变量

可以使用ARG或ENV指令指定可用于RUN指令的变量。使用ENV定义的环境变量始终会覆盖同一名称的ARG指令定义的变量。例如:


FROM ubuntu

ARG CONT_IMG_VER

ENV CONT_IMG_VER v1.0.0

RUN echo $CONT_IMG_VER

然后,假定此映像是使用以下命令构建的:


$ docker build --build-arg CONT_IMG_VER=v2.0.1 .

在这种情况下,该RUN指令将使用v1.0.0而不是ARG用户传递的设置:v2.0.1

此行为类似于Shell脚本,其中局部作用域的变量从其定义的角度覆盖作为参数传递或从环境继承的变量。

使用上面的示例,但使用不同的ENV规范,可以在ARG和ENV指令之间创建更有用的交互:


FROM ubuntu

ARG CONT_IMG_VER

ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}

RUN echo $CONT_IMG_VER

与ARG指令不同,ENV值始终保留在生成的映像中。考虑不带 –build-arg 标志的Docker构建:


$ docker build .

使用此 Dockerfile 示例,CONT_IMG_VER 它仍然保留在映像中,但其值将是指令v1.0.0第3行中的默认设置ENV。

在此示例中,变量扩展技术使您可以从命令行传递参数,并利用 ENV 指令将其保留在最终映像中 。仅有限的一组 Dockerfile 指令支持变量扩展。

全局范围内的平台自动化ARG

仅当使用BuildKit后端时,此功能才可用。

Docker ARG 在执行构建的节点的平台(构建平台)和结果映像的平台(目标平台)上用信息预定义了一组变量。可以使用–platform标志on 来指定目标平台docker build。

以下ARG变量是自动设置的:

  • TARGETPLATFORM-构建结果的平台。例如 linux/amd64,linux/arm/v7,windows/amd64。

  • TARGETOS -TARGETPLATFORM的OS组件

  • TARGETARCH -TARGETPLATFORM的体系结构组件

  • TARGETVARIANT -TARGETPLATFORM的变体组件

  • BUILDPLATFORM -执行构建的节点的平台。

  • BUILDOS -BUILDPLATFORM的OS组件

  • BUILDARCH -BUILDPLATFORM的OS组件

  • BUILDVARIANT -BUILDPLATFORM的OS组件

这些参数是在全局范围内定义的,因此不会在构建阶段或您的RUN命令中自动提供。为了在构建阶段公开这些参数之一,请重新定义它而没有价值。

例如:


FROM alpine

ARG TARGETPLATFORM

RUN echo "I'm building for $TARGETPLATFORM"