关于dockerfile:在docker run命令中传递ENV

Pass ENV in docker run command

有没有一种方法可以传递变量,比如在这个例子中,我想使用ENV animals="turtle, monkey, goose"将动物列表传递到entrypoint.sh文件中?

但我希望在运行容器时能够通过不同的动物,例如docker run -t image animals="mouse,rat,kangaroo"

运行docker run命令时如何传递参数?

目标是在使用docker run命令时使用该变量,并将其插入entrypoint.sh文件中。

现在我把它硬编码在我的文件里。但是我希望在运行docker run命令时能够这样做,这样我就不必总是更改dockerfile。

1
2
3
4
5
6
7
8
9
10
11
FROM anapsix/alpine-java:8u121b13_jdk

ENV FILE_NAME="file_to_run.zip"

ENV animals="turtle, monkey, goose"

ADD ${FILE_NAME} .

RUN echo"${FILENAME} ${animals}"> ./entrypoint.sh    

CMD ["/bin/ash","./entrypoint.sh" ]


看起来您可能会混淆映像构建和容器运行。如果这两个问题之间的区别不是很明显,我建议您复习一些其他问题和文档,如:

在Docker中,容器和图像有什么区别?https://docs.docker.com/develop/develop-images/dockerfile_最佳实践/

1
RUN echo"${FILENAME} ${animals}"> ./entrypoint.sh

通过上面的内容,变量将在图像构建期间展开。entrypoint.sh不包含${FILENAME} ${animals}。相反,它将包含

1
file_to_run.zip turtle, monkey, goose

在构建之后,docker run命令将从该映像创建一个容器,并使用定义但从未使用的环境变量运行上述脚本,因为脚本已经扩展了变量。为了防止变量扩展,您需要退出$或使用单引号来防止扩展,例如。

1
RUN echo"\${FILENAME} \${animals}"> ./entrypoint.sh

1
RUN echo '${FILENAME} ${animals}' > ./entrypoint.sh

我还建议在这个脚本的顶部用一个#!/bin/ash来表示清楚。然后,在运行脚本时,不要用图像名称后面的参数覆盖该命令。相反,使用适当的标志设置环境变量以运行:

1
docker run -it -e animals="mouse,rat,kangaroo" image

最简单的方法,转发单个变量:

1
docker run ... --env animals="turtle, monkey, goose" --env FILE_NAME="file_to_run.zip"

使用文件转发几个变量:

或者,如果您需要从外部获取所有环境变量,您可以先这样做:

1
printenv | grep -E 'animals|FILE_NAME' > my-env

grep是因为docker不喜欢某些变量,例如其中包含空格,而这些变量在实际环境中可能存在。

然后在docker命令中使用该文件:

1
docker run ... --env-file ./my-env

如果您希望避免将环境变量发送到日志(比如敏感变量),后者也很有用。我在运行一些脚本的CI/CD管道中使用这种方法。

在Docker中使用变量:

无论采用哪种方法,环境变量实际上对在容器内运行的脚本都是可用的。

@bmitch的答案有关于如何在您的案例中实现这一点的更完整的细节,您在构建和执行中都有相关的逻辑。

参考文献

参见这里的文档。