假设我有一个Dockerfile,我使用FROM指令在其中构建基于其他图像的图像。
例如,我的图片名为extendedImage
,以FROM baseImage
开头,然后只安装其他内容。
现在,说baseImage
得到更新。我用docker pull baseImage
提取更新。现在,如果我docker run extendedImage
,它是否会反映baseImage
中所做的更改?或者我必须先docker build extendedImage
再次才能反映更新后的baseImage
?
答案 0 :(得分:5)
图像是由图层构建的,每个图层的实际名称是其哈希值,而不是其标记。
我有一张我打电话给的图像" foo",它是由" bar"构建的,但是我真的有这个(最近的一层):
e3e4a61fae2f <--- "foo"
70ba8fd71a0d
9b14cb475328
8e8d2e367ec2 <--- "bar"
8cf23a15c387
(所以我们可以看到我的&#34; foo&#34; Dockerfile必须在FROM
之后有3个命令,&#34; bar&#34;在一些基础层之后有一个命令。)< / p>
如果我更改这些标签,图片就不会改变,因为我只是移动了一些指针,而图像的所有部分都保留了下来:
e3e4a61fae2f <--- "<none>"
70ba8fd71a0d
9b14cb475328
8e8d2e367ec2
8cf23a15c387
试试这个:docker run -d foo
,然后进行一些更改并docker build -t foo .
如果您查看docker ps
,您的容器仍在运行,但现在它还没有#34; foo&#34;标记,因为该标记已移动到某个新图像。但是您的容器尚未更新。 docker build
使用您在构建时拥有的标记,但它最终会使用哈希名称构建图像。 docker run
使用您拥有运行时的标记,但它最终从哈希名称启动容器。标签只是指针被跟随然后被遗忘。
编辑虽然这就是Docker在图片上的标签和容器名称方面的样子,但问题的另一个组成部分是你是否可以换出底层图层。你不能。正如你无法在你的git历史中更改一个提交并让HEAD神奇地改变(你需要将整个历史记录从那一点改写为HEAD),你就不能改变一个较低的层并拥有上层&#34;只是工作&#34;。每一层都取决于它下面的层。
答案 1 :(得分:2)
图像构建在union文件系统上,该系统使用&#39; copy-on-write&#39;政策。图像中的所有较低层都是只读的,每次运行容器时,新的读写层都会放在顶部,而不会触及下层。
现在关键是你可以在基础图像中添加新图层,不能更改基础图像的现有图层。扩展图像将继续使用现有的基本图像层,新图层将不会合并到此处。因此,扩展图像不会改变。