Dockerfile:在一行中设置多个环境变量


76

我给人的印象是,可以如下将环境变量设置在一行上,以最大程度地减少中间图像。

FROM alpine:3.6
ENV RUBY_MAJOR 2.4 \
    RUBY_VERSION 2.4.1 \
    RUBY_DOWNLOAD_SHA256 4fc8a9992de3e90191de369270ea4b6c1b171b7941743614cc50822ddc1fe654 \
    RUBYGEMS_VERSION 2.6.12 \
    BUNDLER_VERSION 1.15.3

但是,基于此代码段运行容器并调用,# set |grep RU我看到变量没有被单独分配,而是被组合为单个字符串。

RUBY_MAJOR='2.4     RUBY_VERSION 2.4.1     RUBY_DOWNLOAD_SHA256 4fc8a9992de3e90191de369270ea4b6c1b171b7941743614cc50822ddc1fe654     RUBYGEMS_VERSION 2.6.12     BUNDLER_VERSION 1.15.3'

但是,如果我按如下所示显式设置每个变量,则可以得到预期的输出,并且在调用变量时没有错误。

ENV RUBY_MAJOR 2.4
ENV RUBY_VERSION 2.4.1
ENV RUBY_DOWNLOAD_SHA256 4fc8a9992de3e90191de369270ea4b6c1b171b7941743614cc50822ddc1fe654
ENV RUBYGEMS_VERSION 2.6.12
ENV BUNDLER_VERSION 1.15.3

问题:是否可以将环境变量的设置合并在一行上?如果是这样,我该怎么办?这是一个好习惯吗?

Answers:


134

有两种用于指定环境的格式。如果您需要单个变量,那么您可以使用以下格式

ENV X Y

这会将X指定为 Y

ENX X Y Z

这会将X指定为 Y Z

如果需要分配多个环境变量,则使用其他格式

ENV X=Y Z=A

这会将X指定为Y,将Z指定为A。所以你Dockerfile应该

FROM alpine:3.6
ENV RUBY_MAJOR=2.4 \
    RUBY_VERSION=2.4.1 \
    RUBY_DOWNLOAD_SHA256=4fc8a9992de3e90191de369270ea4b6c1b171b7941743614cc50822ddc1fe654 \
    RUBYGEMS_VERSION=2.6.12 \
    BUNDLER_VERSION=1.15.3

RUN env

您还可以将其与引号和现有环境变量的扩展结合使用。例如,通常希望将路径扩展为一组环境变量的一部分:ENV PATH="$PATH:/app" \ APPVAR="foo"
JeremyDouglass

4
奇怪的是,我尝试在第二个var中使用第一个var,并且无论它是一行还是多行,它都只能解析为空字符串
milosmns

@milosmns是的,我也注意到了这种行为
Kiran Challa

1
那需要建立论据
塔伦·拉尔瓦尼

2
@milosmns @ kiran-challa要解释Tarun的注释,ENV在命令完成之前,将不会设置在给定命令上声明的任何变量,以便行为符合预期(echo $V_NOT_SET在任何基于* nix的系统上尝试)。输入构建参数。附带说明,export V_NOT_SET="hello" echo $V_NOT_SET这也只会导致空白;export在此之前添加一个没有帮助;在和之间插入&&(aka AND_IF)将导致被回显,因为它现在要求在评估第二个命令之前先完成第一个命令。exportechohello
hlongmore's

20

您无需担心很多 ENV命令,每个命令都会为Dockerfile创建的最终映像创建一个新的中间层。

来自编写Dockerfile的最佳实践

减少层数

在Docker 17.05之前,甚至在Docker 1.10之前,甚至更多,减少映像中的层数非常重要。以下改进减轻了这种需求:

  • 在泊坞窗1.10和更高,只有RUNCOPYADD指令创建图层。其他说明创建临时的中间映像,并且不再直接增加构建的大小。

  • Docker 17.05和更高版本增加了对多阶段构建的支持,这允许您仅将所需的工件复制到最终映像中。这样,您就可以在中间构建阶段中包含工具和调试信息,而无需增加最终映像的大小。



@Tomanow这是docker文档的直接引号(请参阅链接),但我认为混乱的是ENV创建的图层是“临时的”,我认为这意味着在某个时候被压入了另一个图层,但这只是一个猜测执行情况。
迈克·利珀特

4
根据我在docker上进行的19ENV条测试,并没有在图像中创建图层,在构建图像时显示“正在移除中间容器”,然后在进行潜水检查之后,发现没有为其创建任何图层ENV
斯蒂芬·保罗格

3
虽然可以压缩ENV图层很不错,但是仍然必须首先创建它们,这可能需要在我的笔记本电脑上花费一些时间(这是不寻常的吗?),所以我认为最好还是采用多线路线以节省成本建立时间。
Chinoto Vokro

@ChinotoVokro说的是...。确实创建了图层,然后将其破坏了……但是,这仍然很痛苦。
乔纳森·阿尔法罗
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.