无论何种编程语言或脚本中,都不可避免的会应用到变量。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 变量应用
· 可以使用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
指令使用ENV
指令定义的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 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
定义的变量被使用,在更改变量的值时,就会发生缓存未命中这种情况。
总结
ARG
与ENV
指令有些相似,ARG
是定义普通变量,ENV
定义环境变量,环境变量比普通变量的作用域范围更大,具体示例也可以参见ENV
的博文,地址为Dockerfile ENV指令 语法解析,本文就不对ARG
进行举例演示了,其应用形式相对比较简单,但是其应用规范还是需要了解的,以免应用时出现不必要的问题。
若文中存在错误和不足,欢迎指正!