Dockerfile - 将ENV设置为命令结果

Sul*_*nen 56 env dockerfile

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

ENV MY_VAR whoami
Run Code Online (Sandbox Code Playgroud)

我希望MY_VAR获得值"root"或者任何whoami返回的值

Loï*_*oix 25

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

你可以这样做:

RUN echo "export VAR=`command`" >> /envfile
RUN . /envfile; echo $VAR
....
RUN . /envfile; echo $VAR # can be re-used
Run Code Online (Sandbox Code Playgroud)

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

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

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

.就是 env 文件的加载方式。


Dim*_*elu 16

作为DarkSideF的补充答案.

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

你可以这样做:

RUN export bleah=$(hostname -f);echo $bleah;
Run Code Online (Sandbox Code Playgroud)

这是在一个容器中运行.

  • 只是为了澄清 - `$bleah` 在这个 RUN 命令之外的任何地方都**不**可用,甚至在同一个 dockerfile 中的下一行上也不可用,更不用说在它所基于的另一个图像中了。docker 这里确实明显缺少功能,它看起来确实写入和读取文件是在图像中实际存储(动态)变量并在图像之间传递它们的唯一方法,这看起来超级黑客。 (39认同)

小智 13

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

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

docker run  -e SECRET_KEY_BASE="$(openssl rand -hex 64)"
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Docker将其缓存为图层,只有在您更改之前的某些字符串时才会更改.

您还可以尝试不同的方法来设置环境变量.

  • @SigmaX 这不是 docker 的事情,它更像是 **Linux** 的事情。`/etc/profile.d/` 中的任何 `*.sh` 文件都用于填充环境 (2认同)

小智 8

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

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


kat*_*kat 7

不确定这是否是您正在寻找的,但为了将 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 .
Run Code Online (Sandbox Code Playgroud)

为了在 .Dockerfile 中获取 ARG,代码片段可能如下所示:

FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}
Run Code Online (Sandbox Code Playgroud)

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

FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}
Run Code Online (Sandbox Code Playgroud)

这个想法是您运行 shell 脚本,并使用作为构建选项传递的参数调用 .Dockerfile。


seb*_*piq 6

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

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

例如 :

RUN echo "bla" > ./result
RUN echo $(cat ./result)
Run Code Online (Sandbox Code Playgroud)

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

RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)
Run Code Online (Sandbox Code Playgroud)

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


vde*_*nne 5

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

他提出的方法如下Dockerfile

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

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

这是件好事,但环境变量将只可用于过程/bin/bash,如果你尝试运行你的应用程序泊坞窗例如Node.js应用程式,/etc/bash.bashrc将彻底被忽略,你的应用程序将不会有一个线索SECRET_KEY_BASE是当试图访问process.env.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"
$*
Run Code Online (Sandbox Code Playgroud)

然后在您的Dockerfile

...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp
Run Code Online (Sandbox Code Playgroud)