我注意到许多Dockerfiles
试图通过一条UNIX
指令中的多个RUN
命令来减少指令数量。那有什么原因吗?
Dockerfile
之间的结果也有区别吗?Dockerfile1
FROM ubuntu
MAINTAINER demousr@example.com
RUN apt-get update
RUN apt-get install –y nginx
CMD ["echo", "Image created"]
Dockerfile2
FROM ubuntu
MAINTAINER demousr@example.com
RUN apt-get update && apt-get install –y nginx
CMD ["echo", "Image created"]
答案 0 :(得分:3)
大致来说,Docker映像包含一些元数据和一层数组,并且通过添加容器层(读写)在这些层上构建运行中的容器,基础映像中的层是只读的在那个时候。
可以根据配置的驱动程序以不同方式将这些层存储在磁盘中。例如,以下来自官方Docker文档的图像说明了OverlayFS storage driver考虑在这些不同层中更改的文件的方式:
接下来,Dockerfile指令RUN
,COPY
和ADD
创建层,并且Docker网站上提到的最佳实践特别建议将连续的RUN
命令合并到单个RUN
命令,以减少层数,从而减小最终图像的大小:
https://docs.docker.com/develop/dev-best-practices/
[…]尝试通过最小化Dockerfile中单独的
RUN
命令的数量来减少映像中的层数。为此,您可以将多个命令合并到单个RUN
行中,并使用Shell的机制将它们组合在一起。 […]
另请参阅:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
此外,在您的示例中:
RUN apt-get update -y -q
RUN apt-get install -y nginx
如果您对此docker build -t your-image-name .
做过Dockerfile
,然后过了一会儿编辑Dockerfile
,在nginx
之后添加了另一个软件包,然后再次执行docker build -t your-image-name .
,由于Docker缓存机制,apt-get update -y -q
将不会再次执行,因此APT缓存将过时。因此,这是合并两个RUN
命令的另一个好处。
答案 1 :(得分:2)
除了节省空间外,还涉及正确性
考虑您的第一个dockerfile(与使用apt
的类似debian的系统一起使用时,这是一个常见错误):
FROM ubuntu
MAINTAINER demousr@example.com
RUN apt-get update
RUN apt-get install –y nginx
CMD ["echo", "Image created"]
如果两个或两个以上的图像遵循此模式,则缓存命中 可能会由于缓存的元数据而导致图像无法构建
RUN apt-get update
行之前一直存在一个缓存docker build
将重用该缓存层(因为dockerfile和基本映像相同),直到RUN apt-get update
RUN apt-get install
行时,它将使用缓存的apt元数据(现在已过期几周,可能会出错)