我一直在玩创建docker文件和阅读文档,我想知道这个问题:在我的docker文件中添加EXPOSE命令会添加一个图层吗? (如果它确实为什么我会关心/它在文件中的位置是否重要?)
documentation中未明确说明。
我理解RUN,COPY和ADD创建图层,因为它们会更改文件系统。但是暴露只是简单地将元数据添加到容器中,它会改变生成一个层吗?
答案 0 :(得分:6)
是的,Dockerfile中的每条指令都会为生成的图像生成一个新图层。
但是,通过EXPOSE
创建的图层是空图层。也就是说,它们的大小是0字节。
虽然他们不会影响您的存储空间,但他们确实会在构建或从注册表中提取/推送图像时利用图层缓存。
了解图像图层的一种好方法是使用docker history
命令。例如,给定以下Dockerfile:
FROM scratch
EXPOSE 4000
EXPOSE 3000
DO
docker build -t test/image .
如果你然后docker history test/image
,你会看到:
IMAGE CREATED CREATED BY SIZE COMMENT
ab9f435de7bc 4 seconds ago /bin/sh -c #(nop) EXPOSE 4000/tcp 0 B
15e09691c313 5 seconds ago /bin/sh -c #(nop) EXPOSE 3000/tcp 0 B
如果您切换EXPOSE
语句的顺序并再次构建,您将看到图层缓存被忽略。
答案 1 :(得分:2)
所有说明都会创建新图层,但不更改文件系统的说明会创建一个空图层。
值得研究Docker的文件系统分层是如何工作的,您可以阅读here或here for AUFS。
文件系统上的新层基本上是由那些从它们下面的层改变的文件构成的,它就像一堆差异。因此,如果没有变化,则没有要制作的图层。大多...
Dockerfile中的每条指令都会创建一个图像层,但是对于AUFS(在EXPOSE
的情况下),该层将为空(它与它下面的层没有区别)。
答案 2 :(得分:1)
我意识到我可以自己测试一下。并且我发现添加EXPOSE不会添加新的文件系统层,但它确实添加了一个层,同样重要的是你为缓存层制作docker文件的顺序。
基本上:每个命令都会创建一个新层,每个更改文件系统的命令都会创建一个文件系统层。
FROM ...
EXPOSE 80
COPY smthing .
不同于:
FROM ...
COPY smthing .
EXPOSE 80
多次执行时(比如在开发环境中)。
在第一个示例中,EXPOSE
命令被缓存,即使smthing
文件发生更改也不会执行。如果某个文件发生更改,docker build
将仅重新执行此命令(其余部分来自缓存)。
在第二个例子中。如果smthing
文件发生更改,则EXPOSE命令也将重建。 (因为复制命令之后的所有内容都无效并在docker build
上重新执行)。
我是否会更改EXPOSE端口,第一种情况是必须重新执行复制命令,第二个例子不会。
但两者都会导致完全相同的最终结果文件系统层。
docker inspect imageName #shows the file system layer
docker history imageName #shows all the layers
答案 3 :(得分:1)
否,指令EXPOSE
不添加新层。此信息将永久存储在映像和容器配置中,并可通过以下方式检索:
docker inspect --format '{{.Config.ExposedPorts}}' <image_id>
但是您可能仍然想知道为什么输出中有一行显示新图像是为此命令创建的。考虑以下Dockerfile
:
FROM alpine
EXPOSE 8000
最后,Docker产生了这样的输出:
Step 1/2 : FROM alpine
---> 965ea09ff2eb
Step 2/2 : EXPOSE 8000
---> Running in 6c8fae4f3499
Removing intermediate container 6c8fae4f3499
---> 067aa2abe94f
Successfully built 067aa2abe94f
Successfully tagged envtest:latest
同时docker history
概述:
IMAGE CREATED CREATED BY SIZE COMMENT
067aa2abe94f About a minute ago /bin/sh -c #(nop) EXPOSE 8000 0B
965ea09ff2eb 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
Dockerfile
中的每一行都会在当前图像的顶部创建图像,因此图像具有到父图像的链接。然后,立即容器将根据此新映像进行初始化,然后在其中执行命令并将结果提交给该映像。
通常,如果该命令未导致文件系统中的更改,则不会创建新层。我建议使用dive浏览docker映像中的每一层。