【问题标题】:Dockerfile - set ENV to result of commandDockerfile - 将 ENV 设置为命令的结果
【发布时间】:2016-04-26 23:34:40
【问题描述】:

是否可以将 docker ENV 变量设置为命令的结果? 喜欢:

ENV MY_VAR whoami

我希望 MY_VAR 获得值“root”或 whoami 返回的任何值

【问题讨论】:

标签: dockerfile env


【解决方案1】:

我遇到了同样的问题,并找到了通过在 dockerfile 中使用 RUN 命令将环境变量设置为函数结果的方法。

例如,我只需为 Rails 应用程序设置一次 SECRET_KEY_BASE,而无需像运行时那样更改:

docker run  -e SECRET_KEY_BASE="$(openssl rand -hex 64)"

相反,我将其写入 Dockerfile 字符串,例如:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

即使在 bash 登录后,我的 env 变量也可以从 root 获得。 或者可能是

RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" > /etc/profile.d/docker_init.sh'

然后它在 CMD 和 ENTRYPOINT 命令中可用

Docker 将其缓存为层,并且仅在您更改之前的某些字符串时才更改。

您也可以尝试different ways设置环境变量。

【讨论】:

  • /etc/profile.d/docker_init.sh 还是一个东西吗?这个答案是我可以在谷歌上找到的唯一提及它,它对我不起作用。它是否可能是 2016 年不再流行的 Docker 执行引擎的一部分?
  • @SigmaX 这不是 docker 的东西,它更像是 Linux 的东西。 /etc/profile.d/ 中的任何 *.sh 文件都用于填充环境
【解决方案2】:

作为 DarkSideF 答案的补充。

您应该知道 Dockerfile 中的每一行/命令都在另一个容器中运行。

你可以这样做:

RUN export bleah=$(hostname -f);echo $bleah;

这是在单个容器中运行的。

【讨论】:

  • 澄清一下 - $bleah 在此 RUN 命令之外的任何地方都可用,甚至在同一个 dockerfile 的下一行也不可用,更不用说在它所基于的另一个图像中了.此处 docker 确实缺少明显的功能,看起来写入和读取文件是在图像中实际存储(动态)变量并在图像之间传递它们的唯一方法,这似乎超级 hacky。
【解决方案3】:

此时,命令结果可以与RUN export 一起使用,但不能分配给ENV 变量。

已知问题:https://github.com/docker/docker/issues/29110

【讨论】:

    【解决方案4】:

    这个答案是对@DarkSideF的回应,

    他提出的方法如下,Dockerfile

    RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
    

    (/etc/bash.bashrc中添加导出)

    这很好,但环境变量将仅可用于进程 /bin/bash,如果您尝试运行 docker 应用程序,例如 Node.js 应用程序,/etc/bash.bashrc 将被完全忽略,您的应用程序将不会在尝试访问 process.env.SECRET_KEY_BASE 时,您完全不知道 SECRET_KEY_BASE 是什么。

    这就是为什么ENV 关键字是每个人都试图在动态命令中使用的原因,因为每次运行容器或使用exec 命令时,Docker 都会检查ENV 并将每个值传递给当前运行的进程(类似于-e)。

    一种解决方案是使用包装器(感谢github issue 中的@duglin)。 在您的项目根目录中有一个包装文件(例如envwrapper),其中包含:

    #!/bin/bash
    export SECRET_KEY_BASE="$(openssl rand -hex 64)"
    export ANOTHER_ENV "hello world"
    $*
    

    然后在您的 Dockerfile 中:

    ...
    COPY . .
    RUN mv envwrapper /bin/.
    RUN chmod 755 /bin/envwrapper
    CMD envwrapper myapp
    

    【讨论】:

      【解决方案5】:

      作为对@DarkSideF 答案的补充,如果您想在您的Dockerfile 在构建过程中 中重用先前命令的结果,您可以使用以下解决方法:

      1. 运行命令,将结果存储在文件中
      2. 使用命令替换将该文件中的先前结果获取到另一个命令中

      例如:

      RUN echo "bla" > ./result
      RUN echo $(cat ./result)
      

      为了更简洁,您还可以使用以下 gist,它提供了一个名为 envstore.py 的小型 CLI:

      RUN envstore.py set MY_VAR bla
      RUN echo $(envstore.py get MY_VAR)
      

      或者您可以使用具有类似 CLI 的 python-dotenv 库。

      【讨论】:

      • 我在与ENV 交互时遇到了困难。可与RUN 一起使用。
      【解决方案6】:

      不确定这是否是您要查找的内容,但为了将 ENV vars 或 ARGS 注入您的 .Dockerfile 构建,此模式有效。

      在你的 my_build.sh 中:

      echo getting version of osbase image to build from
      OSBASE=$(grep "osbase_version" .version | sed 's/^.*: //')
      
      echo building docker
      docker build -f \
      --build-arg ARTIFACT_TAG=$OSBASE \
      PATH_TO_MY.Dockerfile \
      -t my_artifact_home_url/bucketname:$TAG .
      

      为了在 .Dockerfile 中获取 ARG,sn-p 可能如下所示:

      FROM scratch
      ARG ARTIFACT_TAG
      FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}
      

      另外,为了在 .Dockerfile 中获取 ENV,sn-p 可能如下所示:

      FROM someimage:latest
      ARG ARTIFACT_TAG
      ENV ARTIFACT_TAG=${ARTIFACT_TAG}
      

      这个想法是您运行 shell 脚本并调用 .Dockerfile,并将 args 作为构建选项传入。

      【讨论】:

        【解决方案7】:

        如果您使用 sh 运行命令,因为它似乎是 docker 中的默认设置。

        你可以这样做:

        RUN echo "export VAR=`command`" >> /envfile
        RUN . /envfile; echo $VAR
        

        这样,您通过将输出重定向到您选择的 env 文件来构建一个 env 文件。它比必须定义配置文件等更明确。

        然后,由于该文件可用于其他层,因此可以获取该文件并使用正在导出的变量。创建 env 文件的方式并不重要。

        然后,当您完成后,您可以删除该文件,使其对正在运行的容器不可用。

        . 是 env 文件的加载方式。

        【讨论】:

        • 这总是很方便的!
        猜你喜欢
        • 1970-01-01
        • 2015-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-09
        • 2020-07-10
        • 1970-01-01
        相关资源
        最近更新 更多