在Dockerfile
中,我看到大多数人都使用这种语法
RUN apt-get -y update \
&& apt-get install -y libicu-dev
超过这个
RUN apt-get -y update
RUN apt-get install -y libicu-dev
对我来说,第一个只缓存一行(图层)而第二个缓存两个(我错了吗?)并在命令不成功时立即停止。
此外我没有发现第一个更具可读性。
那么我们为什么要使用第一种语法?
答案 0 :(得分:2)
它是泊坞窗图像层的优化。我还建议您阅读Best practices for writing Dockerfiles
DockerCon EU 2017还有一些有趣的presentation。
答案 1 :(得分:1)
图层越少,图像越好。
因此,使用&&组合命令。将创建一个单独的图层。
有两个RUN将创建两个层。
答案 2 :(得分:0)
Dockerfile 中的每个命令都会创建另一个图像层。
组合命令是一种总体上减少层数的方法。
请参阅https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/#images-and-layers
答案 3 :(得分:0)
这一行:
RUN apt-get -y update \
&& apt-get install -y libicu-dev
将创建一个泊坞窗图层和these lines:
RUN apt-get -y update
RUN apt-get install -y libicu-dev
将创建两个不同的图层。
这就是为什么当您需要在docker机器中安装某些东西时(例如:通过APT),您倾向于将所有内容保存在一行(也称为图层)
答案 4 :(得分:0)
正如其他答案已经说过的那样,每个命令都会生成一个图层,通常希望每个图像的图层数量最少。
每个图层只是与之前图层的一组差异。这些层堆叠在彼此之上。创建新容器时,可在基础图层上添加新的可写层。
这意味着除非您要“挤压”您的图像(在构建过程中使用--squash
选项进行翻译),否则最终会让图像消耗空间。
实施例
# Dockerfile
FROM ubuntu
RUN apt-get update
RUN apt-get install -y --no-install-recommends dnsutils
RUN echo $( dig somewhere.nowhere )
RUN apt-get remove --purge dnsutils
RUN rm -rf /var/lib/apt/lists/*
COPY magicalScript.sh /
CMD /magicalScript.sh
在这种情况下,您将拥有仅包含开销的图层:
apt-get update
dnsutils
的dnsutils
问题在于所有这些层都保留在那里并且毫无理由地消耗空间。
为什么squash
并不总是一个好的解决方案?因为图层也代表缓存。当你需要执行大量构建并且需要它们尽可能快时,它非常有用。
通常最好将操作相关的操作组合在操作系统上安装新包:
# Dockerfile
FROM ubuntu
RUN useradd docker \
&& mkdir /home/docker \
&& chown docker:docker /home/docker \
&& addgroup docker staff
RUN apt-get update \
&& apt-get install -y --no-install-recommends ed less locales vim-tiny wget ca-certificates fonts-texgyre \
&& rm -rf /var/lib/apt/lists/*
RUN echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \
&& locale-gen en_US.utf8 \
&& /usr/sbin/update-locale LANG=en_US.UTF-8
CMD ["mySpecialCommand"]
答案 5 :(得分:0)
根据images and layers documentation
每个图层只是与之前图层的一组差异
因此,例如,2层创建不同的文件将不会使用更多的磁盘空间。特别是自Docker 17.05 allows multi-stage builds以来。但是,如果第二个完全修改第一个文件,它仍然可以使用更多空间。
关注Khapov Igor's comment我在best practice doc找到了原始问题的真实答案:
在
apt-get update
语句中单独使用RUN
会导致缓存问题和后续apt-get install
条指令失败。
实际上更多的是关于以前命令的层依赖性,结果可以随着时间的推移而发展,如apt-get update
。
这就是他们说的原因:
始终将
中RUN apt-get update
与apt-get install
合并到同一RUN
声明