Docker 为假定缓存的摘要下载较新的图像
Docker downloads newer image for supposedly-cached digest
我的 Dockerfile
有第一步:
FROM python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
这样做的目标是to "lock" or "pin" the version of the image。
有一段时间,docker build
正确使用了缓存版本:
Step 1/2 : FROM python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
---> 114ae8bdb954
但过了一段时间,它决定 "download a newer image":
Step 1/2 : FROM python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11: Pulling from library/python
7e2b2a5af8f6: Pulling fs layer
09b6f03ffac4: Pulling fs layer
dc3f0c679f0f: Pulling fs layer
fd4b47407fc3: Pulling fs layer
bb7b28578995: Pulling fs layer
6ebea4a9a306: Pulling fs layer
22a2327cd1ca: Pulling fs layer
bfbf91c84bbe: Pulling fs layer
f6b29b259c5c: Pulling fs layer
09b6f03ffac4: Verifying Checksum
09b6f03ffac4: Download complete
dc3f0c679f0f: Download complete
7e2b2a5af8f6: Verifying Checksum
7e2b2a5af8f6: Download complete
6ebea4a9a306: Verifying Checksum
6ebea4a9a306: Download complete
fd4b47407fc3: Verifying Checksum
fd4b47407fc3: Download complete
bfbf91c84bbe: Verifying Checksum
bfbf91c84bbe: Download complete
f6b29b259c5c: Verifying Checksum
f6b29b259c5c: Download complete
22a2327cd1ca: Verifying Checksum
22a2327cd1ca: Download complete
bb7b28578995: Verifying Checksum
bb7b28578995: Download complete
7e2b2a5af8f6: Pull complete
09b6f03ffac4: Pull complete
dc3f0c679f0f: Pull complete
fd4b47407fc3: Pull complete
bb7b28578995: Pull complete
6ebea4a9a306: Pull complete
22a2327cd1ca: Pull complete
bfbf91c84bbe: Pull complete
f6b29b259c5c: Pull complete
Digest: sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
Status: Downloaded newer image for python@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
---> 114ae8bdb954
尽管这一步的最终哈希是相同的:
---> 114ae8bdb954
据我了解,摘要 (sha256:...
) 是不可变的。
那么它们到底是可变的吗?
还是缓存的版本以某种方式被删除了?
这是怎么回事,我该如何解决?
有两种摘要:注册表中镜像清单的摘要和JSON本地镜像配置的摘要,其中还包含镜像内容的摘要。
第一个摘要:python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
Docker Hub 中的清单摘要作为参考。
摘要不可变。
如果两个不同的东西产生相同的摘要值 - 那么散列函数(在这种情况下使用的 sha256)将被破坏并且不能再使用。参见 collision.
在您的情况下,由于某种原因它不再找到缓存的图像。
它再次下载了相同的图像。
最后生成的摘要 (---> 114ae8bdb954
) 是该图像(图像 ID)的结果配置的摘要。
您可以确认下载了正确的清单:
docker inspect 114ae8bdb954
有包含:
"RepoDigests": [
"python@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11"
],
由于两种情况下的图片 ID 相同,我认为没有什么可以解决的。但是,如果它总是发生,则缓存存在一些问题。
关于缓存的编辑:如果这是在 docker-in-docker 场景中完成的 - 如果在父级 Docker 中构建阶段之前发生某些变化,它将始终再次重建此图像。
有关图片 ID 的更多信息:https://windsock.io/explaining-docker-image-ids/
鉴于这不会发生在每个 运行 上,如果您在本地测试也可能不会发生,问题似乎与您的 Docker 文件或 FROM 行无关. Docker 不会自动清除缓存,因此您需要调查哪些外部进程正在删除缓存。由于您 运行 使用 kubernetes 插件在 Jenkins 中构建,问题似乎是该插件在超时后清理构建代理。从文档中可以看到 various settings to tune this builder:
- podRetention Controls the behavior of keeping slave pods. Can be 'never()', 'onFailure()', 'always()', or 'default()' - if empty will
default to deleting the pod after
activeDeadlineSeconds
has passed.
- activeDeadlineSeconds If
podRetention
is set to 'never()' or 'onFailure()', pod is deleted after this deadline is passed.
- idleMinutes Allows the Pod to remain active for reuse until the configured number of minutes has passed since the last step was
executed on it.
解决临时构建代理的一种方法是在 docker build
命令中使用 --cache-from
选项。使用经典构建(相对于 buildkit),您需要先在本地拉取此图像。该图像将来自以前的构建,您可以将多个图像用于缓存,这对于多阶段构建特别有用,因为您需要为每个阶段提取缓存。这个标志告诉 docker 信任从注册表中提取的图像,因为通常只有本地构建的图像是可信的(有人可能会注入恶意图像的风险,该图像声称在流行图像中有 运行 个步骤,但包括该层的 tar 中的恶意软件)。
注意:有一个用于固定“来源”的 RFC:moby/buildkit
issue 2794, from Akihiro Suda(NTT 公司的软件工程师)。
它将介绍:
Dockerfile.sum is an equivalent of go.sum
but s/go/Dockerfile/
.
The content is a subset of BuildInfo:
{
"sources": [
{
"type": "docker-image",
"ref": "docker.io/library/alpine:latest",
"pin": "sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454"
},
{
"type": "http",
"ref": "https://raw.githubusercontent.com/moby/buildkit/v0.10.1/README.md",
"pin": "sha256:6e4b94fc270e708e1068be28bd3551dc6917a4fc5a61293d51bb36e6b75c4b53"
}
]
}
When `Dockerfile.sum` exists in the context, the Dockerfile builder does:
- Pinning the digest of docker-image sources (`FROM ...`)
- Pinning the digest of http sources (`ADD https://...`)
- Recording the consumed entries to the build info structure (`["containerimage.buildinfo"].consumedPin`)
In the future, Dockerfile should also support `ADD git://...` and pinning its commit hash.
这是向最终用户provide/show buildinfo
功能提供的一种方式,参与 Build reproducibility。
我的 Dockerfile
有第一步:
FROM python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
这样做的目标是to "lock" or "pin" the version of the image。
有一段时间,docker build
正确使用了缓存版本:
Step 1/2 : FROM python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
---> 114ae8bdb954
但过了一段时间,它决定 "download a newer image":
Step 1/2 : FROM python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11: Pulling from library/python
7e2b2a5af8f6: Pulling fs layer
09b6f03ffac4: Pulling fs layer
dc3f0c679f0f: Pulling fs layer
fd4b47407fc3: Pulling fs layer
bb7b28578995: Pulling fs layer
6ebea4a9a306: Pulling fs layer
22a2327cd1ca: Pulling fs layer
bfbf91c84bbe: Pulling fs layer
f6b29b259c5c: Pulling fs layer
09b6f03ffac4: Verifying Checksum
09b6f03ffac4: Download complete
dc3f0c679f0f: Download complete
7e2b2a5af8f6: Verifying Checksum
7e2b2a5af8f6: Download complete
6ebea4a9a306: Verifying Checksum
6ebea4a9a306: Download complete
fd4b47407fc3: Verifying Checksum
fd4b47407fc3: Download complete
bfbf91c84bbe: Verifying Checksum
bfbf91c84bbe: Download complete
f6b29b259c5c: Verifying Checksum
f6b29b259c5c: Download complete
22a2327cd1ca: Verifying Checksum
22a2327cd1ca: Download complete
bb7b28578995: Verifying Checksum
bb7b28578995: Download complete
7e2b2a5af8f6: Pull complete
09b6f03ffac4: Pull complete
dc3f0c679f0f: Pull complete
fd4b47407fc3: Pull complete
bb7b28578995: Pull complete
6ebea4a9a306: Pull complete
22a2327cd1ca: Pull complete
bfbf91c84bbe: Pull complete
f6b29b259c5c: Pull complete
Digest: sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
Status: Downloaded newer image for python@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
---> 114ae8bdb954
尽管这一步的最终哈希是相同的:
---> 114ae8bdb954
据我了解,摘要 (sha256:...
) 是不可变的。
那么它们到底是可变的吗?
还是缓存的版本以某种方式被删除了?
这是怎么回事,我该如何解决?
有两种摘要:注册表中镜像清单的摘要和JSON本地镜像配置的摘要,其中还包含镜像内容的摘要。
第一个摘要:python:3.6.10@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11
Docker Hub 中的清单摘要作为参考。
摘要不可变。
如果两个不同的东西产生相同的摘要值 - 那么散列函数(在这种情况下使用的 sha256)将被破坏并且不能再使用。参见 collision.
在您的情况下,由于某种原因它不再找到缓存的图像。 它再次下载了相同的图像。
最后生成的摘要 (---> 114ae8bdb954
) 是该图像(图像 ID)的结果配置的摘要。
您可以确认下载了正确的清单:
docker inspect 114ae8bdb954
有包含:
"RepoDigests": [
"python@sha256:6cd232ed00e729b4d4d3aa57c1764dddfab70f616042b7f36536e2c3d70c4c11"
],
由于两种情况下的图片 ID 相同,我认为没有什么可以解决的。但是,如果它总是发生,则缓存存在一些问题。
关于缓存的编辑:如果这是在 docker-in-docker 场景中完成的 - 如果在父级 Docker 中构建阶段之前发生某些变化,它将始终再次重建此图像。
有关图片 ID 的更多信息:https://windsock.io/explaining-docker-image-ids/
鉴于这不会发生在每个 运行 上,如果您在本地测试也可能不会发生,问题似乎与您的 Docker 文件或 FROM 行无关. Docker 不会自动清除缓存,因此您需要调查哪些外部进程正在删除缓存。由于您 运行 使用 kubernetes 插件在 Jenkins 中构建,问题似乎是该插件在超时后清理构建代理。从文档中可以看到 various settings to tune this builder:
- podRetention Controls the behavior of keeping slave pods. Can be 'never()', 'onFailure()', 'always()', or 'default()' - if empty will default to deleting the pod after
activeDeadlineSeconds
has passed.- activeDeadlineSeconds If
podRetention
is set to 'never()' or 'onFailure()', pod is deleted after this deadline is passed.- idleMinutes Allows the Pod to remain active for reuse until the configured number of minutes has passed since the last step was executed on it.
解决临时构建代理的一种方法是在 docker build
命令中使用 --cache-from
选项。使用经典构建(相对于 buildkit),您需要先在本地拉取此图像。该图像将来自以前的构建,您可以将多个图像用于缓存,这对于多阶段构建特别有用,因为您需要为每个阶段提取缓存。这个标志告诉 docker 信任从注册表中提取的图像,因为通常只有本地构建的图像是可信的(有人可能会注入恶意图像的风险,该图像声称在流行图像中有 运行 个步骤,但包括该层的 tar 中的恶意软件)。
注意:有一个用于固定“来源”的 RFC:moby/buildkit
issue 2794, from Akihiro Suda(NTT 公司的软件工程师)。
它将介绍:
Dockerfile.sum is an equivalent of
go.sum
buts/go/Dockerfile/
.The content is a subset of BuildInfo:
{ "sources": [ { "type": "docker-image", "ref": "docker.io/library/alpine:latest", "pin": "sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454" }, { "type": "http", "ref": "https://raw.githubusercontent.com/moby/buildkit/v0.10.1/README.md", "pin": "sha256:6e4b94fc270e708e1068be28bd3551dc6917a4fc5a61293d51bb36e6b75c4b53" } ] } When `Dockerfile.sum` exists in the context, the Dockerfile builder does: - Pinning the digest of docker-image sources (`FROM ...`) - Pinning the digest of http sources (`ADD https://...`) - Recording the consumed entries to the build info structure (`["containerimage.buildinfo"].consumedPin`) In the future, Dockerfile should also support `ADD git://...` and pinning its commit hash.
这是向最终用户provide/show buildinfo
功能提供的一种方式,参与 Build reproducibility。