当前位置: 首页 > 工具软件 > arg > 使用案例 >

Dockerfile ARG指令 语法解析

慕宏博
2023-12-01

  无论何种编程语言或脚本中,都不可避免的会应用到变量。dockerfile中使用ARG来定义变量,本文来对ARG指令定义变量进行解析。

  ARG 语法:

ARG <name>[=<default value>]

  ARG 语义:

  · ARG指令用于定义一个变量,可以使用--build-arg <varname>=<value>标志在构建时通过docker build命令传递给构建器。

  · 如果指定的构建参数未在dockerfile中定义,则构建将输出警告。

[Warning] One or more build-args [foo] were not consumed.

  · dockerfile可以包含一个或多个ARG指令。例如:

FROM busybox
ARG user1
ARG buildno
# ...

  · 不建议使用构建时变量来传递诸如github密钥、用户凭据等机密信息。因为使用docker history命令,镜像的任何用户都可以看到构建时的变量值。

  ARG 默认值:

  · ARG指令可以选择包含默认值:

FROM busybox
ARG user1=someuser
ARG buildno=1
# ...

  ·ARG指令具有默认值,并且在构建时没有传递值,则构建器将使用默认值。

  ARG 作用域:

  · ARG定义的变量从dockerfile定义行开始生效,并不是从使用变量行或其他位置开始。

FROM busybox
USER ${user:-some_user}
ARG user
USER $user
# ...

  使用如下命令构建:

docker build --build-arg user=what_user .

  ARG 变量应用

  · 可以使用ARGENV指令为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指令使用ENV指令定义的v1.0.0代替ARG指令定义的v2.0.1,这种行为类似于shell脚本,本地变量会覆盖传递参数或继承环境变量。

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

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 build .

  上例中,CONT_IMG_VER仍然会保存在构建的镜像中,但是它的值会在第三行被设置为默认值v1.0.0

  通过命令行传递参数,利用ENV指令的作用,将参数保存到构建的镜像中。

  预定义参数

  Docker提供了一些预定义参数,无需通过ARG定义,即可使用

HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy

  使用它们的方式,和其他变量一样,在命令行中传递参数。

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

  默认情况下,预定义参数不会包括在docker history的输出中。排除它们的目的是为了降低泄漏敏感信息的危险。

--build-arg HTTP_PROXY=http://user:pass@proxy.lon.example.com
FROM ubuntu
RUN echo "Hello World"

  上例中,HTTP_PROXY变量的值不会在docker history中输出,并且不会缓存。

  如果要改变预定义参数的这种行为,可以在dockerfile中定义同名变量,覆盖预定义变量,使其与普通变量拥有同样行为。

FROM ubuntu
ARG HTTP_PROXY
RUN echo "Hello World"

​  构建dockerfile时,HTTP_PROXY会保存在docker history中,更改它的值会导致缓存失效。

  构建缓存影响

  ARG变量不会像ENV变量一样保存到构建镜像中,ARG变量会影响构建缓存。

  如果dockerfile定义一个与已有同名不同值的变量,第一次使用时会导致缓存为命中。特别是,在ARG指令之后的所有RUN指令都隐式使用ARG变量(作为环境变量),因此可能导致缓存未命中。除非dockerfile中有匹配的ARG语句,否则所有预定义的ARG变量都不会被缓存。

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>,变更的值进行构建时,会导致缓存未命中。缓存未命中会发生在第三行。

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=$CONT_IMG_VER
RUN echo $CONT_IMG_VER

  上例中,缓存未命中会发生在第三行。

  总之,只要是ARG定义的变量被使用,在更改变量的值时,就会发生缓存未命中这种情况。

  总结

  ARGENV指令有些相似,ARG是定义普通变量,ENV定义环境变量,环境变量比普通变量的作用域范围更大,具体示例也可以参见ENV的博文,地址为Dockerfile ENV指令 语法解析,本文就不对ARG进行举例演示了,其应用形式相对比较简单,但是其应用规范还是需要了解的,以免应用时出现不必要的问题。

  若文中存在错误和不足,欢迎指正!

 类似资料: