我在处理opensource Dockerfile时遇到的问题时感到困惑,归结为"为什么要更改图层?" - 所以我试图通过自己的调查回答这个问题。
我很抱歉这个主题没有明确定义,但实质上它是关于docker层如何与docker-cache相关。
所以我在一个没有充分记录的领域寻找一个优雅的解释。
我对原始Dockerfile的更改将ENV分隔到不同的层,先前移动COPY,然后再显示端口。
原文(简化):
FROM ubuntu:latest
ENV HELLO world
ENV DOCKER whale # <-- Separate ENV into different layers
COPY source /to/container # <-- Less prone to change, move earlier
RUN # Run stuff
EXPOSE 80 # <-- "Bake in" port later
CMD # Do stuff
我的更改:
{{1}}
我的理解是,从docker-cache的角度来看, 将ENV变量分成不同的层是一个很好的做法,因为 - 如果是用户想要覆盖ENV - 只有一个ENV需要在它自己的层 内进行更改,而不是为了整个包含所有ENV的整个层而改变一个。
但是稍后添加端口EXPOSE - 感觉还不错。这是因为我已经使用Docker大约18个月了,几乎所有Docker的文档和指南都会在Dockerfile中稍后公开端口。
我也根据我的经验(并参加了DockerCon2017并参加了一些&#34;最佳实践和#34;课程)来相信这一点 应该更容易发生更改/覆盖的图层稍后放在Dockerfile 中,以更好地优化docker-cache,这样就没有那么多低级别的层变化。
我的观点是正确的(或愚蠢的)假设分离ENV层,提前移动COPY, 稍后放置EXPOSE层 是一种良好的做法,并且是对从优化Docker缓存的角度看原始Dockerfile的层?
答案 0 :(得分:2)
虽然这个问题有一些很有见解的可能答案,但我会尝试跟踪来自docker's docs on this
的事实和其他事情。Docker中图层的正确分层基本上有三个目标(大致有序):
apt
操作应该始终以apt-get update && ...
开头,apt-get update
永远不应该在单独的RUN
中层鉴于此,这里有一些您提出的建议的观察结果:
ENV
图层鉴于上述(2),您应尽可能将ENV
个图层组合在一起。用户可以在运行时覆盖--env
,这不会影响构建时分层。是的,如果其中一个ENV
行在源代码中被修改,它将使文件的其余部分无效(3)但通常会因性能原因而被删除。
COPY
通常这不是一个好主意,磁盘上的源是最可能的要更改的内容,如果源更改,COPY
层中的所有层都将失效
EXPOSE
这无关紧要。 EXPOSE
是一个几乎无关紧要的层(事实上,除非你链接容器,否则它什么都不做)。由于它是可缓存的,我把它放在顶部附近,但再次,计算并不会真正改变它是微不足道的。
tl; dr维护者对所有三个更改都说“不”是正确的,因为它会使构建和运行性能变差。