我正在尝试在构建期间在docker容器中设置环境变量,但没有成功。使用run命令时设置它们有效但我需要在构建期间设置它们。
Dockerfile
FROM ubuntu:latest
ARG TEST_ENV=something
我正在使用构建
的命令docker build -t --build-arg TEST_ENV="test" myimage .
运行
docker run -dit myimage
我正在使用
检查可用的环境变量docker exec containerid printenv
,结果是
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e49c1abfd58b
TERM=xterm
no_proxy=*.local, 169.254/16
HOME=/root
TEST_ENV不存在
答案 0 :(得分:50)
ARG
用于设置docker build
过程中使用的环境变量 - 它们不会出现在最终图像中,这就是您在使用{{{{{{{{ 1}}。
您使用docker run
进行仅在构建图像时相关的设置,并且您从图像运行的容器不需要这些设置。您可以在构建期间和容器中使用ARG
来获取环境变量。
使用此Dockerfile:
ENV
您可以像使用FROM ubuntu
ARG BUILD_TIME=abc
ENV RUN_TIME=123
RUN touch /env.txt
RUN printenv > /env.txt
一样覆盖构建参数。然后你得到了你期望的东西:
docker build -t temp --build-arg BUILD_TIME=def .
答案 1 :(得分:8)
我将总结this精彩文章中的要点。
1)简短说明:
ARG 仅在构建Docker映像期间(RUN等)可用,而在创建映像并从中启动容器(ENTRYPOINT,CMD)之后不可用。
ENV 值可用于容器,但在Docker构建期间(从引入它们的行开始)也可使用RUN样式的命令。 如果您使用bash(RUN export VARI = 5 &&…)在中间容器中设置环境变量,则该变量将不会保留在下一个命令中。
2)更长的解释:
ARG 也称为生成时变量。它们只有在使用ARG指令在Dockerfile中“宣布”之时才可用,直到构建映像为止。正在运行的容器无法访问ARG变量的值。这也适用于CMD和ENTRYPOINT指令,它们仅告诉容器默认情况下应运行的内容。如果您告诉Dockerfile期望使用各种ARG变量(没有默认值),但是在运行build命令时未提供任何变量,则会出现错误消息。
但是,在构建映像后,可以通过查看映像的docker历史记录轻松检查ARG值。因此,对于敏感数据,它们是一个糟糕的选择。
在向您介绍ENV指令后,ENV 变量在构建过程中也可用。但是,与ARG不同,从最终映像开始的容器也可以访问它们。启动容器时,可以覆盖ENV值,详情请参见下文。
3)带diagrem:
这是围绕从Dockerfile构建Docker映像并运行容器的过程中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映像时,可以使用ARG
设置–build-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
当您尝试设置ARG
中未提及的Dockerfile
变量时,Docker会抱怨。
那么,如何设置ENV
值?您可以在启动容器时做到这一点(下面我们将对此进行介绍),但是您也可以通过对它们进行硬编码来直接在您的ENV
中提供默认的Dockerfile
值。另外,您可以为环境变量设置动态默认值!
构建图像时,如上所述,您只能提供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
的摘要,使用动态的内置环境值:
# 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
文件。
所有这些都将覆盖ENV
中的所有默认Dockerfile
值。
与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
的可用性概述以及从命令行设置它们的常用方法。