Dockerfile-将ENV设置为命令结果


Answers:


23

作为DarkSideF答案的补充。

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

您可以执行以下操作:

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

它在单个容器中运行。


14
只是为了澄清-$bleah不是该RUN命令之外可在任何地方,甚至没有在同一dockerfile下一行,更不用说它是基于掀起另一图像。码头工人在这里确实缺少明显的功能,它看起来像是在文件中读写文件,这是在图像中实际存储(动态)变量并在图像之间传递它们的唯一方法,这似乎非常hacky。
davnicwil

17

我有同样的问题,并找到了通过在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变量也可以从根目录获取。或许

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

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

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

您也可以尝试其他方法来设置环境变量。


/etc/profile.d/docker_init.sh还是一回事吗?我只能在Google上找到该答案,它对我不起作用。它可能是2016年不再流行的Docker执行引擎的一部分吗?
SigmaX

1
@SigmaX不是docker,而是Linux*.sh内部的任何文件/etc/profile.d/均用于填充环境
Madacol


7

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

他提出的方法如下Dockerfile

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

(在中添加导出/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"
$*

然后在您的Dockerfile

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

2

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

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

例如 :

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

对于更干净的东西,您还可以使用以下要点,该要点提供了一个称为的小型CLI envstore.py

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

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


2

不确定这是否是您想要的,但是为了将ENV var或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,并将args作为选项传递给构建。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.