我将总结来自this 精彩文章的亮点。
ARG 与 ENV
1) 简短说明:
ARG 仅在构建 Docker 映像(RUN 等)期间可用,而不是在创建映像并从其启动容器之后(ENTRYPOINT、CMD)。
ENV 值可用于容器,但在 Docker 构建期间从引入它们的行开始的 RUN 样式命令也可用。
如果您使用 bash (RUN export VARI=5 && ...) 在中间容器中设置环境变量,它将不会在下一个命令中持续存在。
2) 更长的解释:
ARG 也称为构建时变量。它们仅在使用 ARG 指令在 Dockerfile 中“宣布”时才可用,直到构建映像时才可用。正在运行的容器无法访问 ARG 变量的值。这也适用于 CMD 和 ENTRYPOINT 指令,它们只是告诉容器应该默认运行什么。如果您告诉 Dockerfile 需要各种 ARG 变量(没有默认值),但在运行构建命令时没有提供任何变量,则会出现错误消息。
但是,在构建映像后,可以通过查看映像的 docker 历史记录轻松检查 ARG 值。因此,它们对于敏感数据来说是一个糟糕的选择。
ENV 变量在构建过程中也可用,只要您使用 ENV 指令引入它们。但是,与 ARG 不同,它们也可以通过从最终映像启动的容器访问。启动容器时可以覆盖 ENV 值,更多内容见下文。
3) 带图:
以下是围绕从 Dockerfile 构建 Docker 映像和运行容器的过程的 ARG 和 ENV 可用性的简化概述。
它们重叠,但不能从容器内部使用 ARG。
设置 ARG 和 ENV 值
设置 ARG 值
所以,你有你的Dockerfile,它定义了ARG 和ENV 值。如何设置它们,在哪里?您可以在Dockerfile 中将它们留空,或设置默认值。如果您没有为没有默认值的预期 ARG 变量提供值,则会收到错误消息。
这是一个Dockerfile 示例,无论是默认值还是没有默认值:
ARG some_variable_name
# or with a hard-coded default:
#ARG some_variable_name=default_value
RUN echo "Oh dang look at that $some_variable_name"
# you could also use braces - ${some_variable_name}
从命令行构建 Docker 映像时,您可以使用 –build-arg 设置 ARG 值:
$ docker build --build-arg some_variable_name=a_value
使用上面的Dockerfile 运行该命令将导致打印以下行(以及其他):哦,看看那个 a_value
那么,这如何转化为使用docker-compose.yml 文件?
使用 docker-compose 时,您可以在 args 块中为 ARG 指定要传递的值:
(docker-compose.yml 文件)
version: '3'
services:
somename:
build:
context: ./app
dockerfile: Dockerfile
args:
some_variable_name: a_value
当你尝试设置一个不是Dockerfile 中提到的ARG 的变量时,Docker 会报错。
设置 ENV 值
那么,如何设置ENV 值?您可以在启动容器时执行此操作(我们将在下面稍微介绍一下),但您也可以通过硬编码直接在 Dockerfile 中提供默认的 ENV 值。此外,您还可以为环境变量设置动态默认值!
在构建映像时,您唯一可以提供的是ARG 值,如上所述。您不能直接为 ENV 变量提供值。但是,ARG 和 ENV 可以一起工作。您可以使用 ARG 设置 ENV vars 的默认值。
这是一个基本的Dockerfile,使用硬编码的默认值:
# no default value
ENV hey
# a default value
ENV foo /bar
# or ENV foo=/bar
# ENV values can be used during the build
ADD . $foo
# or ADD . ${foo}
# translates to: ADD . /bar
这里是 Dockerfile 的 sn-p,使用动态构建环境值:
# expect a build-time variable
ARG A_VARIABLE
# use the value to set the ENV var default
ENV an_env_var=$A_VARIABLE
# if not overridden, that value of an_env_var will be available to your containers!
构建映像后,您可以启动容器并以三种不同的方式为ENV 变量提供值,无论是从命令行还是使用docker-compose.yml 文件。
所有这些都将覆盖Dockerfile 中的任何默认ENV 值。
不同于ARG,你可以将各种环境变量传递给容器。即使在Dockerfile 中没有明确定义。
但是,这取决于您的应用程序是否会执行任何操作。
选项 1:一一提供值
在命令行中,使用 -e 标志:
$ docker run -e "env_var_name=another_value" alpine env
来自docker-compose.yml 文件:
version: '3'
services:
plex:
image: linuxserver/plex
environment:
- env_var_name=another_value
选项 2:从您的主机传递环境变量值
与上述方法相同。
唯一的区别是,您不提供值,而只是命名变量。这将使 Docker 访问宿主环境中的当前值并将其传递给容器。
$ docker run -e env_var_name alpine env
对于docker-compose.yml 文件,省略等式符号及其后的所有内容,效果相同。
version: '3'
services:
plex:
image: linuxserver/plex
environment:
- env_var_name
选项 3:从文件 (env_file) 中获取值
我们可以指定一个文件来读取值,而不是把变量写出来或硬编码(根据 12 因素的人来说这不是很好的品味)。此类文件的内容如下所示:
env_var_name=another_value
上面的文件名为 env_file_name(名称任意),它位于当前目录中。
可以引用文件名,解析后提取环境变量进行设置:
$ docker run --env-file=env_file_name alpine env
对于docker-compose.yml 文件,我们只引用一个env_file,Docker 会解析它以设置变量。
version: '3'
services:
plex:
image: linuxserver/plex
env_file: env_file_name
从命令行设置 ARG 和 ENV 的常用方法
这是一个小备忘单,结合了ARG 和ENV 可用性的概述以及从命令行设置它们的常用方法。