【问题标题】:How do I set environment variables during the build in docker如何在 docker 构建期间设置环境变量
【发布时间】:2017-01-28 14:30:25
【问题描述】:

我试图在构建期间在 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 不存在

【问题讨论】:

    标签: docker dockerfile


    【解决方案1】:

    ARG 用于设置在docker build 过程中使用的环境变量 - 它们不会出现在最终图像中,这就是为什么您在使用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=/ 
    

    【讨论】:

    • 使用 ENV 添加了环境变量,但使用 docker build -t temp --build-arg BUILD_TIME=def 打印“一个或多个构建参数 [BUILD_TIME] 未被使用,构建失败。”。添加单独的ARG BUILD_TIME_ARG=defaultENV BUILD_TIME=$BUILD_TIME_ARG 有帮助。您可以将其添加到您的答案中吗?感谢您的帮助。
    • 我刚刚意识到您可以将ARGENV 同名。 ARG BUILD_TIME=defaultENV BUILD_TIME=$BUILD_TIME
    • 具有讽刺意味的是,埃尔顿的回答并不正确。 Michael 的最后一条评论一针见血,展示了如何通过构建实际设置环境变量(在撰写本文时)。
    【解决方案2】:

    我将总结来自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,它定义了ARGENV 值。如何设置它们,在哪里?您可以在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 变量提供值。但是,ARGENV 可以一起工作。您可以使用 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 的常用方法

    这是一个小备忘单,结合了ARGENV 可用性的概述以及从命令行设置它们的常用方法。

    【讨论】:

    • 如果我不设置环境变量,那么容器中默认的环境变量是什么?它会跟随宿主环境吗?
    • 如果您没有在 Dockerfile 中配置任何环境变量,它将仅包含基本映像附带的默认变量(可能更多系统级别)。不是主人的。
    • 这个答案对于备忘单来说是值得的。谢谢:)
    • 是在容器内放一个.env文件还是把ENV值加载到容器的环境中更好?
    • @Zaffer,这两种选择都有效,这取决于具体情况或在代码中更容易使用它的方式(读取环境变量或从文件中读取可能会更慢)。
    猜你喜欢
    • 2021-07-28
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2021-01-31
    • 2019-02-25
    • 2011-10-31
    • 2020-03-28
    • 1970-01-01
    相关资源
    最近更新 更多