许多同学不知道Dockerfile应该如何写,不清楚Dockerfile中的指令分别有什么意义,能达到什么样的目的,接下来我将在容器化专栏中详细的为大家解释每一个指令的含义以及用法。
专栏订阅传送门https://blog.csdn.net/qq_38220908/category_11989778.html
指令不区分大小写。但是,按照惯例,它们应该是大写的,以便更容易地将它们与参数区分开来。(引用至官方文档>>>)
![](https://img-blog.csdnimg.cn/4c9a5ebafce44f1d9aef5dcf5030070c.jpeg)
【开发云】年年都是折扣价,不用四处薅羊毛
语法
ARG <name>[=<default value>]
ARG指令用于定义一个变量,用户可以在构建Docker镜像的时候,使用 --build-arg 定义变量的值。比如:
我们新建一个Dockerfile文件,使用ARG定义参数username,这里我们没有赋予默认值
FROM ubuntu
ARG username
RUN echo $username
然后我们使用以下命令构建镜像,我们可以看到RUN echo $username被替换成了RUN echo 清风怎不知意
docker build --build-arg username=清风怎不知意 -t myapp:tag-v0.0.1 .
来自Docker官方的警告:
不建议在构建时使用ARG传递密钥、用户凭证等信息,因为构建时的信息是任何用户都可以通过docker history看到的!!!!!!!!!
我们也可以使用 ARG username=默认姓名 赋予变量默认值。
我们还可以利用ARG指令,声明基础镜像的版本,使其在构建的时候可以通过--build-arg选项对镜像版本进行修改,比如:
Dockerfile
ARG BASE_VERSION=latest
FROM openjdk:$BASE_VERSION
RUN echo $BASE_VERSION
当我们运行命令 docker build . 的时候,没有使用--build-arg 定义BASE_VERSION的值,所以BASE_VERSION取默认值latest,实际拉取的基础镜像版本是 openjdk:latest
当我们运行命令docker build --build-arg BASE_VERSION=11 . 的时候,BASE_VERSION的值为11,所以实际拉取的镜像版本是 openjdk:11
注意:
在FROM指令前使用ARG指令定义的变量,只能用于FROM指令。所以,Dockerfile第三行的 RUN echo $BASE_VERSION指令,并未取到值!!!
作用域
上面的例子我们可以看到,ARG声明的变量是有作用域限制的。接下来我们说说ARG指令定义变量的作用域。
1、与常规变量的定义一样,变量的生效时间,都是在被定义之后。
比如:
Dockerfile
FROM ubuntu
# 定义环境变量
ENV MYENV=test
RUN echo $MYENV
# 覆盖定义的环境变量
ARG MYENV
RUN echo $MYENV
使用以下命令构建镜像文件
docker build --build-arg MYENV=pre -t myapp:tag-v0.0.2 .
运行的结果为:
第一次RUN 指令 echo 的值是test,第二次RUN指令 echo 的值是pre,我们可以看到ARG指令只影响到了其后面的变量值。
如果我们构建镜像的时候,不指定参数值,那么ARG指令声明的MYENV变量的值,会以上面EVN指令定义的值为默认值
docker build -t myapp:tag-v0.0.2 .
可以看到,两次RUN指令echo的值都是与ENV指令定义的值一样的
2、 ARG指令声明的变量在当前构建阶段完成后失效
相当于在函数内声明的变量,只能在该函数内生效。所以在进行多阶段构建时,每个阶段都必须重新使用ARG指令声明变量。
错误使用方式
多阶段构建Dockerfile
FROM ubuntu
ARG SETTINGS=12
RUN echo $SETTINGS
FROM ubuntu
RUN echo $SETTINGS
使用以下命令构建镜像
docker build --no-cache .
我们可以看到,我们在第一阶段声明的SETTINGS参数,在第二阶段构建的时候,SETTINGS未取值
正确使用方式
当我们为第二阶段使用ARG声明参数后,再次构建,可以看到,此时变量SETTINGS的值变为了22 多阶段构建Dockerfile
FROM ubuntu
ARG SETTINGS=12
RUN echo $SETTINGS
FROM ubuntu
ARG SETTINGS=22
RUN echo $SETTINGS
我们可以使用ARG或者ENV指令指定RUN指令可用的变量,但是ENV指令定义的环境变量,会覆盖ARG定义的同名变量
预定义变量
Docker提供以下预定义变量
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
ALL_PROXY
all_proxy
针对以上预定义的变量,我们同样可以使用--build-arg给他们赋值,并且,这些预定义变量不会被docker history所记录,能够相对安全的保护这部分敏感信息。
如果我们需要改变预定义变量的行为,我们可以在Dockerfile中声明同名变量,比如我们在Dockerfile中使用指令 ARG HTTP_PROXY重新声明了预定义变量,这时候,我们在构建镜像的时候,docker history就会记录下它的值,失去对此信息的保护,并且,更改HTTP_PROXY的值会使构建的缓存失效。
[1] 感谢大佬 @kenllf 的斧正
版权归原作者 清风怎不知意 所有, 如有侵权,请联系我们删除。