Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dockerfile中的多次运行与单链运行,哪一种更好?_Docker_Dockerfile - Fatal编程技术网

Dockerfile中的多次运行与单链运行,哪一种更好?

Dockerfile中的多次运行与单链运行,哪一种更好?,docker,dockerfile,Docker,Dockerfile,Dockerfile.1执行多个RUN: FROM busybox RUN echo This is the A > a RUN echo This is the B > b RUN echo This is the C > c Dockerfile.2加入它们: FROM busybox RUN echo This is the A > a &&\ echo This is the B > b &&\ echo T

Dockerfile.1
执行多个
RUN

FROM busybox
RUN echo This is the A > a
RUN echo This is the B > b
RUN echo This is the C > c
Dockerfile.2
加入它们:

FROM busybox
RUN echo This is the A > a &&\
    echo This is the B > b &&\
    echo This is the C > c
每次运行
RUN
都会创建一个层,因此我一直认为层越少越好,因此
Dockerfile.2
越好

运行
删除前一次
运行
添加的内容(即
yum install nano&&yum clean all
)时,这显然是正确的,但在每次
运行
都会添加内容的情况下,我们需要考虑以下几点:

  • 层应该只在前一层的基础上添加一个diff,因此如果后一层没有删除前一层中添加的内容,那么这两种方法之间应该没有多少节省磁盘空间的优势

  • 层是从Docker Hub并行提取的,因此,
    Dockerfile.1
    ,虽然可能稍大,但理论上下载速度会更快

  • 如果添加第四句话(即
    echo这是D>D
    )并在本地重建,
    Dockerfile.1
    将由于缓存而构建得更快,但
    Dockerfile.2
    必须再次运行所有4个命令


  • 因此,问题是:哪种方法更适合制作Dockerfile?这取决于图像层中包含的内容

    关键是尽可能多地共享层:

    坏例子:

    Dockerfile.1

    RUN yum install big-package && yum install package1
    
    RUN yum install big-package
    RUN yum install package1
    
    Dockerfile.2

    RUN yum install big-package && yum install package2
    
    RUN yum install big-package
    RUN yum install package2
    
    好例子:

    Dockerfile.1

    RUN yum install big-package && yum install package1
    
    RUN yum install big-package
    RUN yum install package1
    
    Dockerfile.2

    RUN yum install big-package && yum install package2
    
    RUN yum install big-package
    RUN yum install package2
    

    另一个建议是,只有当删除与添加/安装操作发生在同一层时,删除才没有那么大用处。

    他们的最佳实践中列出了官方答案(官方图片必须遵守这些)

    最小化层的数量

    你需要在两者之间找到平衡 Dockerfile和 最小化它使用的层数。谋略谨慎 关于您使用的层数

    自从docker 1.10以来,
    COPY
    ADD
    RUN
    语句为图像添加了一个新层。使用这些语句时要小心。尝试将命令组合成一个
    RUN
    语句。只有在可读性要求时才将其分开

    更多信息:

    更新:docker中的多阶段>17.05

    对于多阶段构建,您可以在Dockerfile中使用多个
    FROM
    语句。每个
    FROM
    语句都是一个阶段,可以有自己的基本映像。在最后一个阶段中,您将使用一个最小的基本映像(如alpine),从以前的阶段复制构建工件并安装运行时需求。这个阶段的最终结果就是你的形象。因此,这就是您担心前面描述的层的地方

    和往常一样,docker已经完成了多阶段构建。下面是一个简短的摘录:

    对于多阶段构建,您可以在应用程序中使用多个FROM语句 Dockerfile。每个FROM指令都可以使用不同的基址 他们中的大多数人开始了一个新的建设阶段。你可以有选择地复制 从一个阶段到另一个阶段的人工制品,留下你想要的一切 不希望出现在最终图像中

    关于这一点的一篇很棒的博客文章可以在这里找到:

    要回答您的观点:

  • 是的,图层有点像diff。我认为如果绝对没有变化,就不会添加图层。问题是,一旦你在第2层安装/下载了一些东西,你就不能在第3层删除它。因此,一旦在一个层中写入了某个内容,图像大小就不能再通过删除该内容来减小

  • 尽管层可以并行拉取,这可能会加快拉取速度,但每个层无疑会增加图像大小,即使它们正在删除文件

  • 是的,如果您正在更新docker文件,缓存非常有用。但它在一个方向上起作用。如果您有10个层,并且更改了第6层,您仍然需要从第6层到第10层重建所有内容。因此,它不会太频繁地加快构建过程,但会保证不必要地增加图像的大小



  • 感谢您提醒我更新此答案。

    如果可能,我总是将创建文件的命令与删除相同文件的命令合并到一行中。这是因为每个
    RUN
    行都会向映像添加一个层,其输出实际上就是文件系统更改,您可以使用它创建的临时容器上的
    docker diff
    查看这些更改。如果删除在不同层中创建的文件,union文件系统只需在新层中注册文件系统更改,该文件仍存在于前一层中,并通过网络传送并存储在磁盘上。因此,如果您下载源代码,将其解压缩,编译成二进制文件,然后在最后删除tgz和源文件,您真的希望所有这些都在一个层中完成,以减小图像大小

    接下来,我个人根据层在其他图像中的重用潜力和预期的缓存使用情况来划分层。如果我有4个映像,所有映像都具有相同的基本映像(例如debian),我可能会将这些映像中大多数映像的公共实用程序集合拉入第一个run命令,以便其他映像从缓存中受益

    查看映像缓存重用时,Dockerfile中的顺序非常重要。我看了一些很少更新的组件,可能只有在基本映像更新并将它们放在Dockerfile的较高位置时才会更新。在Dockerfile的末尾,我包含了任何快速运行且可能频繁更改的命令,例如添加具有主机特定UID的用户或创建文件夹和更改权限。如果容器包含正在积极开发的解释代码(例如JavaScript),那么将尽可能晚地添加该代码,以便重建只运行单个更改

    在每一组更改中,我都尽可能地进行整合,以最大限度地减少l