Dockerfile-将 ENV 设置为执行命令的结果

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

ENV MY_VAR whoami

我希望 MY _ VAR 获取值“ root”或 whoami 返回的任何值

90370 次浏览

我也遇到过同样的问题,我在 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'

和我的 env 变量在 root 中可用,即使在 bash 登录之后也是如此。 或者可能是

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

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

Docker 将其缓存为层,只有在更改之前的字符串时才进行更改。

你亦可尝试使用 不同的方式设定环境变量。

作为黑暗面答案的补充。

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

你可以这样做:

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

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

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

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

这个答案是对 @ Dark SideF的回应,

他提出的方法如下,在 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 的问题中是 @ 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

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

  1. run a command, store the result in a file
  2. 使用指令替代将前一个结果从该文件转移到另一个命令中

例如:

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

对于一些干净的东西,你也可以使用下面的 大意,它提供了一个叫做 envstore.py的小 CLI:

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

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

不确定这是否是您所寻找的,但为了注入 ENV 变量或 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,代码片段可能如下所示:

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

或者在.Dockerfile 中获取一个 ENV,代码片段可能如下所示:

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

其思想是运行 shell 脚本,然后调用。Dockerfile,其中的参数作为生成中的选项传入。

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

你可以这样做:

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

通过这种方式,您可以通过将输出重定向到所选的 env 文件来构建 env 文件。它比定义配置文件等更加明确。

然后,由于该文件将可用于其他层,这将是可能的来源,并使用变量被导出。创建 env 文件的方法并不重要。

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

.是加载 env 文件的方式。