我试图在构建期间在docker容器中设置环境变量,但没有成功。在使用运行命令时设置它们,但我需要在构建期间设置它们。

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不存在


ARG用于设置在docker构建过程中使用的环境变量——它们不会出现在最终的图像中,这就是为什么在使用docker run时看不到它们的原因。

您可以使用ARG来设置仅在构建映像时相关的设置,并且从映像运行的容器不需要这些设置。在构建期间和容器中使用的环境变量可以使用ENV。

使用这个Dockerfile:

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一样重写构建参数。然后你就会得到你想要的:

> docker run temp cat /env.txt                                                                                         
HOSTNAME=b18b9cafe0e0                                                                                                  
RUN_TIME=123                                                                                                           
HOME=/root                                                                                                             
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin                                                      
BUILD_TIME=def                                                                                                         
PWD=/ 

我将总结这篇伟大文章中的亮点。


ARG VS 环境

1)简短说明: ARG只在构建Docker映像期间可用(RUN等),而不是在映像创建并从映像启动容器之后(ENTRYPOINT, CMD)。

容器可以使用ENV值,但在Docker构建过程中,从引入ENV值的行开始,也可以使用run样式的命令。 如果您使用bash在中间容器中设置了一个环境变量(RUN export VARI=5 &&…),它将不会在下一个命令中保持。

2 ) Longer explanation: ARG are also known as build-time variables. They are only available from the moment they are ‘announced’ in the Dockerfile with an ARG instruction up to the moment when the image is built. Running containers can’t access values of ARG variables. This also applies to CMD and ENTRYPOINT instructions which just tell what the container should run by default. If you tell a Dockerfile to expect various ARG variables (without a default value) but none are provided when running the build command, there will be an error message.

然而,通过查看映像的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中运行这个命令,将会打印出以下一行

那么,这如何转化为使用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变量的默认值。 下面是一个基本的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的代码片段,使用动态的on-build env值:

# 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

从码头编曲。yml文件:

version: '3'

services:
  plex:
    image: linuxserver/plex
      environment:
        - env_var_name=another_value

选项2:从主机传递环境变量值 这与上面的方法相同。 唯一的区别是,您不提供值,而只是命名变量。这将使Docker访问主机环境中的当前值并将其传递给容器。

$ docker run -e env_var_name alpine env

对于码头编曲。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可用性的概述,以及从命令行设置它们的常用方法。