-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] Docker pull/push to the same registry changes image digest #3394
Comments
@thaJeztah could I kindly ask you to help me with bug report review? |
What's the diff in the manifest? Could you do an inspect of the manifest on the first push and the second? docker buildx imagetools inspect --raw localhost:5000/test |
@thaJeztah formatting and field order. $ docker buildx imagetools inspect --raw localhost:5000/test > meta_registry.json diff meta_registry.json meta.json
1,16c1
< {
< "schemaVersion": 2,
< "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
< "config": {
< "mediaType": "application/vnd.docker.container.image.v1+json",
< "size": 358,
< "digest": "sha256:8a3b3ebf46ea72d4c4859e18147485204d7144e3e82dd5b6416b167af9f25a86"
< },
< "layers": [
< {
< "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
< "size": 229,
< "digest": "sha256:cf51c3f692e54f42033483875a084a5ff8ace3f69c2e44a8d29525fa4e07741c"
< }
< ]
< }
\ No newline at end of file
---
> {"image":"localhost:5000/test","imageId":"sha256:8a3b3ebf46ea72d4c4859e18147485204d7144e3e82dd5b6416b167af9f25a86","imageDigest":"sha256:40b9754190108932d81362bc2b845fb6176b20d5ac99312abf2a1f149309e39e","tags":["latest"]}
\ No newline at end of file
upd: $ jib-0.8.0/bin/jib build -c `pwd` -b build.yaml -t registry://localhost:5000/test --allow-insecure-registries --image-metadata-out=meta.json
$ docker pull localhost:5000/test
$ docker buildx imagetools inspect --raw localhost:5000/test > meta_registry_after_docker_pull.json
$ docker push localhost:5000/test
$ docker buildx imagetools inspect --raw localhost:5000/test > meta_registry_after_docker_push.json
$ diff meta_registry_after_docker_pull.json meta_registry_after_docker_push.json 1c1,16
< {"schemaVersion":2,"mediaType":"application/vnd.docker.distribution.manifest.v2+json","config":{"mediaType":"application/vnd.docker.container.image.v1+json","digest":"sha256:8a3b3ebf46ea72d4c4859e18147485204d7144e3e82dd5b6416b167af9f25a86","size":358},"layers":[{"mediaType":"application/vnd.docker.image.rootfs.diff.tar.gzip","digest":"sha256:cf51c3f692e54f42033483875a084a5ff8ace3f69c2e44a8d29525fa4e07741c","size":229}]}
\ No newline at end of file
---
> {
> "schemaVersion": 2,
> "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
> "config": {
> "mediaType": "application/vnd.docker.container.image.v1+json",
> "size": 358,
> "digest": "sha256:8a3b3ebf46ea72d4c4859e18147485204d7144e3e82dd5b6416b167af9f25a86"
> },
> "layers": [
> {
> "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
> "size": 229,
> "digest": "sha256:cf51c3f692e54f42033483875a084a5ff8ace3f69c2e44a8d29525fa4e07741c"
> }
> ]
> }
\ No newline at end of file |
@thaJeztah sorry for being buzzer. Could you please take a look into the case? |
Hmm.. right, so it looks like the manifest that was pushed got reformatted (pretty-print), instead of preserving the original without whitespace (probably that was generated with a library to create canonical JSON, as described in the image-spec (ISTR that was largely abandoned at some point, as canonical JSON was still open to too many variations. @justincormack @tonistiigi any ideas? |
@thaJeztah "manifest that was pushed got reformatted (pretty-print), instead of preserving the original without whitespace" exactly @justincormack @tonistiigi what do you think? |
The way push is implemented in dockerd atm always creates new manifests on push. Immutability is only guaranteed in the image config layer. For compressed layers, they are kept as is if they already exist in the registry, otherwise they are compressed into new blobs. |
@tonistiigi but dockerd overrides the same (logically, same entries, formatting and order changed) manifest. |
|
I run into the same issue. It prevents deterministic container images, to a certain degree. My plan was to compare the digest of the one image built on the CI, that was automatically pushed to the registry to one image built locally - and then, if they match, to use sign the image with cosign. My workaround for now is to print the digest on the CI too and then compare it with the local build, before adding the cosign. |
use the following, it will not change the image digest! |
there is no problem to push image to the sever. Jib do it without a problem and docker itself. Please don't list tools that can interact with docker registry (one can do it with |
There is no such thing as
|
Looks like this is a different |
This is still an issue. I don't understand that this doesn't bother more people. Even other CLIs have this problem like |
It's not possible with graphdrivers due to how they store layers. You can use the containerd image store to get consistent digests though. |
@vvoland nonsense, |
The digest of the image depends on the bytes of the image as a whole IMO. If you change anything, like reording keys in the mainfest.json for example, adding an additional tag or anything else, the digest of the image will change. I guess it is pretty hard to store the image to disk without altering anything within since it is not as simple as downloading a tar from a webserver. It is pulling the manifests and layers seperately and putting it all together afterwards to store it as tar. On the way are many things that might change based on the libraries used for unmarshalling or marshalling jsons or how the tar is built. |
The manifest is not stored at all, it's recreated at push. Also layers are stored in the uncompressed form, while the manifest references the digest of the compressed content. So there's still no guarantee that if you tar and compress the extracted layers they will actually have the same digest as the original content. |
True, I guess storing it as TAR is not what I want. :) |
that is exactly what I said, if manifest is changed than digest is changed
and it was 2nd sentence, if implementation doesn't align to contract, its buggy one and have to be fixed. |
There is no plan to fix the graphdriver backed image store at this time. If this matters for you, please enable the containerd image store in your docker daemon config. |
Small clarification on that one: they can be pushed, it's just that full image content is required locally (so you need to pull all the platform locally first), or in the remote registry repository (registry-dependent, but pushing to the same repository that the image was pulled from should still work). |
Description
Docker pull/push to the same registry changes image digest pushed by another tool. looks like docker reformats manifest the way it like.
The bug breaks
docker trust sign
process as digest is already used in other systems.Combined with session nature
docker login
makes it hurts any CI process badly, as onlydocker push
can be used for consistent pushing\signingDescribe the results you expected:
My understanding is that docker push\pull to the same repo have to leave docekr digest the same.
Steps to reproduce the issue:
./build.yaml
The docker imageDigest is changed
from: sha256:40b9754190108932d81362bc2b845fb6176b20d5ac99312abf2a1f149309e39e
to: sha256:340a8be0c6d5d9ec54e49f484a88a3a92290ad8ade703da654265cafa3c8e315
The text was updated successfully, but these errors were encountered: